diff --git a/bundle.js b/bundle.js new file mode 100644 index 0000000..db22b53 --- /dev/null +++ b/bundle.js @@ -0,0 +1,33339 @@ +var ArticleExtractor = (function (exports, fetch$2) { + 'use strict'; + + // utils / detection + + const ob2Str = (val) => { + return {}.toString.call(val) + }; + + const isArray$3 = (val) => { + return Array.isArray(val) + }; + + const isString$1 = (val) => { + return String(val) === val + }; + + const isNumber$1 = (val) => { + return Number(val) === val + }; + + const isFunction = (val) => { + return ob2Str(val) === '[object Function]' + }; + + const isObject$2 = (val) => { + return ob2Str(val) === '[object Object]' && !isArray$3(val) + }; + + const isDate = (val) => { + return val instanceof Date && !isNaN(val.valueOf()) + }; + + const hasProperty = (ob, k) => { + if (!ob || !k) { + return false + } + return Object.prototype.hasOwnProperty.call(ob, k) + }; + + // utils / string + + + const toString$2 = (input) => { + const s = isNumber$1(input) ? String(input) : input; + if (!isString$1(s)) { + throw new Error('InvalidInput: String required.') + } + return s + }; + + const truncate = (s, len = 140) => { + const txt = toString$2(s); + const txtlen = txt.length; + if (txtlen <= len) { + return txt + } + const subtxt = txt.substring(0, len).trim(); + const subtxtArr = subtxt.split(' '); + const subtxtLen = subtxtArr.length; + if (subtxtLen > 1) { + subtxtArr.pop(); + return subtxtArr.map(word => word.trim()).join(' ') + '...' + } + return subtxt.substring(0, len - 3) + '...' + }; + + const stripTags = (s) => { + return toString$2(s).replace(/(<([^>]+)>)/ig, '').trim() + }; + + // utils / pipe + + const pipe = (...fns) => { + return fns.reduce((f, g) => (x) => g(f(x))) + }; + + /** + * bellajs + * @ndaidong + **/ + + + const clone = (val, history = null) => { + const stack = history || new Set(); + + if (stack.has(val)) { + return val + } + + stack.add(val); + + if (isDate(val)) { + return new Date(val.valueOf()) + } + + const copyObject = (o) => { + const oo = Object.create({}); + for (const k in o) { + if (hasProperty(o, k)) { + oo[k] = clone(o[k], stack); + } + } + return oo + }; + + const copyArray = (a) => { + return [...a].map((e) => { + if (isArray$3(e)) { + return copyArray(e) + } else if (isObject$2(e)) { + return copyObject(e) + } + return clone(e, stack) + }) + }; + + if (isArray$3(val)) { + return copyArray(val) + } + + if (isObject$2(val)) { + return copyObject(val) + } + + return val + }; + + const unique = (arr = []) => { + return [...new Set(arr)] + }; + + // utils -> retrieve + + + const profetch = async (url, options = {}) => { + const { proxy = {}, signal = null } = options; + const { + target, + headers = {}, + } = proxy; + const res = await fetch$2(target + encodeURIComponent(url), { + headers, + signal, + }); + return res + }; + + var retrieve = async (url, options = {}) => { + const { + headers = { + 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0', + }, + proxy = null, + agent = null, + signal = null, + } = options; + + const res = proxy ? await profetch(url, { proxy, signal }) : await fetch$2(url, { headers, agent, signal }); + + const status = res.status; + if (status >= 400) { + throw new Error(`Request failed with error code ${status}`) + } + const buffer = await res.arrayBuffer(); + return buffer + }; + + // used in Attr to signal changes + const CHANGED = Symbol('changed'); + + // used in Element to setup once classList + const CLASS_LIST = Symbol('classList'); + + // used in Document to attach once customElements + const CUSTOM_ELEMENTS = Symbol('CustomElements'); + + // used in HTMLTemplateElement + const CONTENT = Symbol('content'); + + // used in Element for data attributes + const DATASET = Symbol('dataset'); + + // used in Document to attach the DocType + const DOCTYPE = Symbol('doctype'); + + // used in parser and Document to attach once a DOMParser + const DOM_PARSER = Symbol('DOMParser'); + + // used to reference an end node + const END = Symbol('end'); + + // used in Document to make the globalThis an event target + const EVENT_TARGET = Symbol('EventTarget'); + + // used to augment a created document defaultView + const GLOBALS = Symbol('globals'); + + // used in both Canvas and Document to provide images + const IMAGE = Symbol('image'); + + // used to define Document mime type + const MIME = Symbol('mime'); + + // used in Document to attach once MutationObserver + const MUTATION_OBSERVER = Symbol('MutationObserver'); + + // used to define next node reference + const NEXT = Symbol('next'); + + // used to define Attr owner elements + const OWNER_ELEMENT = Symbol('ownerElement'); + + // used to define previous node reference + const PREV = Symbol('prev'); + + // used to define various "private" properties + const PRIVATE = Symbol('private'); + + // used to define the CSSStyleSheet.sheet + const SHEET = Symbol('sheet'); + + // used to define start node reference + const START = Symbol('start'); + + // used to define special CSS style attribute + const STYLE = Symbol('style'); + + // used to upgrade Custom Elements + const UPGRADE = Symbol('upgrade'); + + // used to define generic values + const VALUE = Symbol('value'); + + // Generated using scripts/write-decode-map.ts + var htmlDecodeTree = new Uint16Array( + // prettier-ignore + "\u1d41<\xd5\u0131\u028a\u049d\u057b\u05d0\u0675\u06de\u07a2\u07d6\u080f\u0a4a\u0a91\u0da1\u0e6d\u0f09\u0f26\u10ca\u1228\u12e1\u1415\u149d\u14c3\u14df\u1525\0\0\0\0\0\0\u156b\u16cd\u198d\u1c12\u1ddd\u1f7e\u2060\u21b0\u228d\u23c0\u23fb\u2442\u2824\u2912\u2d08\u2e48\u2fce\u3016\u32ba\u3639\u37ac\u38fe\u3a28\u3a71\u3ae0\u3b2e\u0800EMabcfglmnoprstu\\bfms\x7f\x84\x8b\x90\x95\x98\xa6\xb3\xb9\xc8\xcflig\u803b\xc6\u40c6P\u803b&\u4026cute\u803b\xc1\u40c1reve;\u4102\u0100iyx}rc\u803b\xc2\u40c2;\u4410r;\uc000\ud835\udd04rave\u803b\xc0\u40c0pha;\u4391acr;\u4100d;\u6a53\u0100gp\x9d\xa1on;\u4104f;\uc000\ud835\udd38plyFunction;\u6061ing\u803b\xc5\u40c5\u0100cs\xbe\xc3r;\uc000\ud835\udc9cign;\u6254ilde\u803b\xc3\u40c3ml\u803b\xc4\u40c4\u0400aceforsu\xe5\xfb\xfe\u0117\u011c\u0122\u0127\u012a\u0100cr\xea\xf2kslash;\u6216\u0176\xf6\xf8;\u6ae7ed;\u6306y;\u4411\u0180crt\u0105\u010b\u0114ause;\u6235noullis;\u612ca;\u4392r;\uc000\ud835\udd05pf;\uc000\ud835\udd39eve;\u42d8c\xf2\u0113mpeq;\u624e\u0700HOacdefhilorsu\u014d\u0151\u0156\u0180\u019e\u01a2\u01b5\u01b7\u01ba\u01dc\u0215\u0273\u0278\u027ecy;\u4427PY\u803b\xa9\u40a9\u0180cpy\u015d\u0162\u017aute;\u4106\u0100;i\u0167\u0168\u62d2talDifferentialD;\u6145leys;\u612d\u0200aeio\u0189\u018e\u0194\u0198ron;\u410cdil\u803b\xc7\u40c7rc;\u4108nint;\u6230ot;\u410a\u0100dn\u01a7\u01adilla;\u40b8terDot;\u40b7\xf2\u017fi;\u43a7rcle\u0200DMPT\u01c7\u01cb\u01d1\u01d6ot;\u6299inus;\u6296lus;\u6295imes;\u6297o\u0100cs\u01e2\u01f8kwiseContourIntegral;\u6232eCurly\u0100DQ\u0203\u020foubleQuote;\u601duote;\u6019\u0200lnpu\u021e\u0228\u0247\u0255on\u0100;e\u0225\u0226\u6237;\u6a74\u0180git\u022f\u0236\u023aruent;\u6261nt;\u622fourIntegral;\u622e\u0100fr\u024c\u024e;\u6102oduct;\u6210nterClockwiseContourIntegral;\u6233oss;\u6a2fcr;\uc000\ud835\udc9ep\u0100;C\u0284\u0285\u62d3ap;\u624d\u0580DJSZacefios\u02a0\u02ac\u02b0\u02b4\u02b8\u02cb\u02d7\u02e1\u02e6\u0333\u048d\u0100;o\u0179\u02a5trahd;\u6911cy;\u4402cy;\u4405cy;\u440f\u0180grs\u02bf\u02c4\u02c7ger;\u6021r;\u61a1hv;\u6ae4\u0100ay\u02d0\u02d5ron;\u410e;\u4414l\u0100;t\u02dd\u02de\u6207a;\u4394r;\uc000\ud835\udd07\u0100af\u02eb\u0327\u0100cm\u02f0\u0322ritical\u0200ADGT\u0300\u0306\u0316\u031ccute;\u40b4o\u0174\u030b\u030d;\u42d9bleAcute;\u42ddrave;\u4060ilde;\u42dcond;\u62c4ferentialD;\u6146\u0470\u033d\0\0\0\u0342\u0354\0\u0405f;\uc000\ud835\udd3b\u0180;DE\u0348\u0349\u034d\u40a8ot;\u60dcqual;\u6250ble\u0300CDLRUV\u0363\u0372\u0382\u03cf\u03e2\u03f8ontourIntegra\xec\u0239o\u0274\u0379\0\0\u037b\xbb\u0349nArrow;\u61d3\u0100eo\u0387\u03a4ft\u0180ART\u0390\u0396\u03a1rrow;\u61d0ightArrow;\u61d4e\xe5\u02cang\u0100LR\u03ab\u03c4eft\u0100AR\u03b3\u03b9rrow;\u67f8ightArrow;\u67faightArrow;\u67f9ight\u0100AT\u03d8\u03derrow;\u61d2ee;\u62a8p\u0241\u03e9\0\0\u03efrrow;\u61d1ownArrow;\u61d5erticalBar;\u6225n\u0300ABLRTa\u0412\u042a\u0430\u045e\u047f\u037crrow\u0180;BU\u041d\u041e\u0422\u6193ar;\u6913pArrow;\u61f5reve;\u4311eft\u02d2\u043a\0\u0446\0\u0450ightVector;\u6950eeVector;\u695eector\u0100;B\u0459\u045a\u61bdar;\u6956ight\u01d4\u0467\0\u0471eeVector;\u695fector\u0100;B\u047a\u047b\u61c1ar;\u6957ee\u0100;A\u0486\u0487\u62a4rrow;\u61a7\u0100ct\u0492\u0497r;\uc000\ud835\udc9frok;\u4110\u0800NTacdfglmopqstux\u04bd\u04c0\u04c4\u04cb\u04de\u04e2\u04e7\u04ee\u04f5\u0521\u052f\u0536\u0552\u055d\u0560\u0565G;\u414aH\u803b\xd0\u40d0cute\u803b\xc9\u40c9\u0180aiy\u04d2\u04d7\u04dcron;\u411arc\u803b\xca\u40ca;\u442dot;\u4116r;\uc000\ud835\udd08rave\u803b\xc8\u40c8ement;\u6208\u0100ap\u04fa\u04fecr;\u4112ty\u0253\u0506\0\0\u0512mallSquare;\u65fberySmallSquare;\u65ab\u0100gp\u0526\u052aon;\u4118f;\uc000\ud835\udd3csilon;\u4395u\u0100ai\u053c\u0549l\u0100;T\u0542\u0543\u6a75ilde;\u6242librium;\u61cc\u0100ci\u0557\u055ar;\u6130m;\u6a73a;\u4397ml\u803b\xcb\u40cb\u0100ip\u056a\u056fsts;\u6203onentialE;\u6147\u0280cfios\u0585\u0588\u058d\u05b2\u05ccy;\u4424r;\uc000\ud835\udd09lled\u0253\u0597\0\0\u05a3mallSquare;\u65fcerySmallSquare;\u65aa\u0370\u05ba\0\u05bf\0\0\u05c4f;\uc000\ud835\udd3dAll;\u6200riertrf;\u6131c\xf2\u05cb\u0600JTabcdfgorst\u05e8\u05ec\u05ef\u05fa\u0600\u0612\u0616\u061b\u061d\u0623\u066c\u0672cy;\u4403\u803b>\u403emma\u0100;d\u05f7\u05f8\u4393;\u43dcreve;\u411e\u0180eiy\u0607\u060c\u0610dil;\u4122rc;\u411c;\u4413ot;\u4120r;\uc000\ud835\udd0a;\u62d9pf;\uc000\ud835\udd3eeater\u0300EFGLST\u0635\u0644\u064e\u0656\u065b\u0666qual\u0100;L\u063e\u063f\u6265ess;\u62dbullEqual;\u6267reater;\u6aa2ess;\u6277lantEqual;\u6a7eilde;\u6273cr;\uc000\ud835\udca2;\u626b\u0400Aacfiosu\u0685\u068b\u0696\u069b\u069e\u06aa\u06be\u06caRDcy;\u442a\u0100ct\u0690\u0694ek;\u42c7;\u405eirc;\u4124r;\u610clbertSpace;\u610b\u01f0\u06af\0\u06b2f;\u610dizontalLine;\u6500\u0100ct\u06c3\u06c5\xf2\u06a9rok;\u4126mp\u0144\u06d0\u06d8ownHum\xf0\u012fqual;\u624f\u0700EJOacdfgmnostu\u06fa\u06fe\u0703\u0707\u070e\u071a\u071e\u0721\u0728\u0744\u0778\u078b\u078f\u0795cy;\u4415lig;\u4132cy;\u4401cute\u803b\xcd\u40cd\u0100iy\u0713\u0718rc\u803b\xce\u40ce;\u4418ot;\u4130r;\u6111rave\u803b\xcc\u40cc\u0180;ap\u0720\u072f\u073f\u0100cg\u0734\u0737r;\u412ainaryI;\u6148lie\xf3\u03dd\u01f4\u0749\0\u0762\u0100;e\u074d\u074e\u622c\u0100gr\u0753\u0758ral;\u622bsection;\u62c2isible\u0100CT\u076c\u0772omma;\u6063imes;\u6062\u0180gpt\u077f\u0783\u0788on;\u412ef;\uc000\ud835\udd40a;\u4399cr;\u6110ilde;\u4128\u01eb\u079a\0\u079ecy;\u4406l\u803b\xcf\u40cf\u0280cfosu\u07ac\u07b7\u07bc\u07c2\u07d0\u0100iy\u07b1\u07b5rc;\u4134;\u4419r;\uc000\ud835\udd0dpf;\uc000\ud835\udd41\u01e3\u07c7\0\u07ccr;\uc000\ud835\udca5rcy;\u4408kcy;\u4404\u0380HJacfos\u07e4\u07e8\u07ec\u07f1\u07fd\u0802\u0808cy;\u4425cy;\u440cppa;\u439a\u0100ey\u07f6\u07fbdil;\u4136;\u441ar;\uc000\ud835\udd0epf;\uc000\ud835\udd42cr;\uc000\ud835\udca6\u0580JTaceflmost\u0825\u0829\u082c\u0850\u0863\u09b3\u09b8\u09c7\u09cd\u0a37\u0a47cy;\u4409\u803b<\u403c\u0280cmnpr\u0837\u083c\u0841\u0844\u084dute;\u4139bda;\u439bg;\u67ealacetrf;\u6112r;\u619e\u0180aey\u0857\u085c\u0861ron;\u413ddil;\u413b;\u441b\u0100fs\u0868\u0970t\u0500ACDFRTUVar\u087e\u08a9\u08b1\u08e0\u08e6\u08fc\u092f\u095b\u0390\u096a\u0100nr\u0883\u088fgleBracket;\u67e8row\u0180;BR\u0899\u089a\u089e\u6190ar;\u61e4ightArrow;\u61c6eiling;\u6308o\u01f5\u08b7\0\u08c3bleBracket;\u67e6n\u01d4\u08c8\0\u08d2eeVector;\u6961ector\u0100;B\u08db\u08dc\u61c3ar;\u6959loor;\u630aight\u0100AV\u08ef\u08f5rrow;\u6194ector;\u694e\u0100er\u0901\u0917e\u0180;AV\u0909\u090a\u0910\u62a3rrow;\u61a4ector;\u695aiangle\u0180;BE\u0924\u0925\u0929\u62b2ar;\u69cfqual;\u62b4p\u0180DTV\u0937\u0942\u094cownVector;\u6951eeVector;\u6960ector\u0100;B\u0956\u0957\u61bfar;\u6958ector\u0100;B\u0965\u0966\u61bcar;\u6952ight\xe1\u039cs\u0300EFGLST\u097e\u098b\u0995\u099d\u09a2\u09adqualGreater;\u62daullEqual;\u6266reater;\u6276ess;\u6aa1lantEqual;\u6a7dilde;\u6272r;\uc000\ud835\udd0f\u0100;e\u09bd\u09be\u62d8ftarrow;\u61daidot;\u413f\u0180npw\u09d4\u0a16\u0a1bg\u0200LRlr\u09de\u09f7\u0a02\u0a10eft\u0100AR\u09e6\u09ecrrow;\u67f5ightArrow;\u67f7ightArrow;\u67f6eft\u0100ar\u03b3\u0a0aight\xe1\u03bfight\xe1\u03caf;\uc000\ud835\udd43er\u0100LR\u0a22\u0a2ceftArrow;\u6199ightArrow;\u6198\u0180cht\u0a3e\u0a40\u0a42\xf2\u084c;\u61b0rok;\u4141;\u626a\u0400acefiosu\u0a5a\u0a5d\u0a60\u0a77\u0a7c\u0a85\u0a8b\u0a8ep;\u6905y;\u441c\u0100dl\u0a65\u0a6fiumSpace;\u605flintrf;\u6133r;\uc000\ud835\udd10nusPlus;\u6213pf;\uc000\ud835\udd44c\xf2\u0a76;\u439c\u0480Jacefostu\u0aa3\u0aa7\u0aad\u0ac0\u0b14\u0b19\u0d91\u0d97\u0d9ecy;\u440acute;\u4143\u0180aey\u0ab4\u0ab9\u0aberon;\u4147dil;\u4145;\u441d\u0180gsw\u0ac7\u0af0\u0b0eative\u0180MTV\u0ad3\u0adf\u0ae8ediumSpace;\u600bhi\u0100cn\u0ae6\u0ad8\xeb\u0ad9eryThi\xee\u0ad9ted\u0100GL\u0af8\u0b06reaterGreate\xf2\u0673essLes\xf3\u0a48Line;\u400ar;\uc000\ud835\udd11\u0200Bnpt\u0b22\u0b28\u0b37\u0b3areak;\u6060BreakingSpace;\u40a0f;\u6115\u0680;CDEGHLNPRSTV\u0b55\u0b56\u0b6a\u0b7c\u0ba1\u0beb\u0c04\u0c5e\u0c84\u0ca6\u0cd8\u0d61\u0d85\u6aec\u0100ou\u0b5b\u0b64ngruent;\u6262pCap;\u626doubleVerticalBar;\u6226\u0180lqx\u0b83\u0b8a\u0b9bement;\u6209ual\u0100;T\u0b92\u0b93\u6260ilde;\uc000\u2242\u0338ists;\u6204reater\u0380;EFGLST\u0bb6\u0bb7\u0bbd\u0bc9\u0bd3\u0bd8\u0be5\u626fqual;\u6271ullEqual;\uc000\u2267\u0338reater;\uc000\u226b\u0338ess;\u6279lantEqual;\uc000\u2a7e\u0338ilde;\u6275ump\u0144\u0bf2\u0bfdownHump;\uc000\u224e\u0338qual;\uc000\u224f\u0338e\u0100fs\u0c0a\u0c27tTriangle\u0180;BE\u0c1a\u0c1b\u0c21\u62eaar;\uc000\u29cf\u0338qual;\u62ecs\u0300;EGLST\u0c35\u0c36\u0c3c\u0c44\u0c4b\u0c58\u626equal;\u6270reater;\u6278ess;\uc000\u226a\u0338lantEqual;\uc000\u2a7d\u0338ilde;\u6274ested\u0100GL\u0c68\u0c79reaterGreater;\uc000\u2aa2\u0338essLess;\uc000\u2aa1\u0338recedes\u0180;ES\u0c92\u0c93\u0c9b\u6280qual;\uc000\u2aaf\u0338lantEqual;\u62e0\u0100ei\u0cab\u0cb9verseElement;\u620cghtTriangle\u0180;BE\u0ccb\u0ccc\u0cd2\u62ebar;\uc000\u29d0\u0338qual;\u62ed\u0100qu\u0cdd\u0d0cuareSu\u0100bp\u0ce8\u0cf9set\u0100;E\u0cf0\u0cf3\uc000\u228f\u0338qual;\u62e2erset\u0100;E\u0d03\u0d06\uc000\u2290\u0338qual;\u62e3\u0180bcp\u0d13\u0d24\u0d4eset\u0100;E\u0d1b\u0d1e\uc000\u2282\u20d2qual;\u6288ceeds\u0200;EST\u0d32\u0d33\u0d3b\u0d46\u6281qual;\uc000\u2ab0\u0338lantEqual;\u62e1ilde;\uc000\u227f\u0338erset\u0100;E\u0d58\u0d5b\uc000\u2283\u20d2qual;\u6289ilde\u0200;EFT\u0d6e\u0d6f\u0d75\u0d7f\u6241qual;\u6244ullEqual;\u6247ilde;\u6249erticalBar;\u6224cr;\uc000\ud835\udca9ilde\u803b\xd1\u40d1;\u439d\u0700Eacdfgmoprstuv\u0dbd\u0dc2\u0dc9\u0dd5\u0ddb\u0de0\u0de7\u0dfc\u0e02\u0e20\u0e22\u0e32\u0e3f\u0e44lig;\u4152cute\u803b\xd3\u40d3\u0100iy\u0dce\u0dd3rc\u803b\xd4\u40d4;\u441eblac;\u4150r;\uc000\ud835\udd12rave\u803b\xd2\u40d2\u0180aei\u0dee\u0df2\u0df6cr;\u414cga;\u43a9cron;\u439fpf;\uc000\ud835\udd46enCurly\u0100DQ\u0e0e\u0e1aoubleQuote;\u601cuote;\u6018;\u6a54\u0100cl\u0e27\u0e2cr;\uc000\ud835\udcaaash\u803b\xd8\u40d8i\u016c\u0e37\u0e3cde\u803b\xd5\u40d5es;\u6a37ml\u803b\xd6\u40d6er\u0100BP\u0e4b\u0e60\u0100ar\u0e50\u0e53r;\u603eac\u0100ek\u0e5a\u0e5c;\u63deet;\u63b4arenthesis;\u63dc\u0480acfhilors\u0e7f\u0e87\u0e8a\u0e8f\u0e92\u0e94\u0e9d\u0eb0\u0efcrtialD;\u6202y;\u441fr;\uc000\ud835\udd13i;\u43a6;\u43a0usMinus;\u40b1\u0100ip\u0ea2\u0eadncareplan\xe5\u069df;\u6119\u0200;eio\u0eb9\u0eba\u0ee0\u0ee4\u6abbcedes\u0200;EST\u0ec8\u0ec9\u0ecf\u0eda\u627aqual;\u6aaflantEqual;\u627cilde;\u627eme;\u6033\u0100dp\u0ee9\u0eeeuct;\u620fortion\u0100;a\u0225\u0ef9l;\u621d\u0100ci\u0f01\u0f06r;\uc000\ud835\udcab;\u43a8\u0200Ufos\u0f11\u0f16\u0f1b\u0f1fOT\u803b\"\u4022r;\uc000\ud835\udd14pf;\u611acr;\uc000\ud835\udcac\u0600BEacefhiorsu\u0f3e\u0f43\u0f47\u0f60\u0f73\u0fa7\u0faa\u0fad\u1096\u10a9\u10b4\u10bearr;\u6910G\u803b\xae\u40ae\u0180cnr\u0f4e\u0f53\u0f56ute;\u4154g;\u67ebr\u0100;t\u0f5c\u0f5d\u61a0l;\u6916\u0180aey\u0f67\u0f6c\u0f71ron;\u4158dil;\u4156;\u4420\u0100;v\u0f78\u0f79\u611cerse\u0100EU\u0f82\u0f99\u0100lq\u0f87\u0f8eement;\u620builibrium;\u61cbpEquilibrium;\u696fr\xbb\u0f79o;\u43a1ght\u0400ACDFTUVa\u0fc1\u0feb\u0ff3\u1022\u1028\u105b\u1087\u03d8\u0100nr\u0fc6\u0fd2gleBracket;\u67e9row\u0180;BL\u0fdc\u0fdd\u0fe1\u6192ar;\u61e5eftArrow;\u61c4eiling;\u6309o\u01f5\u0ff9\0\u1005bleBracket;\u67e7n\u01d4\u100a\0\u1014eeVector;\u695dector\u0100;B\u101d\u101e\u61c2ar;\u6955loor;\u630b\u0100er\u102d\u1043e\u0180;AV\u1035\u1036\u103c\u62a2rrow;\u61a6ector;\u695biangle\u0180;BE\u1050\u1051\u1055\u62b3ar;\u69d0qual;\u62b5p\u0180DTV\u1063\u106e\u1078ownVector;\u694feeVector;\u695cector\u0100;B\u1082\u1083\u61bear;\u6954ector\u0100;B\u1091\u1092\u61c0ar;\u6953\u0100pu\u109b\u109ef;\u611dndImplies;\u6970ightarrow;\u61db\u0100ch\u10b9\u10bcr;\u611b;\u61b1leDelayed;\u69f4\u0680HOacfhimoqstu\u10e4\u10f1\u10f7\u10fd\u1119\u111e\u1151\u1156\u1161\u1167\u11b5\u11bb\u11bf\u0100Cc\u10e9\u10eeHcy;\u4429y;\u4428FTcy;\u442ccute;\u415a\u0280;aeiy\u1108\u1109\u110e\u1113\u1117\u6abcron;\u4160dil;\u415erc;\u415c;\u4421r;\uc000\ud835\udd16ort\u0200DLRU\u112a\u1134\u113e\u1149ownArrow\xbb\u041eeftArrow\xbb\u089aightArrow\xbb\u0fddpArrow;\u6191gma;\u43a3allCircle;\u6218pf;\uc000\ud835\udd4a\u0272\u116d\0\0\u1170t;\u621aare\u0200;ISU\u117b\u117c\u1189\u11af\u65a1ntersection;\u6293u\u0100bp\u118f\u119eset\u0100;E\u1197\u1198\u628fqual;\u6291erset\u0100;E\u11a8\u11a9\u6290qual;\u6292nion;\u6294cr;\uc000\ud835\udcaear;\u62c6\u0200bcmp\u11c8\u11db\u1209\u120b\u0100;s\u11cd\u11ce\u62d0et\u0100;E\u11cd\u11d5qual;\u6286\u0100ch\u11e0\u1205eeds\u0200;EST\u11ed\u11ee\u11f4\u11ff\u627bqual;\u6ab0lantEqual;\u627dilde;\u627fTh\xe1\u0f8c;\u6211\u0180;es\u1212\u1213\u1223\u62d1rset\u0100;E\u121c\u121d\u6283qual;\u6287et\xbb\u1213\u0580HRSacfhiors\u123e\u1244\u1249\u1255\u125e\u1271\u1276\u129f\u12c2\u12c8\u12d1ORN\u803b\xde\u40deADE;\u6122\u0100Hc\u124e\u1252cy;\u440by;\u4426\u0100bu\u125a\u125c;\u4009;\u43a4\u0180aey\u1265\u126a\u126fron;\u4164dil;\u4162;\u4422r;\uc000\ud835\udd17\u0100ei\u127b\u1289\u01f2\u1280\0\u1287efore;\u6234a;\u4398\u0100cn\u128e\u1298kSpace;\uc000\u205f\u200aSpace;\u6009lde\u0200;EFT\u12ab\u12ac\u12b2\u12bc\u623cqual;\u6243ullEqual;\u6245ilde;\u6248pf;\uc000\ud835\udd4bipleDot;\u60db\u0100ct\u12d6\u12dbr;\uc000\ud835\udcafrok;\u4166\u0ae1\u12f7\u130e\u131a\u1326\0\u132c\u1331\0\0\0\0\0\u1338\u133d\u1377\u1385\0\u13ff\u1404\u140a\u1410\u0100cr\u12fb\u1301ute\u803b\xda\u40dar\u0100;o\u1307\u1308\u619fcir;\u6949r\u01e3\u1313\0\u1316y;\u440eve;\u416c\u0100iy\u131e\u1323rc\u803b\xdb\u40db;\u4423blac;\u4170r;\uc000\ud835\udd18rave\u803b\xd9\u40d9acr;\u416a\u0100di\u1341\u1369er\u0100BP\u1348\u135d\u0100ar\u134d\u1350r;\u405fac\u0100ek\u1357\u1359;\u63dfet;\u63b5arenthesis;\u63ddon\u0100;P\u1370\u1371\u62c3lus;\u628e\u0100gp\u137b\u137fon;\u4172f;\uc000\ud835\udd4c\u0400ADETadps\u1395\u13ae\u13b8\u13c4\u03e8\u13d2\u13d7\u13f3rrow\u0180;BD\u1150\u13a0\u13a4ar;\u6912ownArrow;\u61c5ownArrow;\u6195quilibrium;\u696eee\u0100;A\u13cb\u13cc\u62a5rrow;\u61a5own\xe1\u03f3er\u0100LR\u13de\u13e8eftArrow;\u6196ightArrow;\u6197i\u0100;l\u13f9\u13fa\u43d2on;\u43a5ing;\u416ecr;\uc000\ud835\udcb0ilde;\u4168ml\u803b\xdc\u40dc\u0480Dbcdefosv\u1427\u142c\u1430\u1433\u143e\u1485\u148a\u1490\u1496ash;\u62abar;\u6aeby;\u4412ash\u0100;l\u143b\u143c\u62a9;\u6ae6\u0100er\u1443\u1445;\u62c1\u0180bty\u144c\u1450\u147aar;\u6016\u0100;i\u144f\u1455cal\u0200BLST\u1461\u1465\u146a\u1474ar;\u6223ine;\u407ceparator;\u6758ilde;\u6240ThinSpace;\u600ar;\uc000\ud835\udd19pf;\uc000\ud835\udd4dcr;\uc000\ud835\udcb1dash;\u62aa\u0280cefos\u14a7\u14ac\u14b1\u14b6\u14bcirc;\u4174dge;\u62c0r;\uc000\ud835\udd1apf;\uc000\ud835\udd4ecr;\uc000\ud835\udcb2\u0200fios\u14cb\u14d0\u14d2\u14d8r;\uc000\ud835\udd1b;\u439epf;\uc000\ud835\udd4fcr;\uc000\ud835\udcb3\u0480AIUacfosu\u14f1\u14f5\u14f9\u14fd\u1504\u150f\u1514\u151a\u1520cy;\u442fcy;\u4407cy;\u442ecute\u803b\xdd\u40dd\u0100iy\u1509\u150drc;\u4176;\u442br;\uc000\ud835\udd1cpf;\uc000\ud835\udd50cr;\uc000\ud835\udcb4ml;\u4178\u0400Hacdefos\u1535\u1539\u153f\u154b\u154f\u155d\u1560\u1564cy;\u4416cute;\u4179\u0100ay\u1544\u1549ron;\u417d;\u4417ot;\u417b\u01f2\u1554\0\u155boWidt\xe8\u0ad9a;\u4396r;\u6128pf;\u6124cr;\uc000\ud835\udcb5\u0be1\u1583\u158a\u1590\0\u15b0\u15b6\u15bf\0\0\0\0\u15c6\u15db\u15eb\u165f\u166d\0\u1695\u169b\u16b2\u16b9\0\u16becute\u803b\xe1\u40e1reve;\u4103\u0300;Ediuy\u159c\u159d\u15a1\u15a3\u15a8\u15ad\u623e;\uc000\u223e\u0333;\u623frc\u803b\xe2\u40e2te\u80bb\xb4\u0306;\u4430lig\u803b\xe6\u40e6\u0100;r\xb2\u15ba;\uc000\ud835\udd1erave\u803b\xe0\u40e0\u0100ep\u15ca\u15d6\u0100fp\u15cf\u15d4sym;\u6135\xe8\u15d3ha;\u43b1\u0100ap\u15dfc\u0100cl\u15e4\u15e7r;\u4101g;\u6a3f\u0264\u15f0\0\0\u160a\u0280;adsv\u15fa\u15fb\u15ff\u1601\u1607\u6227nd;\u6a55;\u6a5clope;\u6a58;\u6a5a\u0380;elmrsz\u1618\u1619\u161b\u161e\u163f\u164f\u1659\u6220;\u69a4e\xbb\u1619sd\u0100;a\u1625\u1626\u6221\u0461\u1630\u1632\u1634\u1636\u1638\u163a\u163c\u163e;\u69a8;\u69a9;\u69aa;\u69ab;\u69ac;\u69ad;\u69ae;\u69aft\u0100;v\u1645\u1646\u621fb\u0100;d\u164c\u164d\u62be;\u699d\u0100pt\u1654\u1657h;\u6222\xbb\xb9arr;\u637c\u0100gp\u1663\u1667on;\u4105f;\uc000\ud835\udd52\u0380;Eaeiop\u12c1\u167b\u167d\u1682\u1684\u1687\u168a;\u6a70cir;\u6a6f;\u624ad;\u624bs;\u4027rox\u0100;e\u12c1\u1692\xf1\u1683ing\u803b\xe5\u40e5\u0180cty\u16a1\u16a6\u16a8r;\uc000\ud835\udcb6;\u402amp\u0100;e\u12c1\u16af\xf1\u0288ilde\u803b\xe3\u40e3ml\u803b\xe4\u40e4\u0100ci\u16c2\u16c8onin\xf4\u0272nt;\u6a11\u0800Nabcdefiklnoprsu\u16ed\u16f1\u1730\u173c\u1743\u1748\u1778\u177d\u17e0\u17e6\u1839\u1850\u170d\u193d\u1948\u1970ot;\u6aed\u0100cr\u16f6\u171ek\u0200ceps\u1700\u1705\u170d\u1713ong;\u624cpsilon;\u43f6rime;\u6035im\u0100;e\u171a\u171b\u623dq;\u62cd\u0176\u1722\u1726ee;\u62bded\u0100;g\u172c\u172d\u6305e\xbb\u172drk\u0100;t\u135c\u1737brk;\u63b6\u0100oy\u1701\u1741;\u4431quo;\u601e\u0280cmprt\u1753\u175b\u1761\u1764\u1768aus\u0100;e\u010a\u0109ptyv;\u69b0s\xe9\u170cno\xf5\u0113\u0180ahw\u176f\u1771\u1773;\u43b2;\u6136een;\u626cr;\uc000\ud835\udd1fg\u0380costuvw\u178d\u179d\u17b3\u17c1\u17d5\u17db\u17de\u0180aiu\u1794\u1796\u179a\xf0\u0760rc;\u65efp\xbb\u1371\u0180dpt\u17a4\u17a8\u17adot;\u6a00lus;\u6a01imes;\u6a02\u0271\u17b9\0\0\u17becup;\u6a06ar;\u6605riangle\u0100du\u17cd\u17d2own;\u65bdp;\u65b3plus;\u6a04e\xe5\u1444\xe5\u14adarow;\u690d\u0180ako\u17ed\u1826\u1835\u0100cn\u17f2\u1823k\u0180lst\u17fa\u05ab\u1802ozenge;\u69ebriangle\u0200;dlr\u1812\u1813\u1818\u181d\u65b4own;\u65beeft;\u65c2ight;\u65b8k;\u6423\u01b1\u182b\0\u1833\u01b2\u182f\0\u1831;\u6592;\u65914;\u6593ck;\u6588\u0100eo\u183e\u184d\u0100;q\u1843\u1846\uc000=\u20e5uiv;\uc000\u2261\u20e5t;\u6310\u0200ptwx\u1859\u185e\u1867\u186cf;\uc000\ud835\udd53\u0100;t\u13cb\u1863om\xbb\u13cctie;\u62c8\u0600DHUVbdhmptuv\u1885\u1896\u18aa\u18bb\u18d7\u18db\u18ec\u18ff\u1905\u190a\u1910\u1921\u0200LRlr\u188e\u1890\u1892\u1894;\u6557;\u6554;\u6556;\u6553\u0280;DUdu\u18a1\u18a2\u18a4\u18a6\u18a8\u6550;\u6566;\u6569;\u6564;\u6567\u0200LRlr\u18b3\u18b5\u18b7\u18b9;\u655d;\u655a;\u655c;\u6559\u0380;HLRhlr\u18ca\u18cb\u18cd\u18cf\u18d1\u18d3\u18d5\u6551;\u656c;\u6563;\u6560;\u656b;\u6562;\u655fox;\u69c9\u0200LRlr\u18e4\u18e6\u18e8\u18ea;\u6555;\u6552;\u6510;\u650c\u0280;DUdu\u06bd\u18f7\u18f9\u18fb\u18fd;\u6565;\u6568;\u652c;\u6534inus;\u629flus;\u629eimes;\u62a0\u0200LRlr\u1919\u191b\u191d\u191f;\u655b;\u6558;\u6518;\u6514\u0380;HLRhlr\u1930\u1931\u1933\u1935\u1937\u1939\u193b\u6502;\u656a;\u6561;\u655e;\u653c;\u6524;\u651c\u0100ev\u0123\u1942bar\u803b\xa6\u40a6\u0200ceio\u1951\u1956\u195a\u1960r;\uc000\ud835\udcb7mi;\u604fm\u0100;e\u171a\u171cl\u0180;bh\u1968\u1969\u196b\u405c;\u69c5sub;\u67c8\u016c\u1974\u197el\u0100;e\u1979\u197a\u6022t\xbb\u197ap\u0180;Ee\u012f\u1985\u1987;\u6aae\u0100;q\u06dc\u06db\u0ce1\u19a7\0\u19e8\u1a11\u1a15\u1a32\0\u1a37\u1a50\0\0\u1ab4\0\0\u1ac1\0\0\u1b21\u1b2e\u1b4d\u1b52\0\u1bfd\0\u1c0c\u0180cpr\u19ad\u19b2\u19ddute;\u4107\u0300;abcds\u19bf\u19c0\u19c4\u19ca\u19d5\u19d9\u6229nd;\u6a44rcup;\u6a49\u0100au\u19cf\u19d2p;\u6a4bp;\u6a47ot;\u6a40;\uc000\u2229\ufe00\u0100eo\u19e2\u19e5t;\u6041\xee\u0693\u0200aeiu\u19f0\u19fb\u1a01\u1a05\u01f0\u19f5\0\u19f8s;\u6a4don;\u410ddil\u803b\xe7\u40e7rc;\u4109ps\u0100;s\u1a0c\u1a0d\u6a4cm;\u6a50ot;\u410b\u0180dmn\u1a1b\u1a20\u1a26il\u80bb\xb8\u01adptyv;\u69b2t\u8100\xa2;e\u1a2d\u1a2e\u40a2r\xe4\u01b2r;\uc000\ud835\udd20\u0180cei\u1a3d\u1a40\u1a4dy;\u4447ck\u0100;m\u1a47\u1a48\u6713ark\xbb\u1a48;\u43c7r\u0380;Ecefms\u1a5f\u1a60\u1a62\u1a6b\u1aa4\u1aaa\u1aae\u65cb;\u69c3\u0180;el\u1a69\u1a6a\u1a6d\u42c6q;\u6257e\u0261\u1a74\0\0\u1a88rrow\u0100lr\u1a7c\u1a81eft;\u61baight;\u61bb\u0280RSacd\u1a92\u1a94\u1a96\u1a9a\u1a9f\xbb\u0f47;\u64c8st;\u629birc;\u629aash;\u629dnint;\u6a10id;\u6aefcir;\u69c2ubs\u0100;u\u1abb\u1abc\u6663it\xbb\u1abc\u02ec\u1ac7\u1ad4\u1afa\0\u1b0aon\u0100;e\u1acd\u1ace\u403a\u0100;q\xc7\xc6\u026d\u1ad9\0\0\u1ae2a\u0100;t\u1ade\u1adf\u402c;\u4040\u0180;fl\u1ae8\u1ae9\u1aeb\u6201\xee\u1160e\u0100mx\u1af1\u1af6ent\xbb\u1ae9e\xf3\u024d\u01e7\u1afe\0\u1b07\u0100;d\u12bb\u1b02ot;\u6a6dn\xf4\u0246\u0180fry\u1b10\u1b14\u1b17;\uc000\ud835\udd54o\xe4\u0254\u8100\xa9;s\u0155\u1b1dr;\u6117\u0100ao\u1b25\u1b29rr;\u61b5ss;\u6717\u0100cu\u1b32\u1b37r;\uc000\ud835\udcb8\u0100bp\u1b3c\u1b44\u0100;e\u1b41\u1b42\u6acf;\u6ad1\u0100;e\u1b49\u1b4a\u6ad0;\u6ad2dot;\u62ef\u0380delprvw\u1b60\u1b6c\u1b77\u1b82\u1bac\u1bd4\u1bf9arr\u0100lr\u1b68\u1b6a;\u6938;\u6935\u0270\u1b72\0\0\u1b75r;\u62dec;\u62dfarr\u0100;p\u1b7f\u1b80\u61b6;\u693d\u0300;bcdos\u1b8f\u1b90\u1b96\u1ba1\u1ba5\u1ba8\u622arcap;\u6a48\u0100au\u1b9b\u1b9ep;\u6a46p;\u6a4aot;\u628dr;\u6a45;\uc000\u222a\ufe00\u0200alrv\u1bb5\u1bbf\u1bde\u1be3rr\u0100;m\u1bbc\u1bbd\u61b7;\u693cy\u0180evw\u1bc7\u1bd4\u1bd8q\u0270\u1bce\0\0\u1bd2re\xe3\u1b73u\xe3\u1b75ee;\u62ceedge;\u62cfen\u803b\xa4\u40a4earrow\u0100lr\u1bee\u1bf3eft\xbb\u1b80ight\xbb\u1bbde\xe4\u1bdd\u0100ci\u1c01\u1c07onin\xf4\u01f7nt;\u6231lcty;\u632d\u0980AHabcdefhijlorstuwz\u1c38\u1c3b\u1c3f\u1c5d\u1c69\u1c75\u1c8a\u1c9e\u1cac\u1cb7\u1cfb\u1cff\u1d0d\u1d7b\u1d91\u1dab\u1dbb\u1dc6\u1dcdr\xf2\u0381ar;\u6965\u0200glrs\u1c48\u1c4d\u1c52\u1c54ger;\u6020eth;\u6138\xf2\u1133h\u0100;v\u1c5a\u1c5b\u6010\xbb\u090a\u016b\u1c61\u1c67arow;\u690fa\xe3\u0315\u0100ay\u1c6e\u1c73ron;\u410f;\u4434\u0180;ao\u0332\u1c7c\u1c84\u0100gr\u02bf\u1c81r;\u61catseq;\u6a77\u0180glm\u1c91\u1c94\u1c98\u803b\xb0\u40b0ta;\u43b4ptyv;\u69b1\u0100ir\u1ca3\u1ca8sht;\u697f;\uc000\ud835\udd21ar\u0100lr\u1cb3\u1cb5\xbb\u08dc\xbb\u101e\u0280aegsv\u1cc2\u0378\u1cd6\u1cdc\u1ce0m\u0180;os\u0326\u1cca\u1cd4nd\u0100;s\u0326\u1cd1uit;\u6666amma;\u43ddin;\u62f2\u0180;io\u1ce7\u1ce8\u1cf8\u40f7de\u8100\xf7;o\u1ce7\u1cf0ntimes;\u62c7n\xf8\u1cf7cy;\u4452c\u026f\u1d06\0\0\u1d0arn;\u631eop;\u630d\u0280lptuw\u1d18\u1d1d\u1d22\u1d49\u1d55lar;\u4024f;\uc000\ud835\udd55\u0280;emps\u030b\u1d2d\u1d37\u1d3d\u1d42q\u0100;d\u0352\u1d33ot;\u6251inus;\u6238lus;\u6214quare;\u62a1blebarwedg\xe5\xfan\u0180adh\u112e\u1d5d\u1d67ownarrow\xf3\u1c83arpoon\u0100lr\u1d72\u1d76ef\xf4\u1cb4igh\xf4\u1cb6\u0162\u1d7f\u1d85karo\xf7\u0f42\u026f\u1d8a\0\0\u1d8ern;\u631fop;\u630c\u0180cot\u1d98\u1da3\u1da6\u0100ry\u1d9d\u1da1;\uc000\ud835\udcb9;\u4455l;\u69f6rok;\u4111\u0100dr\u1db0\u1db4ot;\u62f1i\u0100;f\u1dba\u1816\u65bf\u0100ah\u1dc0\u1dc3r\xf2\u0429a\xf2\u0fa6angle;\u69a6\u0100ci\u1dd2\u1dd5y;\u445fgrarr;\u67ff\u0900Dacdefglmnopqrstux\u1e01\u1e09\u1e19\u1e38\u0578\u1e3c\u1e49\u1e61\u1e7e\u1ea5\u1eaf\u1ebd\u1ee1\u1f2a\u1f37\u1f44\u1f4e\u1f5a\u0100Do\u1e06\u1d34o\xf4\u1c89\u0100cs\u1e0e\u1e14ute\u803b\xe9\u40e9ter;\u6a6e\u0200aioy\u1e22\u1e27\u1e31\u1e36ron;\u411br\u0100;c\u1e2d\u1e2e\u6256\u803b\xea\u40ealon;\u6255;\u444dot;\u4117\u0100Dr\u1e41\u1e45ot;\u6252;\uc000\ud835\udd22\u0180;rs\u1e50\u1e51\u1e57\u6a9aave\u803b\xe8\u40e8\u0100;d\u1e5c\u1e5d\u6a96ot;\u6a98\u0200;ils\u1e6a\u1e6b\u1e72\u1e74\u6a99nters;\u63e7;\u6113\u0100;d\u1e79\u1e7a\u6a95ot;\u6a97\u0180aps\u1e85\u1e89\u1e97cr;\u4113ty\u0180;sv\u1e92\u1e93\u1e95\u6205et\xbb\u1e93p\u01001;\u1e9d\u1ea4\u0133\u1ea1\u1ea3;\u6004;\u6005\u6003\u0100gs\u1eaa\u1eac;\u414bp;\u6002\u0100gp\u1eb4\u1eb8on;\u4119f;\uc000\ud835\udd56\u0180als\u1ec4\u1ece\u1ed2r\u0100;s\u1eca\u1ecb\u62d5l;\u69e3us;\u6a71i\u0180;lv\u1eda\u1edb\u1edf\u43b5on\xbb\u1edb;\u43f5\u0200csuv\u1eea\u1ef3\u1f0b\u1f23\u0100io\u1eef\u1e31rc\xbb\u1e2e\u0269\u1ef9\0\0\u1efb\xed\u0548ant\u0100gl\u1f02\u1f06tr\xbb\u1e5dess\xbb\u1e7a\u0180aei\u1f12\u1f16\u1f1als;\u403dst;\u625fv\u0100;D\u0235\u1f20D;\u6a78parsl;\u69e5\u0100Da\u1f2f\u1f33ot;\u6253rr;\u6971\u0180cdi\u1f3e\u1f41\u1ef8r;\u612fo\xf4\u0352\u0100ah\u1f49\u1f4b;\u43b7\u803b\xf0\u40f0\u0100mr\u1f53\u1f57l\u803b\xeb\u40ebo;\u60ac\u0180cip\u1f61\u1f64\u1f67l;\u4021s\xf4\u056e\u0100eo\u1f6c\u1f74ctatio\xee\u0559nential\xe5\u0579\u09e1\u1f92\0\u1f9e\0\u1fa1\u1fa7\0\0\u1fc6\u1fcc\0\u1fd3\0\u1fe6\u1fea\u2000\0\u2008\u205allingdotse\xf1\u1e44y;\u4444male;\u6640\u0180ilr\u1fad\u1fb3\u1fc1lig;\u8000\ufb03\u0269\u1fb9\0\0\u1fbdg;\u8000\ufb00ig;\u8000\ufb04;\uc000\ud835\udd23lig;\u8000\ufb01lig;\uc000fj\u0180alt\u1fd9\u1fdc\u1fe1t;\u666dig;\u8000\ufb02ns;\u65b1of;\u4192\u01f0\u1fee\0\u1ff3f;\uc000\ud835\udd57\u0100ak\u05bf\u1ff7\u0100;v\u1ffc\u1ffd\u62d4;\u6ad9artint;\u6a0d\u0100ao\u200c\u2055\u0100cs\u2011\u2052\u03b1\u201a\u2030\u2038\u2045\u2048\0\u2050\u03b2\u2022\u2025\u2027\u202a\u202c\0\u202e\u803b\xbd\u40bd;\u6153\u803b\xbc\u40bc;\u6155;\u6159;\u615b\u01b3\u2034\0\u2036;\u6154;\u6156\u02b4\u203e\u2041\0\0\u2043\u803b\xbe\u40be;\u6157;\u615c5;\u6158\u01b6\u204c\0\u204e;\u615a;\u615d8;\u615el;\u6044wn;\u6322cr;\uc000\ud835\udcbb\u0880Eabcdefgijlnorstv\u2082\u2089\u209f\u20a5\u20b0\u20b4\u20f0\u20f5\u20fa\u20ff\u2103\u2112\u2138\u0317\u213e\u2152\u219e\u0100;l\u064d\u2087;\u6a8c\u0180cmp\u2090\u2095\u209dute;\u41f5ma\u0100;d\u209c\u1cda\u43b3;\u6a86reve;\u411f\u0100iy\u20aa\u20aerc;\u411d;\u4433ot;\u4121\u0200;lqs\u063e\u0642\u20bd\u20c9\u0180;qs\u063e\u064c\u20c4lan\xf4\u0665\u0200;cdl\u0665\u20d2\u20d5\u20e5c;\u6aa9ot\u0100;o\u20dc\u20dd\u6a80\u0100;l\u20e2\u20e3\u6a82;\u6a84\u0100;e\u20ea\u20ed\uc000\u22db\ufe00s;\u6a94r;\uc000\ud835\udd24\u0100;g\u0673\u061bmel;\u6137cy;\u4453\u0200;Eaj\u065a\u210c\u210e\u2110;\u6a92;\u6aa5;\u6aa4\u0200Eaes\u211b\u211d\u2129\u2134;\u6269p\u0100;p\u2123\u2124\u6a8arox\xbb\u2124\u0100;q\u212e\u212f\u6a88\u0100;q\u212e\u211bim;\u62e7pf;\uc000\ud835\udd58\u0100ci\u2143\u2146r;\u610am\u0180;el\u066b\u214e\u2150;\u6a8e;\u6a90\u8300>;cdlqr\u05ee\u2160\u216a\u216e\u2173\u2179\u0100ci\u2165\u2167;\u6aa7r;\u6a7aot;\u62d7Par;\u6995uest;\u6a7c\u0280adels\u2184\u216a\u2190\u0656\u219b\u01f0\u2189\0\u218epro\xf8\u209er;\u6978q\u0100lq\u063f\u2196les\xf3\u2088i\xed\u066b\u0100en\u21a3\u21adrtneqq;\uc000\u2269\ufe00\xc5\u21aa\u0500Aabcefkosy\u21c4\u21c7\u21f1\u21f5\u21fa\u2218\u221d\u222f\u2268\u227dr\xf2\u03a0\u0200ilmr\u21d0\u21d4\u21d7\u21dbrs\xf0\u1484f\xbb\u2024il\xf4\u06a9\u0100dr\u21e0\u21e4cy;\u444a\u0180;cw\u08f4\u21eb\u21efir;\u6948;\u61adar;\u610firc;\u4125\u0180alr\u2201\u220e\u2213rts\u0100;u\u2209\u220a\u6665it\xbb\u220alip;\u6026con;\u62b9r;\uc000\ud835\udd25s\u0100ew\u2223\u2229arow;\u6925arow;\u6926\u0280amopr\u223a\u223e\u2243\u225e\u2263rr;\u61fftht;\u623bk\u0100lr\u2249\u2253eftarrow;\u61a9ightarrow;\u61aaf;\uc000\ud835\udd59bar;\u6015\u0180clt\u226f\u2274\u2278r;\uc000\ud835\udcbdas\xe8\u21f4rok;\u4127\u0100bp\u2282\u2287ull;\u6043hen\xbb\u1c5b\u0ae1\u22a3\0\u22aa\0\u22b8\u22c5\u22ce\0\u22d5\u22f3\0\0\u22f8\u2322\u2367\u2362\u237f\0\u2386\u23aa\u23b4cute\u803b\xed\u40ed\u0180;iy\u0771\u22b0\u22b5rc\u803b\xee\u40ee;\u4438\u0100cx\u22bc\u22bfy;\u4435cl\u803b\xa1\u40a1\u0100fr\u039f\u22c9;\uc000\ud835\udd26rave\u803b\xec\u40ec\u0200;ino\u073e\u22dd\u22e9\u22ee\u0100in\u22e2\u22e6nt;\u6a0ct;\u622dfin;\u69dcta;\u6129lig;\u4133\u0180aop\u22fe\u231a\u231d\u0180cgt\u2305\u2308\u2317r;\u412b\u0180elp\u071f\u230f\u2313in\xe5\u078ear\xf4\u0720h;\u4131f;\u62b7ed;\u41b5\u0280;cfot\u04f4\u232c\u2331\u233d\u2341are;\u6105in\u0100;t\u2338\u2339\u621eie;\u69dddo\xf4\u2319\u0280;celp\u0757\u234c\u2350\u235b\u2361al;\u62ba\u0100gr\u2355\u2359er\xf3\u1563\xe3\u234darhk;\u6a17rod;\u6a3c\u0200cgpt\u236f\u2372\u2376\u237by;\u4451on;\u412ff;\uc000\ud835\udd5aa;\u43b9uest\u803b\xbf\u40bf\u0100ci\u238a\u238fr;\uc000\ud835\udcben\u0280;Edsv\u04f4\u239b\u239d\u23a1\u04f3;\u62f9ot;\u62f5\u0100;v\u23a6\u23a7\u62f4;\u62f3\u0100;i\u0777\u23aelde;\u4129\u01eb\u23b8\0\u23bccy;\u4456l\u803b\xef\u40ef\u0300cfmosu\u23cc\u23d7\u23dc\u23e1\u23e7\u23f5\u0100iy\u23d1\u23d5rc;\u4135;\u4439r;\uc000\ud835\udd27ath;\u4237pf;\uc000\ud835\udd5b\u01e3\u23ec\0\u23f1r;\uc000\ud835\udcbfrcy;\u4458kcy;\u4454\u0400acfghjos\u240b\u2416\u2422\u2427\u242d\u2431\u2435\u243bppa\u0100;v\u2413\u2414\u43ba;\u43f0\u0100ey\u241b\u2420dil;\u4137;\u443ar;\uc000\ud835\udd28reen;\u4138cy;\u4445cy;\u445cpf;\uc000\ud835\udd5ccr;\uc000\ud835\udcc0\u0b80ABEHabcdefghjlmnoprstuv\u2470\u2481\u2486\u248d\u2491\u250e\u253d\u255a\u2580\u264e\u265e\u2665\u2679\u267d\u269a\u26b2\u26d8\u275d\u2768\u278b\u27c0\u2801\u2812\u0180art\u2477\u247a\u247cr\xf2\u09c6\xf2\u0395ail;\u691barr;\u690e\u0100;g\u0994\u248b;\u6a8bar;\u6962\u0963\u24a5\0\u24aa\0\u24b1\0\0\0\0\0\u24b5\u24ba\0\u24c6\u24c8\u24cd\0\u24f9ute;\u413amptyv;\u69b4ra\xee\u084cbda;\u43bbg\u0180;dl\u088e\u24c1\u24c3;\u6991\xe5\u088e;\u6a85uo\u803b\xab\u40abr\u0400;bfhlpst\u0899\u24de\u24e6\u24e9\u24eb\u24ee\u24f1\u24f5\u0100;f\u089d\u24e3s;\u691fs;\u691d\xeb\u2252p;\u61abl;\u6939im;\u6973l;\u61a2\u0180;ae\u24ff\u2500\u2504\u6aabil;\u6919\u0100;s\u2509\u250a\u6aad;\uc000\u2aad\ufe00\u0180abr\u2515\u2519\u251drr;\u690crk;\u6772\u0100ak\u2522\u252cc\u0100ek\u2528\u252a;\u407b;\u405b\u0100es\u2531\u2533;\u698bl\u0100du\u2539\u253b;\u698f;\u698d\u0200aeuy\u2546\u254b\u2556\u2558ron;\u413e\u0100di\u2550\u2554il;\u413c\xec\u08b0\xe2\u2529;\u443b\u0200cqrs\u2563\u2566\u256d\u257da;\u6936uo\u0100;r\u0e19\u1746\u0100du\u2572\u2577har;\u6967shar;\u694bh;\u61b2\u0280;fgqs\u258b\u258c\u0989\u25f3\u25ff\u6264t\u0280ahlrt\u2598\u25a4\u25b7\u25c2\u25e8rrow\u0100;t\u0899\u25a1a\xe9\u24f6arpoon\u0100du\u25af\u25b4own\xbb\u045ap\xbb\u0966eftarrows;\u61c7ight\u0180ahs\u25cd\u25d6\u25derrow\u0100;s\u08f4\u08a7arpoon\xf3\u0f98quigarro\xf7\u21f0hreetimes;\u62cb\u0180;qs\u258b\u0993\u25falan\xf4\u09ac\u0280;cdgs\u09ac\u260a\u260d\u261d\u2628c;\u6aa8ot\u0100;o\u2614\u2615\u6a7f\u0100;r\u261a\u261b\u6a81;\u6a83\u0100;e\u2622\u2625\uc000\u22da\ufe00s;\u6a93\u0280adegs\u2633\u2639\u263d\u2649\u264bppro\xf8\u24c6ot;\u62d6q\u0100gq\u2643\u2645\xf4\u0989gt\xf2\u248c\xf4\u099bi\xed\u09b2\u0180ilr\u2655\u08e1\u265asht;\u697c;\uc000\ud835\udd29\u0100;E\u099c\u2663;\u6a91\u0161\u2669\u2676r\u0100du\u25b2\u266e\u0100;l\u0965\u2673;\u696alk;\u6584cy;\u4459\u0280;acht\u0a48\u2688\u268b\u2691\u2696r\xf2\u25c1orne\xf2\u1d08ard;\u696bri;\u65fa\u0100io\u269f\u26a4dot;\u4140ust\u0100;a\u26ac\u26ad\u63b0che\xbb\u26ad\u0200Eaes\u26bb\u26bd\u26c9\u26d4;\u6268p\u0100;p\u26c3\u26c4\u6a89rox\xbb\u26c4\u0100;q\u26ce\u26cf\u6a87\u0100;q\u26ce\u26bbim;\u62e6\u0400abnoptwz\u26e9\u26f4\u26f7\u271a\u272f\u2741\u2747\u2750\u0100nr\u26ee\u26f1g;\u67ecr;\u61fdr\xeb\u08c1g\u0180lmr\u26ff\u270d\u2714eft\u0100ar\u09e6\u2707ight\xe1\u09f2apsto;\u67fcight\xe1\u09fdparrow\u0100lr\u2725\u2729ef\xf4\u24edight;\u61ac\u0180afl\u2736\u2739\u273dr;\u6985;\uc000\ud835\udd5dus;\u6a2dimes;\u6a34\u0161\u274b\u274fst;\u6217\xe1\u134e\u0180;ef\u2757\u2758\u1800\u65cange\xbb\u2758ar\u0100;l\u2764\u2765\u4028t;\u6993\u0280achmt\u2773\u2776\u277c\u2785\u2787r\xf2\u08a8orne\xf2\u1d8car\u0100;d\u0f98\u2783;\u696d;\u600eri;\u62bf\u0300achiqt\u2798\u279d\u0a40\u27a2\u27ae\u27bbquo;\u6039r;\uc000\ud835\udcc1m\u0180;eg\u09b2\u27aa\u27ac;\u6a8d;\u6a8f\u0100bu\u252a\u27b3o\u0100;r\u0e1f\u27b9;\u601arok;\u4142\u8400<;cdhilqr\u082b\u27d2\u2639\u27dc\u27e0\u27e5\u27ea\u27f0\u0100ci\u27d7\u27d9;\u6aa6r;\u6a79re\xe5\u25f2mes;\u62c9arr;\u6976uest;\u6a7b\u0100Pi\u27f5\u27f9ar;\u6996\u0180;ef\u2800\u092d\u181b\u65c3r\u0100du\u2807\u280dshar;\u694ahar;\u6966\u0100en\u2817\u2821rtneqq;\uc000\u2268\ufe00\xc5\u281e\u0700Dacdefhilnopsu\u2840\u2845\u2882\u288e\u2893\u28a0\u28a5\u28a8\u28da\u28e2\u28e4\u0a83\u28f3\u2902Dot;\u623a\u0200clpr\u284e\u2852\u2863\u287dr\u803b\xaf\u40af\u0100et\u2857\u2859;\u6642\u0100;e\u285e\u285f\u6720se\xbb\u285f\u0100;s\u103b\u2868to\u0200;dlu\u103b\u2873\u2877\u287bow\xee\u048cef\xf4\u090f\xf0\u13d1ker;\u65ae\u0100oy\u2887\u288cmma;\u6a29;\u443cash;\u6014asuredangle\xbb\u1626r;\uc000\ud835\udd2ao;\u6127\u0180cdn\u28af\u28b4\u28c9ro\u803b\xb5\u40b5\u0200;acd\u1464\u28bd\u28c0\u28c4s\xf4\u16a7ir;\u6af0ot\u80bb\xb7\u01b5us\u0180;bd\u28d2\u1903\u28d3\u6212\u0100;u\u1d3c\u28d8;\u6a2a\u0163\u28de\u28e1p;\u6adb\xf2\u2212\xf0\u0a81\u0100dp\u28e9\u28eeels;\u62a7f;\uc000\ud835\udd5e\u0100ct\u28f8\u28fdr;\uc000\ud835\udcc2pos\xbb\u159d\u0180;lm\u2909\u290a\u290d\u43bctimap;\u62b8\u0c00GLRVabcdefghijlmoprstuvw\u2942\u2953\u297e\u2989\u2998\u29da\u29e9\u2a15\u2a1a\u2a58\u2a5d\u2a83\u2a95\u2aa4\u2aa8\u2b04\u2b07\u2b44\u2b7f\u2bae\u2c34\u2c67\u2c7c\u2ce9\u0100gt\u2947\u294b;\uc000\u22d9\u0338\u0100;v\u2950\u0bcf\uc000\u226b\u20d2\u0180elt\u295a\u2972\u2976ft\u0100ar\u2961\u2967rrow;\u61cdightarrow;\u61ce;\uc000\u22d8\u0338\u0100;v\u297b\u0c47\uc000\u226a\u20d2ightarrow;\u61cf\u0100Dd\u298e\u2993ash;\u62afash;\u62ae\u0280bcnpt\u29a3\u29a7\u29ac\u29b1\u29ccla\xbb\u02deute;\u4144g;\uc000\u2220\u20d2\u0280;Eiop\u0d84\u29bc\u29c0\u29c5\u29c8;\uc000\u2a70\u0338d;\uc000\u224b\u0338s;\u4149ro\xf8\u0d84ur\u0100;a\u29d3\u29d4\u666el\u0100;s\u29d3\u0b38\u01f3\u29df\0\u29e3p\u80bb\xa0\u0b37mp\u0100;e\u0bf9\u0c00\u0280aeouy\u29f4\u29fe\u2a03\u2a10\u2a13\u01f0\u29f9\0\u29fb;\u6a43on;\u4148dil;\u4146ng\u0100;d\u0d7e\u2a0aot;\uc000\u2a6d\u0338p;\u6a42;\u443dash;\u6013\u0380;Aadqsx\u0b92\u2a29\u2a2d\u2a3b\u2a41\u2a45\u2a50rr;\u61d7r\u0100hr\u2a33\u2a36k;\u6924\u0100;o\u13f2\u13f0ot;\uc000\u2250\u0338ui\xf6\u0b63\u0100ei\u2a4a\u2a4ear;\u6928\xed\u0b98ist\u0100;s\u0ba0\u0b9fr;\uc000\ud835\udd2b\u0200Eest\u0bc5\u2a66\u2a79\u2a7c\u0180;qs\u0bbc\u2a6d\u0be1\u0180;qs\u0bbc\u0bc5\u2a74lan\xf4\u0be2i\xed\u0bea\u0100;r\u0bb6\u2a81\xbb\u0bb7\u0180Aap\u2a8a\u2a8d\u2a91r\xf2\u2971rr;\u61aear;\u6af2\u0180;sv\u0f8d\u2a9c\u0f8c\u0100;d\u2aa1\u2aa2\u62fc;\u62facy;\u445a\u0380AEadest\u2ab7\u2aba\u2abe\u2ac2\u2ac5\u2af6\u2af9r\xf2\u2966;\uc000\u2266\u0338rr;\u619ar;\u6025\u0200;fqs\u0c3b\u2ace\u2ae3\u2aeft\u0100ar\u2ad4\u2ad9rro\xf7\u2ac1ightarro\xf7\u2a90\u0180;qs\u0c3b\u2aba\u2aealan\xf4\u0c55\u0100;s\u0c55\u2af4\xbb\u0c36i\xed\u0c5d\u0100;r\u0c35\u2afei\u0100;e\u0c1a\u0c25i\xe4\u0d90\u0100pt\u2b0c\u2b11f;\uc000\ud835\udd5f\u8180\xac;in\u2b19\u2b1a\u2b36\u40acn\u0200;Edv\u0b89\u2b24\u2b28\u2b2e;\uc000\u22f9\u0338ot;\uc000\u22f5\u0338\u01e1\u0b89\u2b33\u2b35;\u62f7;\u62f6i\u0100;v\u0cb8\u2b3c\u01e1\u0cb8\u2b41\u2b43;\u62fe;\u62fd\u0180aor\u2b4b\u2b63\u2b69r\u0200;ast\u0b7b\u2b55\u2b5a\u2b5flle\xec\u0b7bl;\uc000\u2afd\u20e5;\uc000\u2202\u0338lint;\u6a14\u0180;ce\u0c92\u2b70\u2b73u\xe5\u0ca5\u0100;c\u0c98\u2b78\u0100;e\u0c92\u2b7d\xf1\u0c98\u0200Aait\u2b88\u2b8b\u2b9d\u2ba7r\xf2\u2988rr\u0180;cw\u2b94\u2b95\u2b99\u619b;\uc000\u2933\u0338;\uc000\u219d\u0338ghtarrow\xbb\u2b95ri\u0100;e\u0ccb\u0cd6\u0380chimpqu\u2bbd\u2bcd\u2bd9\u2b04\u0b78\u2be4\u2bef\u0200;cer\u0d32\u2bc6\u0d37\u2bc9u\xe5\u0d45;\uc000\ud835\udcc3ort\u026d\u2b05\0\0\u2bd6ar\xe1\u2b56m\u0100;e\u0d6e\u2bdf\u0100;q\u0d74\u0d73su\u0100bp\u2beb\u2bed\xe5\u0cf8\xe5\u0d0b\u0180bcp\u2bf6\u2c11\u2c19\u0200;Ees\u2bff\u2c00\u0d22\u2c04\u6284;\uc000\u2ac5\u0338et\u0100;e\u0d1b\u2c0bq\u0100;q\u0d23\u2c00c\u0100;e\u0d32\u2c17\xf1\u0d38\u0200;Ees\u2c22\u2c23\u0d5f\u2c27\u6285;\uc000\u2ac6\u0338et\u0100;e\u0d58\u2c2eq\u0100;q\u0d60\u2c23\u0200gilr\u2c3d\u2c3f\u2c45\u2c47\xec\u0bd7lde\u803b\xf1\u40f1\xe7\u0c43iangle\u0100lr\u2c52\u2c5ceft\u0100;e\u0c1a\u2c5a\xf1\u0c26ight\u0100;e\u0ccb\u2c65\xf1\u0cd7\u0100;m\u2c6c\u2c6d\u43bd\u0180;es\u2c74\u2c75\u2c79\u4023ro;\u6116p;\u6007\u0480DHadgilrs\u2c8f\u2c94\u2c99\u2c9e\u2ca3\u2cb0\u2cb6\u2cd3\u2ce3ash;\u62adarr;\u6904p;\uc000\u224d\u20d2ash;\u62ac\u0100et\u2ca8\u2cac;\uc000\u2265\u20d2;\uc000>\u20d2nfin;\u69de\u0180Aet\u2cbd\u2cc1\u2cc5rr;\u6902;\uc000\u2264\u20d2\u0100;r\u2cca\u2ccd\uc000<\u20d2ie;\uc000\u22b4\u20d2\u0100At\u2cd8\u2cdcrr;\u6903rie;\uc000\u22b5\u20d2im;\uc000\u223c\u20d2\u0180Aan\u2cf0\u2cf4\u2d02rr;\u61d6r\u0100hr\u2cfa\u2cfdk;\u6923\u0100;o\u13e7\u13e5ear;\u6927\u1253\u1a95\0\0\0\0\0\0\0\0\0\0\0\0\0\u2d2d\0\u2d38\u2d48\u2d60\u2d65\u2d72\u2d84\u1b07\0\0\u2d8d\u2dab\0\u2dc8\u2dce\0\u2ddc\u2e19\u2e2b\u2e3e\u2e43\u0100cs\u2d31\u1a97ute\u803b\xf3\u40f3\u0100iy\u2d3c\u2d45r\u0100;c\u1a9e\u2d42\u803b\xf4\u40f4;\u443e\u0280abios\u1aa0\u2d52\u2d57\u01c8\u2d5alac;\u4151v;\u6a38old;\u69bclig;\u4153\u0100cr\u2d69\u2d6dir;\u69bf;\uc000\ud835\udd2c\u036f\u2d79\0\0\u2d7c\0\u2d82n;\u42dbave\u803b\xf2\u40f2;\u69c1\u0100bm\u2d88\u0df4ar;\u69b5\u0200acit\u2d95\u2d98\u2da5\u2da8r\xf2\u1a80\u0100ir\u2d9d\u2da0r;\u69beoss;\u69bbn\xe5\u0e52;\u69c0\u0180aei\u2db1\u2db5\u2db9cr;\u414dga;\u43c9\u0180cdn\u2dc0\u2dc5\u01cdron;\u43bf;\u69b6pf;\uc000\ud835\udd60\u0180ael\u2dd4\u2dd7\u01d2r;\u69b7rp;\u69b9\u0380;adiosv\u2dea\u2deb\u2dee\u2e08\u2e0d\u2e10\u2e16\u6228r\xf2\u1a86\u0200;efm\u2df7\u2df8\u2e02\u2e05\u6a5dr\u0100;o\u2dfe\u2dff\u6134f\xbb\u2dff\u803b\xaa\u40aa\u803b\xba\u40bagof;\u62b6r;\u6a56lope;\u6a57;\u6a5b\u0180clo\u2e1f\u2e21\u2e27\xf2\u2e01ash\u803b\xf8\u40f8l;\u6298i\u016c\u2e2f\u2e34de\u803b\xf5\u40f5es\u0100;a\u01db\u2e3as;\u6a36ml\u803b\xf6\u40f6bar;\u633d\u0ae1\u2e5e\0\u2e7d\0\u2e80\u2e9d\0\u2ea2\u2eb9\0\0\u2ecb\u0e9c\0\u2f13\0\0\u2f2b\u2fbc\0\u2fc8r\u0200;ast\u0403\u2e67\u2e72\u0e85\u8100\xb6;l\u2e6d\u2e6e\u40b6le\xec\u0403\u0269\u2e78\0\0\u2e7bm;\u6af3;\u6afdy;\u443fr\u0280cimpt\u2e8b\u2e8f\u2e93\u1865\u2e97nt;\u4025od;\u402eil;\u6030enk;\u6031r;\uc000\ud835\udd2d\u0180imo\u2ea8\u2eb0\u2eb4\u0100;v\u2ead\u2eae\u43c6;\u43d5ma\xf4\u0a76ne;\u660e\u0180;tv\u2ebf\u2ec0\u2ec8\u43c0chfork\xbb\u1ffd;\u43d6\u0100au\u2ecf\u2edfn\u0100ck\u2ed5\u2eddk\u0100;h\u21f4\u2edb;\u610e\xf6\u21f4s\u0480;abcdemst\u2ef3\u2ef4\u1908\u2ef9\u2efd\u2f04\u2f06\u2f0a\u2f0e\u402bcir;\u6a23ir;\u6a22\u0100ou\u1d40\u2f02;\u6a25;\u6a72n\u80bb\xb1\u0e9dim;\u6a26wo;\u6a27\u0180ipu\u2f19\u2f20\u2f25ntint;\u6a15f;\uc000\ud835\udd61nd\u803b\xa3\u40a3\u0500;Eaceinosu\u0ec8\u2f3f\u2f41\u2f44\u2f47\u2f81\u2f89\u2f92\u2f7e\u2fb6;\u6ab3p;\u6ab7u\xe5\u0ed9\u0100;c\u0ece\u2f4c\u0300;acens\u0ec8\u2f59\u2f5f\u2f66\u2f68\u2f7eppro\xf8\u2f43urlye\xf1\u0ed9\xf1\u0ece\u0180aes\u2f6f\u2f76\u2f7approx;\u6ab9qq;\u6ab5im;\u62e8i\xed\u0edfme\u0100;s\u2f88\u0eae\u6032\u0180Eas\u2f78\u2f90\u2f7a\xf0\u2f75\u0180dfp\u0eec\u2f99\u2faf\u0180als\u2fa0\u2fa5\u2faalar;\u632eine;\u6312urf;\u6313\u0100;t\u0efb\u2fb4\xef\u0efbrel;\u62b0\u0100ci\u2fc0\u2fc5r;\uc000\ud835\udcc5;\u43c8ncsp;\u6008\u0300fiopsu\u2fda\u22e2\u2fdf\u2fe5\u2feb\u2ff1r;\uc000\ud835\udd2epf;\uc000\ud835\udd62rime;\u6057cr;\uc000\ud835\udcc6\u0180aeo\u2ff8\u3009\u3013t\u0100ei\u2ffe\u3005rnion\xf3\u06b0nt;\u6a16st\u0100;e\u3010\u3011\u403f\xf1\u1f19\xf4\u0f14\u0a80ABHabcdefhilmnoprstux\u3040\u3051\u3055\u3059\u30e0\u310e\u312b\u3147\u3162\u3172\u318e\u3206\u3215\u3224\u3229\u3258\u326e\u3272\u3290\u32b0\u32b7\u0180art\u3047\u304a\u304cr\xf2\u10b3\xf2\u03ddail;\u691car\xf2\u1c65ar;\u6964\u0380cdenqrt\u3068\u3075\u3078\u307f\u308f\u3094\u30cc\u0100eu\u306d\u3071;\uc000\u223d\u0331te;\u4155i\xe3\u116emptyv;\u69b3g\u0200;del\u0fd1\u3089\u308b\u308d;\u6992;\u69a5\xe5\u0fd1uo\u803b\xbb\u40bbr\u0580;abcfhlpstw\u0fdc\u30ac\u30af\u30b7\u30b9\u30bc\u30be\u30c0\u30c3\u30c7\u30cap;\u6975\u0100;f\u0fe0\u30b4s;\u6920;\u6933s;\u691e\xeb\u225d\xf0\u272el;\u6945im;\u6974l;\u61a3;\u619d\u0100ai\u30d1\u30d5il;\u691ao\u0100;n\u30db\u30dc\u6236al\xf3\u0f1e\u0180abr\u30e7\u30ea\u30eer\xf2\u17e5rk;\u6773\u0100ak\u30f3\u30fdc\u0100ek\u30f9\u30fb;\u407d;\u405d\u0100es\u3102\u3104;\u698cl\u0100du\u310a\u310c;\u698e;\u6990\u0200aeuy\u3117\u311c\u3127\u3129ron;\u4159\u0100di\u3121\u3125il;\u4157\xec\u0ff2\xe2\u30fa;\u4440\u0200clqs\u3134\u3137\u313d\u3144a;\u6937dhar;\u6969uo\u0100;r\u020e\u020dh;\u61b3\u0180acg\u314e\u315f\u0f44l\u0200;ips\u0f78\u3158\u315b\u109cn\xe5\u10bbar\xf4\u0fa9t;\u65ad\u0180ilr\u3169\u1023\u316esht;\u697d;\uc000\ud835\udd2f\u0100ao\u3177\u3186r\u0100du\u317d\u317f\xbb\u047b\u0100;l\u1091\u3184;\u696c\u0100;v\u318b\u318c\u43c1;\u43f1\u0180gns\u3195\u31f9\u31fcht\u0300ahlrst\u31a4\u31b0\u31c2\u31d8\u31e4\u31eerrow\u0100;t\u0fdc\u31ada\xe9\u30c8arpoon\u0100du\u31bb\u31bfow\xee\u317ep\xbb\u1092eft\u0100ah\u31ca\u31d0rrow\xf3\u0feaarpoon\xf3\u0551ightarrows;\u61c9quigarro\xf7\u30cbhreetimes;\u62ccg;\u42daingdotse\xf1\u1f32\u0180ahm\u320d\u3210\u3213r\xf2\u0feaa\xf2\u0551;\u600foust\u0100;a\u321e\u321f\u63b1che\xbb\u321fmid;\u6aee\u0200abpt\u3232\u323d\u3240\u3252\u0100nr\u3237\u323ag;\u67edr;\u61fer\xeb\u1003\u0180afl\u3247\u324a\u324er;\u6986;\uc000\ud835\udd63us;\u6a2eimes;\u6a35\u0100ap\u325d\u3267r\u0100;g\u3263\u3264\u4029t;\u6994olint;\u6a12ar\xf2\u31e3\u0200achq\u327b\u3280\u10bc\u3285quo;\u603ar;\uc000\ud835\udcc7\u0100bu\u30fb\u328ao\u0100;r\u0214\u0213\u0180hir\u3297\u329b\u32a0re\xe5\u31f8mes;\u62cai\u0200;efl\u32aa\u1059\u1821\u32ab\u65b9tri;\u69celuhar;\u6968;\u611e\u0d61\u32d5\u32db\u32df\u332c\u3338\u3371\0\u337a\u33a4\0\0\u33ec\u33f0\0\u3428\u3448\u345a\u34ad\u34b1\u34ca\u34f1\0\u3616\0\0\u3633cute;\u415bqu\xef\u27ba\u0500;Eaceinpsy\u11ed\u32f3\u32f5\u32ff\u3302\u330b\u330f\u331f\u3326\u3329;\u6ab4\u01f0\u32fa\0\u32fc;\u6ab8on;\u4161u\xe5\u11fe\u0100;d\u11f3\u3307il;\u415frc;\u415d\u0180Eas\u3316\u3318\u331b;\u6ab6p;\u6abaim;\u62e9olint;\u6a13i\xed\u1204;\u4441ot\u0180;be\u3334\u1d47\u3335\u62c5;\u6a66\u0380Aacmstx\u3346\u334a\u3357\u335b\u335e\u3363\u336drr;\u61d8r\u0100hr\u3350\u3352\xeb\u2228\u0100;o\u0a36\u0a34t\u803b\xa7\u40a7i;\u403bwar;\u6929m\u0100in\u3369\xf0nu\xf3\xf1t;\u6736r\u0100;o\u3376\u2055\uc000\ud835\udd30\u0200acoy\u3382\u3386\u3391\u33a0rp;\u666f\u0100hy\u338b\u338fcy;\u4449;\u4448rt\u026d\u3399\0\0\u339ci\xe4\u1464ara\xec\u2e6f\u803b\xad\u40ad\u0100gm\u33a8\u33b4ma\u0180;fv\u33b1\u33b2\u33b2\u43c3;\u43c2\u0400;deglnpr\u12ab\u33c5\u33c9\u33ce\u33d6\u33de\u33e1\u33e6ot;\u6a6a\u0100;q\u12b1\u12b0\u0100;E\u33d3\u33d4\u6a9e;\u6aa0\u0100;E\u33db\u33dc\u6a9d;\u6a9fe;\u6246lus;\u6a24arr;\u6972ar\xf2\u113d\u0200aeit\u33f8\u3408\u340f\u3417\u0100ls\u33fd\u3404lsetm\xe9\u336ahp;\u6a33parsl;\u69e4\u0100dl\u1463\u3414e;\u6323\u0100;e\u341c\u341d\u6aaa\u0100;s\u3422\u3423\u6aac;\uc000\u2aac\ufe00\u0180flp\u342e\u3433\u3442tcy;\u444c\u0100;b\u3438\u3439\u402f\u0100;a\u343e\u343f\u69c4r;\u633ff;\uc000\ud835\udd64a\u0100dr\u344d\u0402es\u0100;u\u3454\u3455\u6660it\xbb\u3455\u0180csu\u3460\u3479\u349f\u0100au\u3465\u346fp\u0100;s\u1188\u346b;\uc000\u2293\ufe00p\u0100;s\u11b4\u3475;\uc000\u2294\ufe00u\u0100bp\u347f\u348f\u0180;es\u1197\u119c\u3486et\u0100;e\u1197\u348d\xf1\u119d\u0180;es\u11a8\u11ad\u3496et\u0100;e\u11a8\u349d\xf1\u11ae\u0180;af\u117b\u34a6\u05b0r\u0165\u34ab\u05b1\xbb\u117car\xf2\u1148\u0200cemt\u34b9\u34be\u34c2\u34c5r;\uc000\ud835\udcc8tm\xee\xf1i\xec\u3415ar\xe6\u11be\u0100ar\u34ce\u34d5r\u0100;f\u34d4\u17bf\u6606\u0100an\u34da\u34edight\u0100ep\u34e3\u34eapsilo\xee\u1ee0h\xe9\u2eafs\xbb\u2852\u0280bcmnp\u34fb\u355e\u1209\u358b\u358e\u0480;Edemnprs\u350e\u350f\u3511\u3515\u351e\u3523\u352c\u3531\u3536\u6282;\u6ac5ot;\u6abd\u0100;d\u11da\u351aot;\u6ac3ult;\u6ac1\u0100Ee\u3528\u352a;\u6acb;\u628alus;\u6abfarr;\u6979\u0180eiu\u353d\u3552\u3555t\u0180;en\u350e\u3545\u354bq\u0100;q\u11da\u350feq\u0100;q\u352b\u3528m;\u6ac7\u0100bp\u355a\u355c;\u6ad5;\u6ad3c\u0300;acens\u11ed\u356c\u3572\u3579\u357b\u3326ppro\xf8\u32faurlye\xf1\u11fe\xf1\u11f3\u0180aes\u3582\u3588\u331bppro\xf8\u331aq\xf1\u3317g;\u666a\u0680123;Edehlmnps\u35a9\u35ac\u35af\u121c\u35b2\u35b4\u35c0\u35c9\u35d5\u35da\u35df\u35e8\u35ed\u803b\xb9\u40b9\u803b\xb2\u40b2\u803b\xb3\u40b3;\u6ac6\u0100os\u35b9\u35bct;\u6abeub;\u6ad8\u0100;d\u1222\u35c5ot;\u6ac4s\u0100ou\u35cf\u35d2l;\u67c9b;\u6ad7arr;\u697bult;\u6ac2\u0100Ee\u35e4\u35e6;\u6acc;\u628blus;\u6ac0\u0180eiu\u35f4\u3609\u360ct\u0180;en\u121c\u35fc\u3602q\u0100;q\u1222\u35b2eq\u0100;q\u35e7\u35e4m;\u6ac8\u0100bp\u3611\u3613;\u6ad4;\u6ad6\u0180Aan\u361c\u3620\u362drr;\u61d9r\u0100hr\u3626\u3628\xeb\u222e\u0100;o\u0a2b\u0a29war;\u692alig\u803b\xdf\u40df\u0be1\u3651\u365d\u3660\u12ce\u3673\u3679\0\u367e\u36c2\0\0\0\0\0\u36db\u3703\0\u3709\u376c\0\0\0\u3787\u0272\u3656\0\0\u365bget;\u6316;\u43c4r\xeb\u0e5f\u0180aey\u3666\u366b\u3670ron;\u4165dil;\u4163;\u4442lrec;\u6315r;\uc000\ud835\udd31\u0200eiko\u3686\u369d\u36b5\u36bc\u01f2\u368b\0\u3691e\u01004f\u1284\u1281a\u0180;sv\u3698\u3699\u369b\u43b8ym;\u43d1\u0100cn\u36a2\u36b2k\u0100as\u36a8\u36aeppro\xf8\u12c1im\xbb\u12acs\xf0\u129e\u0100as\u36ba\u36ae\xf0\u12c1rn\u803b\xfe\u40fe\u01ec\u031f\u36c6\u22e7es\u8180\xd7;bd\u36cf\u36d0\u36d8\u40d7\u0100;a\u190f\u36d5r;\u6a31;\u6a30\u0180eps\u36e1\u36e3\u3700\xe1\u2a4d\u0200;bcf\u0486\u36ec\u36f0\u36f4ot;\u6336ir;\u6af1\u0100;o\u36f9\u36fc\uc000\ud835\udd65rk;\u6ada\xe1\u3362rime;\u6034\u0180aip\u370f\u3712\u3764d\xe5\u1248\u0380adempst\u3721\u374d\u3740\u3751\u3757\u375c\u375fngle\u0280;dlqr\u3730\u3731\u3736\u3740\u3742\u65b5own\xbb\u1dbbeft\u0100;e\u2800\u373e\xf1\u092e;\u625cight\u0100;e\u32aa\u374b\xf1\u105aot;\u65ecinus;\u6a3alus;\u6a39b;\u69cdime;\u6a3bezium;\u63e2\u0180cht\u3772\u377d\u3781\u0100ry\u3777\u377b;\uc000\ud835\udcc9;\u4446cy;\u445brok;\u4167\u0100io\u378b\u378ex\xf4\u1777head\u0100lr\u3797\u37a0eftarro\xf7\u084fightarrow\xbb\u0f5d\u0900AHabcdfghlmoprstuw\u37d0\u37d3\u37d7\u37e4\u37f0\u37fc\u380e\u381c\u3823\u3834\u3851\u385d\u386b\u38a9\u38cc\u38d2\u38ea\u38f6r\xf2\u03edar;\u6963\u0100cr\u37dc\u37e2ute\u803b\xfa\u40fa\xf2\u1150r\u01e3\u37ea\0\u37edy;\u445eve;\u416d\u0100iy\u37f5\u37farc\u803b\xfb\u40fb;\u4443\u0180abh\u3803\u3806\u380br\xf2\u13adlac;\u4171a\xf2\u13c3\u0100ir\u3813\u3818sht;\u697e;\uc000\ud835\udd32rave\u803b\xf9\u40f9\u0161\u3827\u3831r\u0100lr\u382c\u382e\xbb\u0957\xbb\u1083lk;\u6580\u0100ct\u3839\u384d\u026f\u383f\0\0\u384arn\u0100;e\u3845\u3846\u631cr\xbb\u3846op;\u630fri;\u65f8\u0100al\u3856\u385acr;\u416b\u80bb\xa8\u0349\u0100gp\u3862\u3866on;\u4173f;\uc000\ud835\udd66\u0300adhlsu\u114b\u3878\u387d\u1372\u3891\u38a0own\xe1\u13b3arpoon\u0100lr\u3888\u388cef\xf4\u382digh\xf4\u382fi\u0180;hl\u3899\u389a\u389c\u43c5\xbb\u13faon\xbb\u389aparrows;\u61c8\u0180cit\u38b0\u38c4\u38c8\u026f\u38b6\0\0\u38c1rn\u0100;e\u38bc\u38bd\u631dr\xbb\u38bdop;\u630eng;\u416fri;\u65f9cr;\uc000\ud835\udcca\u0180dir\u38d9\u38dd\u38e2ot;\u62f0lde;\u4169i\u0100;f\u3730\u38e8\xbb\u1813\u0100am\u38ef\u38f2r\xf2\u38a8l\u803b\xfc\u40fcangle;\u69a7\u0780ABDacdeflnoprsz\u391c\u391f\u3929\u392d\u39b5\u39b8\u39bd\u39df\u39e4\u39e8\u39f3\u39f9\u39fd\u3a01\u3a20r\xf2\u03f7ar\u0100;v\u3926\u3927\u6ae8;\u6ae9as\xe8\u03e1\u0100nr\u3932\u3937grt;\u699c\u0380eknprst\u34e3\u3946\u394b\u3952\u395d\u3964\u3996app\xe1\u2415othin\xe7\u1e96\u0180hir\u34eb\u2ec8\u3959op\xf4\u2fb5\u0100;h\u13b7\u3962\xef\u318d\u0100iu\u3969\u396dgm\xe1\u33b3\u0100bp\u3972\u3984setneq\u0100;q\u397d\u3980\uc000\u228a\ufe00;\uc000\u2acb\ufe00setneq\u0100;q\u398f\u3992\uc000\u228b\ufe00;\uc000\u2acc\ufe00\u0100hr\u399b\u399fet\xe1\u369ciangle\u0100lr\u39aa\u39afeft\xbb\u0925ight\xbb\u1051y;\u4432ash\xbb\u1036\u0180elr\u39c4\u39d2\u39d7\u0180;be\u2dea\u39cb\u39cfar;\u62bbq;\u625alip;\u62ee\u0100bt\u39dc\u1468a\xf2\u1469r;\uc000\ud835\udd33tr\xe9\u39aesu\u0100bp\u39ef\u39f1\xbb\u0d1c\xbb\u0d59pf;\uc000\ud835\udd67ro\xf0\u0efbtr\xe9\u39b4\u0100cu\u3a06\u3a0br;\uc000\ud835\udccb\u0100bp\u3a10\u3a18n\u0100Ee\u3980\u3a16\xbb\u397en\u0100Ee\u3992\u3a1e\xbb\u3990igzag;\u699a\u0380cefoprs\u3a36\u3a3b\u3a56\u3a5b\u3a54\u3a61\u3a6airc;\u4175\u0100di\u3a40\u3a51\u0100bg\u3a45\u3a49ar;\u6a5fe\u0100;q\u15fa\u3a4f;\u6259erp;\u6118r;\uc000\ud835\udd34pf;\uc000\ud835\udd68\u0100;e\u1479\u3a66at\xe8\u1479cr;\uc000\ud835\udccc\u0ae3\u178e\u3a87\0\u3a8b\0\u3a90\u3a9b\0\0\u3a9d\u3aa8\u3aab\u3aaf\0\0\u3ac3\u3ace\0\u3ad8\u17dc\u17dftr\xe9\u17d1r;\uc000\ud835\udd35\u0100Aa\u3a94\u3a97r\xf2\u03c3r\xf2\u09f6;\u43be\u0100Aa\u3aa1\u3aa4r\xf2\u03b8r\xf2\u09eba\xf0\u2713is;\u62fb\u0180dpt\u17a4\u3ab5\u3abe\u0100fl\u3aba\u17a9;\uc000\ud835\udd69im\xe5\u17b2\u0100Aa\u3ac7\u3acar\xf2\u03cer\xf2\u0a01\u0100cq\u3ad2\u17b8r;\uc000\ud835\udccd\u0100pt\u17d6\u3adcr\xe9\u17d4\u0400acefiosu\u3af0\u3afd\u3b08\u3b0c\u3b11\u3b15\u3b1b\u3b21c\u0100uy\u3af6\u3afbte\u803b\xfd\u40fd;\u444f\u0100iy\u3b02\u3b06rc;\u4177;\u444bn\u803b\xa5\u40a5r;\uc000\ud835\udd36cy;\u4457pf;\uc000\ud835\udd6acr;\uc000\ud835\udcce\u0100cm\u3b26\u3b29y;\u444el\u803b\xff\u40ff\u0500acdefhiosw\u3b42\u3b48\u3b54\u3b58\u3b64\u3b69\u3b6d\u3b74\u3b7a\u3b80cute;\u417a\u0100ay\u3b4d\u3b52ron;\u417e;\u4437ot;\u417c\u0100et\u3b5d\u3b61tr\xe6\u155fa;\u43b6r;\uc000\ud835\udd37cy;\u4436grarr;\u61ddpf;\uc000\ud835\udd6bcr;\uc000\ud835\udccf\u0100jn\u3b85\u3b87;\u600dj;\u600c" + .split("") + .map((c) => c.charCodeAt(0))); + + // Generated using scripts/write-decode-map.ts + var xmlDecodeTree = new Uint16Array( + // prettier-ignore + "\u0200aglq\t\x15\x18\x1b\u026d\x0f\0\0\x12p;\u4026os;\u4027t;\u403et;\u403cuot;\u4022" + .split("") + .map((c) => c.charCodeAt(0))); + + // Adapted from https://github.com/mathiasbynens/he/blob/36afe179392226cf1b6ccdb16ebbb7a5a844d93a/src/he.js#L106-L134 + var _a; + const decodeMap = new Map([ + [0, 65533], + // C1 Unicode control character reference replacements + [128, 8364], + [130, 8218], + [131, 402], + [132, 8222], + [133, 8230], + [134, 8224], + [135, 8225], + [136, 710], + [137, 8240], + [138, 352], + [139, 8249], + [140, 338], + [142, 381], + [145, 8216], + [146, 8217], + [147, 8220], + [148, 8221], + [149, 8226], + [150, 8211], + [151, 8212], + [152, 732], + [153, 8482], + [154, 353], + [155, 8250], + [156, 339], + [158, 382], + [159, 376], + ]); + /** + * Polyfill for `String.fromCodePoint`. It is used to create a string from a Unicode code point. + */ + const fromCodePoint = + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, node/no-unsupported-features/es-builtins + (_a = String.fromCodePoint) !== null && _a !== void 0 ? _a : function (codePoint) { + let output = ""; + if (codePoint > 0xffff) { + codePoint -= 0x10000; + output += String.fromCharCode(((codePoint >>> 10) & 0x3ff) | 0xd800); + codePoint = 0xdc00 | (codePoint & 0x3ff); + } + output += String.fromCharCode(codePoint); + return output; + }; + /** + * Replace the given code point with a replacement character if it is a + * surrogate or is outside the valid range. Otherwise return the code + * point unchanged. + */ + function replaceCodePoint(codePoint) { + var _a; + if ((codePoint >= 0xd800 && codePoint <= 0xdfff) || codePoint > 0x10ffff) { + return 0xfffd; + } + return (_a = decodeMap.get(codePoint)) !== null && _a !== void 0 ? _a : codePoint; + } + + var CharCodes$1; + (function (CharCodes) { + CharCodes[CharCodes["NUM"] = 35] = "NUM"; + CharCodes[CharCodes["SEMI"] = 59] = "SEMI"; + CharCodes[CharCodes["EQUALS"] = 61] = "EQUALS"; + CharCodes[CharCodes["ZERO"] = 48] = "ZERO"; + CharCodes[CharCodes["NINE"] = 57] = "NINE"; + CharCodes[CharCodes["LOWER_A"] = 97] = "LOWER_A"; + CharCodes[CharCodes["LOWER_F"] = 102] = "LOWER_F"; + CharCodes[CharCodes["LOWER_X"] = 120] = "LOWER_X"; + CharCodes[CharCodes["LOWER_Z"] = 122] = "LOWER_Z"; + CharCodes[CharCodes["UPPER_A"] = 65] = "UPPER_A"; + CharCodes[CharCodes["UPPER_F"] = 70] = "UPPER_F"; + CharCodes[CharCodes["UPPER_Z"] = 90] = "UPPER_Z"; + })(CharCodes$1 || (CharCodes$1 = {})); + /** Bit that needs to be set to convert an upper case ASCII character to lower case */ + const TO_LOWER_BIT = 0b100000; + var BinTrieFlags; + (function (BinTrieFlags) { + BinTrieFlags[BinTrieFlags["VALUE_LENGTH"] = 49152] = "VALUE_LENGTH"; + BinTrieFlags[BinTrieFlags["BRANCH_LENGTH"] = 16256] = "BRANCH_LENGTH"; + BinTrieFlags[BinTrieFlags["JUMP_TABLE"] = 127] = "JUMP_TABLE"; + })(BinTrieFlags || (BinTrieFlags = {})); + function isNumber(code) { + return code >= CharCodes$1.ZERO && code <= CharCodes$1.NINE; + } + function isHexadecimalCharacter(code) { + return ((code >= CharCodes$1.UPPER_A && code <= CharCodes$1.UPPER_F) || + (code >= CharCodes$1.LOWER_A && code <= CharCodes$1.LOWER_F)); + } + function isAsciiAlphaNumeric(code) { + return ((code >= CharCodes$1.UPPER_A && code <= CharCodes$1.UPPER_Z) || + (code >= CharCodes$1.LOWER_A && code <= CharCodes$1.LOWER_Z) || + isNumber(code)); + } + /** + * Checks if the given character is a valid end character for an entity in an attribute. + * + * Attribute values that aren't terminated properly aren't parsed, and shouldn't lead to a parser error. + * See the example in https://html.spec.whatwg.org/multipage/parsing.html#named-character-reference-state + */ + function isEntityInAttributeInvalidEnd(code) { + return code === CharCodes$1.EQUALS || isAsciiAlphaNumeric(code); + } + var EntityDecoderState; + (function (EntityDecoderState) { + EntityDecoderState[EntityDecoderState["EntityStart"] = 0] = "EntityStart"; + EntityDecoderState[EntityDecoderState["NumericStart"] = 1] = "NumericStart"; + EntityDecoderState[EntityDecoderState["NumericDecimal"] = 2] = "NumericDecimal"; + EntityDecoderState[EntityDecoderState["NumericHex"] = 3] = "NumericHex"; + EntityDecoderState[EntityDecoderState["NamedEntity"] = 4] = "NamedEntity"; + })(EntityDecoderState || (EntityDecoderState = {})); + var DecodingMode; + (function (DecodingMode) { + /** Entities in text nodes that can end with any character. */ + DecodingMode[DecodingMode["Legacy"] = 0] = "Legacy"; + /** Only allow entities terminated with a semicolon. */ + DecodingMode[DecodingMode["Strict"] = 1] = "Strict"; + /** Entities in attributes have limitations on ending characters. */ + DecodingMode[DecodingMode["Attribute"] = 2] = "Attribute"; + })(DecodingMode || (DecodingMode = {})); + /** + * Token decoder with support of writing partial entities. + */ + class EntityDecoder { + constructor( + /** The tree used to decode entities. */ + decodeTree, + /** + * The function that is called when a codepoint is decoded. + * + * For multi-byte named entities, this will be called multiple times, + * with the second codepoint, and the same `consumed` value. + * + * @param codepoint The decoded codepoint. + * @param consumed The number of bytes consumed by the decoder. + */ + emitCodePoint, + /** An object that is used to produce errors. */ + errors) { + this.decodeTree = decodeTree; + this.emitCodePoint = emitCodePoint; + this.errors = errors; + /** The current state of the decoder. */ + this.state = EntityDecoderState.EntityStart; + /** Characters that were consumed while parsing an entity. */ + this.consumed = 1; + /** + * The result of the entity. + * + * Either the result index of a numeric entity, or the codepoint of a + * numeric entity. + */ + this.result = 0; + /** The current index in the decode tree. */ + this.treeIndex = 0; + /** The number of characters that were consumed in excess. */ + this.excess = 1; + /** The mode in which the decoder is operating. */ + this.decodeMode = DecodingMode.Strict; + } + /** Resets the instance to make it reusable. */ + startEntity(decodeMode) { + this.decodeMode = decodeMode; + this.state = EntityDecoderState.EntityStart; + this.result = 0; + this.treeIndex = 0; + this.excess = 1; + this.consumed = 1; + } + /** + * Write an entity to the decoder. This can be called multiple times with partial entities. + * If the entity is incomplete, the decoder will return -1. + * + * Mirrors the implementation of `getDecoder`, but with the ability to stop decoding if the + * entity is incomplete, and resume when the next string is written. + * + * @param string The string containing the entity (or a continuation of the entity). + * @param offset The offset at which the entity begins. Should be 0 if this is not the first call. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + write(str, offset) { + switch (this.state) { + case EntityDecoderState.EntityStart: { + if (str.charCodeAt(offset) === CharCodes$1.NUM) { + this.state = EntityDecoderState.NumericStart; + this.consumed += 1; + return this.stateNumericStart(str, offset + 1); + } + this.state = EntityDecoderState.NamedEntity; + return this.stateNamedEntity(str, offset); + } + case EntityDecoderState.NumericStart: { + return this.stateNumericStart(str, offset); + } + case EntityDecoderState.NumericDecimal: { + return this.stateNumericDecimal(str, offset); + } + case EntityDecoderState.NumericHex: { + return this.stateNumericHex(str, offset); + } + case EntityDecoderState.NamedEntity: { + return this.stateNamedEntity(str, offset); + } + } + } + /** + * Switches between the numeric decimal and hexadecimal states. + * + * Equivalent to the `Numeric character reference state` in the HTML spec. + * + * @param str The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNumericStart(str, offset) { + if (offset >= str.length) { + return -1; + } + if ((str.charCodeAt(offset) | TO_LOWER_BIT) === CharCodes$1.LOWER_X) { + this.state = EntityDecoderState.NumericHex; + this.consumed += 1; + return this.stateNumericHex(str, offset + 1); + } + this.state = EntityDecoderState.NumericDecimal; + return this.stateNumericDecimal(str, offset); + } + addToNumericResult(str, start, end, base) { + if (start !== end) { + const digitCount = end - start; + this.result = + this.result * Math.pow(base, digitCount) + + parseInt(str.substr(start, digitCount), base); + this.consumed += digitCount; + } + } + /** + * Parses a hexadecimal numeric entity. + * + * Equivalent to the `Hexademical character reference state` in the HTML spec. + * + * @param str The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNumericHex(str, offset) { + const startIdx = offset; + while (offset < str.length) { + const char = str.charCodeAt(offset); + if (isNumber(char) || isHexadecimalCharacter(char)) { + offset += 1; + } + else { + this.addToNumericResult(str, startIdx, offset, 16); + return this.emitNumericEntity(char, 3); + } + } + this.addToNumericResult(str, startIdx, offset, 16); + return -1; + } + /** + * Parses a decimal numeric entity. + * + * Equivalent to the `Decimal character reference state` in the HTML spec. + * + * @param str The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNumericDecimal(str, offset) { + const startIdx = offset; + while (offset < str.length) { + const char = str.charCodeAt(offset); + if (isNumber(char)) { + offset += 1; + } + else { + this.addToNumericResult(str, startIdx, offset, 10); + return this.emitNumericEntity(char, 2); + } + } + this.addToNumericResult(str, startIdx, offset, 10); + return -1; + } + /** + * Validate and emit a numeric entity. + * + * Implements the logic from the `Hexademical character reference start + * state` and `Numeric character reference end state` in the HTML spec. + * + * @param lastCp The last code point of the entity. Used to see if the + * entity was terminated with a semicolon. + * @param expectedLength The minimum number of characters that should be + * consumed. Used to validate that at least one digit + * was consumed. + * @returns The number of characters that were consumed. + */ + emitNumericEntity(lastCp, expectedLength) { + var _a; + // Ensure we consumed at least one digit. + if (this.consumed <= expectedLength) { + (_a = this.errors) === null || _a === void 0 ? void 0 : _a.absenceOfDigitsInNumericCharacterReference(this.consumed); + return 0; + } + // Figure out if this is a legit end of the entity + if (lastCp === CharCodes$1.SEMI) { + this.consumed += 1; + } + else if (this.decodeMode === DecodingMode.Strict) { + return 0; + } + this.emitCodePoint(replaceCodePoint(this.result), this.consumed); + if (this.errors) { + if (lastCp !== CharCodes$1.SEMI) { + this.errors.missingSemicolonAfterCharacterReference(); + } + this.errors.validateNumericCharacterReference(this.result); + } + return this.consumed; + } + /** + * Parses a named entity. + * + * Equivalent to the `Named character reference state` in the HTML spec. + * + * @param str The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + stateNamedEntity(str, offset) { + const { decodeTree } = this; + let current = decodeTree[this.treeIndex]; + // The mask is the number of bytes of the value, including the current byte. + let valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; + for (; offset < str.length; offset++, this.excess++) { + const char = str.charCodeAt(offset); + this.treeIndex = determineBranch(decodeTree, current, this.treeIndex + Math.max(1, valueLength), char); + if (this.treeIndex < 0) { + return this.result === 0 || + // If we are parsing an attribute + (this.decodeMode === DecodingMode.Attribute && + // We shouldn't have consumed any characters after the entity, + (valueLength === 0 || + // And there should be no invalid characters. + isEntityInAttributeInvalidEnd(char))) + ? 0 + : this.emitNotTerminatedNamedEntity(); + } + current = decodeTree[this.treeIndex]; + valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; + // If the branch is a value, store it and continue + if (valueLength !== 0) { + // If the entity is terminated by a semicolon, we are done. + if (char === CharCodes$1.SEMI) { + return this.emitNamedEntityData(this.treeIndex, valueLength, this.consumed + this.excess); + } + // If we encounter a non-terminated (legacy) entity while parsing strictly, then ignore it. + if (this.decodeMode !== DecodingMode.Strict) { + this.result = this.treeIndex; + this.consumed += this.excess; + this.excess = 0; + } + } + } + return -1; + } + /** + * Emit a named entity that was not terminated with a semicolon. + * + * @returns The number of characters consumed. + */ + emitNotTerminatedNamedEntity() { + var _a; + const { result, decodeTree } = this; + const valueLength = (decodeTree[result] & BinTrieFlags.VALUE_LENGTH) >> 14; + this.emitNamedEntityData(result, valueLength, this.consumed); + (_a = this.errors) === null || _a === void 0 ? void 0 : _a.missingSemicolonAfterCharacterReference(); + return this.consumed; + } + /** + * Emit a named entity. + * + * @param result The index of the entity in the decode tree. + * @param valueLength The number of bytes in the entity. + * @param consumed The number of characters consumed. + * + * @returns The number of characters consumed. + */ + emitNamedEntityData(result, valueLength, consumed) { + const { decodeTree } = this; + this.emitCodePoint(valueLength === 1 + ? decodeTree[result] & ~BinTrieFlags.VALUE_LENGTH + : decodeTree[result + 1], consumed); + if (valueLength === 3) { + // For multi-byte values, we need to emit the second byte. + this.emitCodePoint(decodeTree[result + 2], consumed); + } + return consumed; + } + /** + * Signal to the parser that the end of the input was reached. + * + * Remaining data will be emitted and relevant errors will be produced. + * + * @returns The number of characters consumed. + */ + end() { + var _a; + switch (this.state) { + case EntityDecoderState.NamedEntity: { + // Emit a named entity if we have one. + return this.result !== 0 && + (this.decodeMode !== DecodingMode.Attribute || + this.result === this.treeIndex) + ? this.emitNotTerminatedNamedEntity() + : 0; + } + // Otherwise, emit a numeric entity if we have one. + case EntityDecoderState.NumericDecimal: { + return this.emitNumericEntity(0, 2); + } + case EntityDecoderState.NumericHex: { + return this.emitNumericEntity(0, 3); + } + case EntityDecoderState.NumericStart: { + (_a = this.errors) === null || _a === void 0 ? void 0 : _a.absenceOfDigitsInNumericCharacterReference(this.consumed); + return 0; + } + case EntityDecoderState.EntityStart: { + // Return 0 if we have no entity. + return 0; + } + } + } + } + /** + * Creates a function that decodes entities in a string. + * + * @param decodeTree The decode tree. + * @returns A function that decodes entities in a string. + */ + function getDecoder(decodeTree) { + let ret = ""; + const decoder = new EntityDecoder(decodeTree, (str) => (ret += fromCodePoint(str))); + return function decodeWithTrie(str, decodeMode) { + let lastIndex = 0; + let offset = 0; + while ((offset = str.indexOf("&", offset)) >= 0) { + ret += str.slice(lastIndex, offset); + decoder.startEntity(decodeMode); + const len = decoder.write(str, + // Skip the "&" + offset + 1); + if (len < 0) { + lastIndex = offset + decoder.end(); + break; + } + lastIndex = offset + len; + // If `len` is 0, skip the current `&` and continue. + offset = len === 0 ? lastIndex + 1 : lastIndex; + } + const result = ret + str.slice(lastIndex); + // Make sure we don't keep a reference to the final string. + ret = ""; + return result; + }; + } + /** + * Determines the branch of the current node that is taken given the current + * character. This function is used to traverse the trie. + * + * @param decodeTree The trie. + * @param current The current node. + * @param nodeIdx The index right after the current node and its value. + * @param char The current character. + * @returns The index of the next node, or -1 if no branch is taken. + */ + function determineBranch(decodeTree, current, nodeIdx, char) { + const branchCount = (current & BinTrieFlags.BRANCH_LENGTH) >> 7; + const jumpOffset = current & BinTrieFlags.JUMP_TABLE; + // Case 1: Single branch encoded in jump offset + if (branchCount === 0) { + return jumpOffset !== 0 && char === jumpOffset ? nodeIdx : -1; + } + // Case 2: Multiple branches encoded in jump table + if (jumpOffset) { + const value = char - jumpOffset; + return value < 0 || value >= branchCount + ? -1 + : decodeTree[nodeIdx + value] - 1; + } + // Case 3: Multiple branches encoded in dictionary + // Binary search for the character. + let lo = nodeIdx; + let hi = lo + branchCount - 1; + while (lo <= hi) { + const mid = (lo + hi) >>> 1; + const midVal = decodeTree[mid]; + if (midVal < char) { + lo = mid + 1; + } + else if (midVal > char) { + hi = mid - 1; + } + else { + return decodeTree[mid + branchCount]; + } + } + return -1; + } + getDecoder(htmlDecodeTree); + getDecoder(xmlDecodeTree); + + var CharCodes; + (function (CharCodes) { + CharCodes[CharCodes["Tab"] = 9] = "Tab"; + CharCodes[CharCodes["NewLine"] = 10] = "NewLine"; + CharCodes[CharCodes["FormFeed"] = 12] = "FormFeed"; + CharCodes[CharCodes["CarriageReturn"] = 13] = "CarriageReturn"; + CharCodes[CharCodes["Space"] = 32] = "Space"; + CharCodes[CharCodes["ExclamationMark"] = 33] = "ExclamationMark"; + CharCodes[CharCodes["Number"] = 35] = "Number"; + CharCodes[CharCodes["Amp"] = 38] = "Amp"; + CharCodes[CharCodes["SingleQuote"] = 39] = "SingleQuote"; + CharCodes[CharCodes["DoubleQuote"] = 34] = "DoubleQuote"; + CharCodes[CharCodes["Dash"] = 45] = "Dash"; + CharCodes[CharCodes["Slash"] = 47] = "Slash"; + CharCodes[CharCodes["Zero"] = 48] = "Zero"; + CharCodes[CharCodes["Nine"] = 57] = "Nine"; + CharCodes[CharCodes["Semi"] = 59] = "Semi"; + CharCodes[CharCodes["Lt"] = 60] = "Lt"; + CharCodes[CharCodes["Eq"] = 61] = "Eq"; + CharCodes[CharCodes["Gt"] = 62] = "Gt"; + CharCodes[CharCodes["Questionmark"] = 63] = "Questionmark"; + CharCodes[CharCodes["UpperA"] = 65] = "UpperA"; + CharCodes[CharCodes["LowerA"] = 97] = "LowerA"; + CharCodes[CharCodes["UpperF"] = 70] = "UpperF"; + CharCodes[CharCodes["LowerF"] = 102] = "LowerF"; + CharCodes[CharCodes["UpperZ"] = 90] = "UpperZ"; + CharCodes[CharCodes["LowerZ"] = 122] = "LowerZ"; + CharCodes[CharCodes["LowerX"] = 120] = "LowerX"; + CharCodes[CharCodes["OpeningSquareBracket"] = 91] = "OpeningSquareBracket"; + })(CharCodes || (CharCodes = {})); + /** All the states the tokenizer can be in. */ + var State; + (function (State) { + State[State["Text"] = 1] = "Text"; + State[State["BeforeTagName"] = 2] = "BeforeTagName"; + State[State["InTagName"] = 3] = "InTagName"; + State[State["InSelfClosingTag"] = 4] = "InSelfClosingTag"; + State[State["BeforeClosingTagName"] = 5] = "BeforeClosingTagName"; + State[State["InClosingTagName"] = 6] = "InClosingTagName"; + State[State["AfterClosingTagName"] = 7] = "AfterClosingTagName"; + // Attributes + State[State["BeforeAttributeName"] = 8] = "BeforeAttributeName"; + State[State["InAttributeName"] = 9] = "InAttributeName"; + State[State["AfterAttributeName"] = 10] = "AfterAttributeName"; + State[State["BeforeAttributeValue"] = 11] = "BeforeAttributeValue"; + State[State["InAttributeValueDq"] = 12] = "InAttributeValueDq"; + State[State["InAttributeValueSq"] = 13] = "InAttributeValueSq"; + State[State["InAttributeValueNq"] = 14] = "InAttributeValueNq"; + // Declarations + State[State["BeforeDeclaration"] = 15] = "BeforeDeclaration"; + State[State["InDeclaration"] = 16] = "InDeclaration"; + // Processing instructions + State[State["InProcessingInstruction"] = 17] = "InProcessingInstruction"; + // Comments & CDATA + State[State["BeforeComment"] = 18] = "BeforeComment"; + State[State["CDATASequence"] = 19] = "CDATASequence"; + State[State["InSpecialComment"] = 20] = "InSpecialComment"; + State[State["InCommentLike"] = 21] = "InCommentLike"; + // Special tags + State[State["BeforeSpecialS"] = 22] = "BeforeSpecialS"; + State[State["BeforeSpecialT"] = 23] = "BeforeSpecialT"; + State[State["SpecialStartSequence"] = 24] = "SpecialStartSequence"; + State[State["InSpecialTag"] = 25] = "InSpecialTag"; + State[State["InEntity"] = 26] = "InEntity"; + })(State || (State = {})); + function isWhitespace$1(c) { + return (c === CharCodes.Space || + c === CharCodes.NewLine || + c === CharCodes.Tab || + c === CharCodes.FormFeed || + c === CharCodes.CarriageReturn); + } + function isEndOfTagSection(c) { + return c === CharCodes.Slash || c === CharCodes.Gt || isWhitespace$1(c); + } + function isASCIIAlpha(c) { + return ((c >= CharCodes.LowerA && c <= CharCodes.LowerZ) || + (c >= CharCodes.UpperA && c <= CharCodes.UpperZ)); + } + var QuoteType; + (function (QuoteType) { + QuoteType[QuoteType["NoValue"] = 0] = "NoValue"; + QuoteType[QuoteType["Unquoted"] = 1] = "Unquoted"; + QuoteType[QuoteType["Single"] = 2] = "Single"; + QuoteType[QuoteType["Double"] = 3] = "Double"; + })(QuoteType || (QuoteType = {})); + /** + * Sequences used to match longer strings. + * + * We don't have `Script`, `Style`, or `Title` here. Instead, we re-use the *End + * sequences with an increased offset. + */ + const Sequences = { + Cdata: new Uint8Array([0x43, 0x44, 0x41, 0x54, 0x41, 0x5b]), // CDATA[ + CdataEnd: new Uint8Array([0x5d, 0x5d, 0x3e]), // ]]> + CommentEnd: new Uint8Array([0x2d, 0x2d, 0x3e]), // `-->` + ScriptEnd: new Uint8Array([0x3c, 0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74]), // ` this.emitCodePoint(cp, consumed)); + } + reset() { + this.state = State.Text; + this.buffer = ""; + this.sectionStart = 0; + this.index = 0; + this.baseState = State.Text; + this.currentSequence = undefined; + this.running = true; + this.offset = 0; + } + write(chunk) { + this.offset += this.buffer.length; + this.buffer = chunk; + this.parse(); + } + end() { + if (this.running) + this.finish(); + } + pause() { + this.running = false; + } + resume() { + this.running = true; + if (this.index < this.buffer.length + this.offset) { + this.parse(); + } + } + stateText(c) { + if (c === CharCodes.Lt || + (!this.decodeEntities && this.fastForwardTo(CharCodes.Lt))) { + if (this.index > this.sectionStart) { + this.cbs.ontext(this.sectionStart, this.index); + } + this.state = State.BeforeTagName; + this.sectionStart = this.index; + } + else if (this.decodeEntities && c === CharCodes.Amp) { + this.startEntity(); + } + } + stateSpecialStartSequence(c) { + const isEnd = this.sequenceIndex === this.currentSequence.length; + const isMatch = isEnd + ? // If we are at the end of the sequence, make sure the tag name has ended + isEndOfTagSection(c) + : // Otherwise, do a case-insensitive comparison + (c | 0x20) === this.currentSequence[this.sequenceIndex]; + if (!isMatch) { + this.isSpecial = false; + } + else if (!isEnd) { + this.sequenceIndex++; + return; + } + this.sequenceIndex = 0; + this.state = State.InTagName; + this.stateInTagName(c); + } + /** Look for an end tag. For tags, also decode entities. */ + stateInSpecialTag(c) { + if (this.sequenceIndex === this.currentSequence.length) { + if (c === CharCodes.Gt || isWhitespace$1(c)) { + const endOfText = this.index - this.currentSequence.length; + if (this.sectionStart < endOfText) { + // Spoof the index so that reported locations match up. + const actualIndex = this.index; + this.index = endOfText; + this.cbs.ontext(this.sectionStart, endOfText); + this.index = actualIndex; + } + this.isSpecial = false; + this.sectionStart = endOfText + 2; // Skip over the `</` + this.stateInClosingTagName(c); + return; // We are done; skip the rest of the function. + } + this.sequenceIndex = 0; + } + if ((c | 0x20) === this.currentSequence[this.sequenceIndex]) { + this.sequenceIndex += 1; + } + else if (this.sequenceIndex === 0) { + if (this.currentSequence === Sequences.TitleEnd) { + // We have to parse entities in <title> tags. + if (this.decodeEntities && c === CharCodes.Amp) { + this.startEntity(); + } + } + else if (this.fastForwardTo(CharCodes.Lt)) { + // Outside of <title> tags, we can fast-forward. + this.sequenceIndex = 1; + } + } + else { + // If we see a `<`, set the sequence index to 1; useful for eg. `<</script>`. + this.sequenceIndex = Number(c === CharCodes.Lt); + } + } + stateCDATASequence(c) { + if (c === Sequences.Cdata[this.sequenceIndex]) { + if (++this.sequenceIndex === Sequences.Cdata.length) { + this.state = State.InCommentLike; + this.currentSequence = Sequences.CdataEnd; + this.sequenceIndex = 0; + this.sectionStart = this.index + 1; + } + } + else { + this.sequenceIndex = 0; + this.state = State.InDeclaration; + this.stateInDeclaration(c); // Reconsume the character + } + } + /** + * When we wait for one specific character, we can speed things up + * by skipping through the buffer until we find it. + * + * @returns Whether the character was found. + */ + fastForwardTo(c) { + while (++this.index < this.buffer.length + this.offset) { + if (this.buffer.charCodeAt(this.index - this.offset) === c) { + return true; + } + } + /* + * We increment the index at the end of the `parse` loop, + * so set it to `buffer.length - 1` here. + * + * TODO: Refactor `parse` to increment index before calling states. + */ + this.index = this.buffer.length + this.offset - 1; + return false; + } + /** + * Comments and CDATA end with `-->` and `]]>`. + * + * Their common qualities are: + * - Their end sequences have a distinct character they start with. + * - That character is then repeated, so we have to check multiple repeats. + * - All characters but the start character of the sequence can be skipped. + */ + stateInCommentLike(c) { + if (c === this.currentSequence[this.sequenceIndex]) { + if (++this.sequenceIndex === this.currentSequence.length) { + if (this.currentSequence === Sequences.CdataEnd) { + this.cbs.oncdata(this.sectionStart, this.index, 2); + } + else { + this.cbs.oncomment(this.sectionStart, this.index, 2); + } + this.sequenceIndex = 0; + this.sectionStart = this.index + 1; + this.state = State.Text; + } + } + else if (this.sequenceIndex === 0) { + // Fast-forward to the first character of the sequence + if (this.fastForwardTo(this.currentSequence[0])) { + this.sequenceIndex = 1; + } + } + else if (c !== this.currentSequence[this.sequenceIndex - 1]) { + // Allow long sequences, eg. --->, ]]]> + this.sequenceIndex = 0; + } + } + /** + * HTML only allows ASCII alpha characters (a-z and A-Z) at the beginning of a tag name. + * + * XML allows a lot more characters here (@see https://www.w3.org/TR/REC-xml/#NT-NameStartChar). + * We allow anything that wouldn't end the tag. + */ + isTagStartChar(c) { + return this.xmlMode ? !isEndOfTagSection(c) : isASCIIAlpha(c); + } + startSpecial(sequence, offset) { + this.isSpecial = true; + this.currentSequence = sequence; + this.sequenceIndex = offset; + this.state = State.SpecialStartSequence; + } + stateBeforeTagName(c) { + if (c === CharCodes.ExclamationMark) { + this.state = State.BeforeDeclaration; + this.sectionStart = this.index + 1; + } + else if (c === CharCodes.Questionmark) { + this.state = State.InProcessingInstruction; + this.sectionStart = this.index + 1; + } + else if (this.isTagStartChar(c)) { + const lower = c | 0x20; + this.sectionStart = this.index; + if (this.xmlMode) { + this.state = State.InTagName; + } + else if (lower === Sequences.ScriptEnd[2]) { + this.state = State.BeforeSpecialS; + } + else if (lower === Sequences.TitleEnd[2]) { + this.state = State.BeforeSpecialT; + } + else { + this.state = State.InTagName; + } + } + else if (c === CharCodes.Slash) { + this.state = State.BeforeClosingTagName; + } + else { + this.state = State.Text; + this.stateText(c); + } + } + stateInTagName(c) { + if (isEndOfTagSection(c)) { + this.cbs.onopentagname(this.sectionStart, this.index); + this.sectionStart = -1; + this.state = State.BeforeAttributeName; + this.stateBeforeAttributeName(c); + } + } + stateBeforeClosingTagName(c) { + if (isWhitespace$1(c)) ; + else if (c === CharCodes.Gt) { + this.state = State.Text; + } + else { + this.state = this.isTagStartChar(c) + ? State.InClosingTagName + : State.InSpecialComment; + this.sectionStart = this.index; + } + } + stateInClosingTagName(c) { + if (c === CharCodes.Gt || isWhitespace$1(c)) { + this.cbs.onclosetag(this.sectionStart, this.index); + this.sectionStart = -1; + this.state = State.AfterClosingTagName; + this.stateAfterClosingTagName(c); + } + } + stateAfterClosingTagName(c) { + // Skip everything until ">" + if (c === CharCodes.Gt || this.fastForwardTo(CharCodes.Gt)) { + this.state = State.Text; + this.sectionStart = this.index + 1; + } + } + stateBeforeAttributeName(c) { + if (c === CharCodes.Gt) { + this.cbs.onopentagend(this.index); + if (this.isSpecial) { + this.state = State.InSpecialTag; + this.sequenceIndex = 0; + } + else { + this.state = State.Text; + } + this.sectionStart = this.index + 1; + } + else if (c === CharCodes.Slash) { + this.state = State.InSelfClosingTag; + } + else if (!isWhitespace$1(c)) { + this.state = State.InAttributeName; + this.sectionStart = this.index; + } + } + stateInSelfClosingTag(c) { + if (c === CharCodes.Gt) { + this.cbs.onselfclosingtag(this.index); + this.state = State.Text; + this.sectionStart = this.index + 1; + this.isSpecial = false; // Reset special state, in case of self-closing special tags + } + else if (!isWhitespace$1(c)) { + this.state = State.BeforeAttributeName; + this.stateBeforeAttributeName(c); + } + } + stateInAttributeName(c) { + if (c === CharCodes.Eq || isEndOfTagSection(c)) { + this.cbs.onattribname(this.sectionStart, this.index); + this.sectionStart = this.index; + this.state = State.AfterAttributeName; + this.stateAfterAttributeName(c); + } + } + stateAfterAttributeName(c) { + if (c === CharCodes.Eq) { + this.state = State.BeforeAttributeValue; + } + else if (c === CharCodes.Slash || c === CharCodes.Gt) { + this.cbs.onattribend(QuoteType.NoValue, this.sectionStart); + this.sectionStart = -1; + this.state = State.BeforeAttributeName; + this.stateBeforeAttributeName(c); + } + else if (!isWhitespace$1(c)) { + this.cbs.onattribend(QuoteType.NoValue, this.sectionStart); + this.state = State.InAttributeName; + this.sectionStart = this.index; + } + } + stateBeforeAttributeValue(c) { + if (c === CharCodes.DoubleQuote) { + this.state = State.InAttributeValueDq; + this.sectionStart = this.index + 1; + } + else if (c === CharCodes.SingleQuote) { + this.state = State.InAttributeValueSq; + this.sectionStart = this.index + 1; + } + else if (!isWhitespace$1(c)) { + this.sectionStart = this.index; + this.state = State.InAttributeValueNq; + this.stateInAttributeValueNoQuotes(c); // Reconsume token + } + } + handleInAttributeValue(c, quote) { + if (c === quote || + (!this.decodeEntities && this.fastForwardTo(quote))) { + this.cbs.onattribdata(this.sectionStart, this.index); + this.sectionStart = -1; + this.cbs.onattribend(quote === CharCodes.DoubleQuote + ? QuoteType.Double + : QuoteType.Single, this.index + 1); + this.state = State.BeforeAttributeName; + } + else if (this.decodeEntities && c === CharCodes.Amp) { + this.startEntity(); + } + } + stateInAttributeValueDoubleQuotes(c) { + this.handleInAttributeValue(c, CharCodes.DoubleQuote); + } + stateInAttributeValueSingleQuotes(c) { + this.handleInAttributeValue(c, CharCodes.SingleQuote); + } + stateInAttributeValueNoQuotes(c) { + if (isWhitespace$1(c) || c === CharCodes.Gt) { + this.cbs.onattribdata(this.sectionStart, this.index); + this.sectionStart = -1; + this.cbs.onattribend(QuoteType.Unquoted, this.index); + this.state = State.BeforeAttributeName; + this.stateBeforeAttributeName(c); + } + else if (this.decodeEntities && c === CharCodes.Amp) { + this.startEntity(); + } + } + stateBeforeDeclaration(c) { + if (c === CharCodes.OpeningSquareBracket) { + this.state = State.CDATASequence; + this.sequenceIndex = 0; + } + else { + this.state = + c === CharCodes.Dash + ? State.BeforeComment + : State.InDeclaration; + } + } + stateInDeclaration(c) { + if (c === CharCodes.Gt || this.fastForwardTo(CharCodes.Gt)) { + this.cbs.ondeclaration(this.sectionStart, this.index); + this.state = State.Text; + this.sectionStart = this.index + 1; + } + } + stateInProcessingInstruction(c) { + if (c === CharCodes.Gt || this.fastForwardTo(CharCodes.Gt)) { + this.cbs.onprocessinginstruction(this.sectionStart, this.index); + this.state = State.Text; + this.sectionStart = this.index + 1; + } + } + stateBeforeComment(c) { + if (c === CharCodes.Dash) { + this.state = State.InCommentLike; + this.currentSequence = Sequences.CommentEnd; + // Allow short comments (eg. <!-->) + this.sequenceIndex = 2; + this.sectionStart = this.index + 1; + } + else { + this.state = State.InDeclaration; + } + } + stateInSpecialComment(c) { + if (c === CharCodes.Gt || this.fastForwardTo(CharCodes.Gt)) { + this.cbs.oncomment(this.sectionStart, this.index, 0); + this.state = State.Text; + this.sectionStart = this.index + 1; + } + } + stateBeforeSpecialS(c) { + const lower = c | 0x20; + if (lower === Sequences.ScriptEnd[3]) { + this.startSpecial(Sequences.ScriptEnd, 4); + } + else if (lower === Sequences.StyleEnd[3]) { + this.startSpecial(Sequences.StyleEnd, 4); + } + else { + this.state = State.InTagName; + this.stateInTagName(c); // Consume the token again + } + } + stateBeforeSpecialT(c) { + const lower = c | 0x20; + if (lower === Sequences.TitleEnd[3]) { + this.startSpecial(Sequences.TitleEnd, 4); + } + else if (lower === Sequences.TextareaEnd[3]) { + this.startSpecial(Sequences.TextareaEnd, 4); + } + else { + this.state = State.InTagName; + this.stateInTagName(c); // Consume the token again + } + } + startEntity() { + this.baseState = this.state; + this.state = State.InEntity; + this.entityStart = this.index; + this.entityDecoder.startEntity(this.xmlMode + ? DecodingMode.Strict + : this.baseState === State.Text || + this.baseState === State.InSpecialTag + ? DecodingMode.Legacy + : DecodingMode.Attribute); + } + stateInEntity() { + const length = this.entityDecoder.write(this.buffer, this.index - this.offset); + // If `length` is positive, we are done with the entity. + if (length >= 0) { + this.state = this.baseState; + if (length === 0) { + this.index = this.entityStart; + } + } + else { + // Mark buffer as consumed. + this.index = this.offset + this.buffer.length - 1; + } + } + /** + * Remove data that has already been consumed from the buffer. + */ + cleanup() { + // If we are inside of text or attributes, emit what we already have. + if (this.running && this.sectionStart !== this.index) { + if (this.state === State.Text || + (this.state === State.InSpecialTag && this.sequenceIndex === 0)) { + this.cbs.ontext(this.sectionStart, this.index); + this.sectionStart = this.index; + } + else if (this.state === State.InAttributeValueDq || + this.state === State.InAttributeValueSq || + this.state === State.InAttributeValueNq) { + this.cbs.onattribdata(this.sectionStart, this.index); + this.sectionStart = this.index; + } + } + } + shouldContinue() { + return this.index < this.buffer.length + this.offset && this.running; + } + /** + * Iterates through the buffer, calling the function corresponding to the current state. + * + * States that are more likely to be hit are higher up, as a performance improvement. + */ + parse() { + while (this.shouldContinue()) { + const c = this.buffer.charCodeAt(this.index - this.offset); + switch (this.state) { + case State.Text: { + this.stateText(c); + break; + } + case State.SpecialStartSequence: { + this.stateSpecialStartSequence(c); + break; + } + case State.InSpecialTag: { + this.stateInSpecialTag(c); + break; + } + case State.CDATASequence: { + this.stateCDATASequence(c); + break; + } + case State.InAttributeValueDq: { + this.stateInAttributeValueDoubleQuotes(c); + break; + } + case State.InAttributeName: { + this.stateInAttributeName(c); + break; + } + case State.InCommentLike: { + this.stateInCommentLike(c); + break; + } + case State.InSpecialComment: { + this.stateInSpecialComment(c); + break; + } + case State.BeforeAttributeName: { + this.stateBeforeAttributeName(c); + break; + } + case State.InTagName: { + this.stateInTagName(c); + break; + } + case State.InClosingTagName: { + this.stateInClosingTagName(c); + break; + } + case State.BeforeTagName: { + this.stateBeforeTagName(c); + break; + } + case State.AfterAttributeName: { + this.stateAfterAttributeName(c); + break; + } + case State.InAttributeValueSq: { + this.stateInAttributeValueSingleQuotes(c); + break; + } + case State.BeforeAttributeValue: { + this.stateBeforeAttributeValue(c); + break; + } + case State.BeforeClosingTagName: { + this.stateBeforeClosingTagName(c); + break; + } + case State.AfterClosingTagName: { + this.stateAfterClosingTagName(c); + break; + } + case State.BeforeSpecialS: { + this.stateBeforeSpecialS(c); + break; + } + case State.BeforeSpecialT: { + this.stateBeforeSpecialT(c); + break; + } + case State.InAttributeValueNq: { + this.stateInAttributeValueNoQuotes(c); + break; + } + case State.InSelfClosingTag: { + this.stateInSelfClosingTag(c); + break; + } + case State.InDeclaration: { + this.stateInDeclaration(c); + break; + } + case State.BeforeDeclaration: { + this.stateBeforeDeclaration(c); + break; + } + case State.BeforeComment: { + this.stateBeforeComment(c); + break; + } + case State.InProcessingInstruction: { + this.stateInProcessingInstruction(c); + break; + } + case State.InEntity: { + this.stateInEntity(); + break; + } + } + this.index++; + } + this.cleanup(); + } + finish() { + if (this.state === State.InEntity) { + this.entityDecoder.end(); + this.state = this.baseState; + } + this.handleTrailingData(); + this.cbs.onend(); + } + /** Handle any trailing data. */ + handleTrailingData() { + const endIndex = this.buffer.length + this.offset; + // If there is no remaining data, we are done. + if (this.sectionStart >= endIndex) { + return; + } + if (this.state === State.InCommentLike) { + if (this.currentSequence === Sequences.CdataEnd) { + this.cbs.oncdata(this.sectionStart, endIndex, 0); + } + else { + this.cbs.oncomment(this.sectionStart, endIndex, 0); + } + } + else if (this.state === State.InTagName || + this.state === State.BeforeAttributeName || + this.state === State.BeforeAttributeValue || + this.state === State.AfterAttributeName || + this.state === State.InAttributeName || + this.state === State.InAttributeValueSq || + this.state === State.InAttributeValueDq || + this.state === State.InAttributeValueNq || + this.state === State.InClosingTagName) ; + else { + this.cbs.ontext(this.sectionStart, endIndex); + } + } + emitCodePoint(cp, consumed) { + if (this.baseState !== State.Text && + this.baseState !== State.InSpecialTag) { + if (this.sectionStart < this.entityStart) { + this.cbs.onattribdata(this.sectionStart, this.entityStart); + } + this.sectionStart = this.entityStart + consumed; + this.index = this.sectionStart - 1; + this.cbs.onattribentity(cp); + } + else { + if (this.sectionStart < this.entityStart) { + this.cbs.ontext(this.sectionStart, this.entityStart); + } + this.sectionStart = this.entityStart + consumed; + this.index = this.sectionStart - 1; + this.cbs.ontextentity(cp, this.sectionStart); + } + } + }; + + const formTags$1 = new Set([ + "input", + "option", + "optgroup", + "select", + "button", + "datalist", + "textarea", + ]); + const pTag$1 = new Set(["p"]); + const tableSectionTags$1 = new Set(["thead", "tbody"]); + const ddtTags$1 = new Set(["dd", "dt"]); + const rtpTags$1 = new Set(["rt", "rp"]); + const openImpliesClose$1 = new Map([ + ["tr", new Set(["tr", "th", "td"])], + ["th", new Set(["th"])], + ["td", new Set(["thead", "th", "td"])], + ["body", new Set(["head", "link", "script"])], + ["li", new Set(["li"])], + ["p", pTag$1], + ["h1", pTag$1], + ["h2", pTag$1], + ["h3", pTag$1], + ["h4", pTag$1], + ["h5", pTag$1], + ["h6", pTag$1], + ["select", formTags$1], + ["input", formTags$1], + ["output", formTags$1], + ["button", formTags$1], + ["datalist", formTags$1], + ["textarea", formTags$1], + ["option", new Set(["option"])], + ["optgroup", new Set(["optgroup", "option"])], + ["dd", ddtTags$1], + ["dt", ddtTags$1], + ["address", pTag$1], + ["article", pTag$1], + ["aside", pTag$1], + ["blockquote", pTag$1], + ["details", pTag$1], + ["div", pTag$1], + ["dl", pTag$1], + ["fieldset", pTag$1], + ["figcaption", pTag$1], + ["figure", pTag$1], + ["footer", pTag$1], + ["form", pTag$1], + ["header", pTag$1], + ["hr", pTag$1], + ["main", pTag$1], + ["nav", pTag$1], + ["ol", pTag$1], + ["pre", pTag$1], + ["section", pTag$1], + ["table", pTag$1], + ["ul", pTag$1], + ["rt", rtpTags$1], + ["rp", rtpTags$1], + ["tbody", tableSectionTags$1], + ["tfoot", tableSectionTags$1], + ]); + const voidElements$2 = new Set([ + "area", + "base", + "basefont", + "br", + "col", + "command", + "embed", + "frame", + "hr", + "img", + "input", + "isindex", + "keygen", + "link", + "meta", + "param", + "source", + "track", + "wbr", + ]); + const foreignContextElements$1 = new Set(["math", "svg"]); + const htmlIntegrationElements$1 = new Set([ + "mi", + "mo", + "mn", + "ms", + "mtext", + "annotation-xml", + "foreignobject", + "desc", + "title", + ]); + const reNameEnd$1 = /\s|\//; + let Parser$5 = class Parser { + constructor(cbs, options = {}) { + var _a, _b, _c, _d, _e, _f; + this.options = options; + /** The start index of the last event. */ + this.startIndex = 0; + /** The end index of the last event. */ + this.endIndex = 0; + /** + * Store the start index of the current open tag, + * so we can update the start index for attributes. + */ + this.openTagStart = 0; + this.tagname = ""; + this.attribname = ""; + this.attribvalue = ""; + this.attribs = null; + this.stack = []; + this.buffers = []; + this.bufferOffset = 0; + /** The index of the last written buffer. Used when resuming after a `pause()`. */ + this.writeIndex = 0; + /** Indicates whether the parser has finished running / `.end` has been called. */ + this.ended = false; + this.cbs = cbs !== null && cbs !== void 0 ? cbs : {}; + this.htmlMode = !this.options.xmlMode; + this.lowerCaseTagNames = (_a = options.lowerCaseTags) !== null && _a !== void 0 ? _a : this.htmlMode; + this.lowerCaseAttributeNames = + (_b = options.lowerCaseAttributeNames) !== null && _b !== void 0 ? _b : this.htmlMode; + this.recognizeSelfClosing = + (_c = options.recognizeSelfClosing) !== null && _c !== void 0 ? _c : !this.htmlMode; + this.tokenizer = new ((_d = options.Tokenizer) !== null && _d !== void 0 ? _d : Tokenizer$1)(this.options, this); + this.foreignContext = [!this.htmlMode]; + (_f = (_e = this.cbs).onparserinit) === null || _f === void 0 ? void 0 : _f.call(_e, this); + } + // Tokenizer event handlers + /** @internal */ + ontext(start, endIndex) { + var _a, _b; + const data = this.getSlice(start, endIndex); + this.endIndex = endIndex - 1; + (_b = (_a = this.cbs).ontext) === null || _b === void 0 ? void 0 : _b.call(_a, data); + this.startIndex = endIndex; + } + /** @internal */ + ontextentity(cp, endIndex) { + var _a, _b; + this.endIndex = endIndex - 1; + (_b = (_a = this.cbs).ontext) === null || _b === void 0 ? void 0 : _b.call(_a, fromCodePoint(cp)); + this.startIndex = endIndex; + } + /** + * Checks if the current tag is a void element. Override this if you want + * to specify your own additional void elements. + */ + isVoidElement(name) { + return this.htmlMode && voidElements$2.has(name); + } + /** @internal */ + onopentagname(start, endIndex) { + this.endIndex = endIndex; + let name = this.getSlice(start, endIndex); + if (this.lowerCaseTagNames) { + name = name.toLowerCase(); + } + this.emitOpenTag(name); + } + emitOpenTag(name) { + var _a, _b, _c, _d; + this.openTagStart = this.startIndex; + this.tagname = name; + const impliesClose = this.htmlMode && openImpliesClose$1.get(name); + if (impliesClose) { + while (this.stack.length > 0 && impliesClose.has(this.stack[0])) { + const element = this.stack.shift(); + (_b = (_a = this.cbs).onclosetag) === null || _b === void 0 ? void 0 : _b.call(_a, element, true); + } + } + if (!this.isVoidElement(name)) { + this.stack.unshift(name); + if (this.htmlMode) { + if (foreignContextElements$1.has(name)) { + this.foreignContext.unshift(true); + } + else if (htmlIntegrationElements$1.has(name)) { + this.foreignContext.unshift(false); + } + } + } + (_d = (_c = this.cbs).onopentagname) === null || _d === void 0 ? void 0 : _d.call(_c, name); + if (this.cbs.onopentag) + this.attribs = {}; + } + endOpenTag(isImplied) { + var _a, _b; + this.startIndex = this.openTagStart; + if (this.attribs) { + (_b = (_a = this.cbs).onopentag) === null || _b === void 0 ? void 0 : _b.call(_a, this.tagname, this.attribs, isImplied); + this.attribs = null; + } + if (this.cbs.onclosetag && this.isVoidElement(this.tagname)) { + this.cbs.onclosetag(this.tagname, true); + } + this.tagname = ""; + } + /** @internal */ + onopentagend(endIndex) { + this.endIndex = endIndex; + this.endOpenTag(false); + // Set `startIndex` for next node + this.startIndex = endIndex + 1; + } + /** @internal */ + onclosetag(start, endIndex) { + var _a, _b, _c, _d, _e, _f, _g, _h; + this.endIndex = endIndex; + let name = this.getSlice(start, endIndex); + if (this.lowerCaseTagNames) { + name = name.toLowerCase(); + } + if (this.htmlMode && + (foreignContextElements$1.has(name) || + htmlIntegrationElements$1.has(name))) { + this.foreignContext.shift(); + } + if (!this.isVoidElement(name)) { + const pos = this.stack.indexOf(name); + if (pos !== -1) { + for (let index = 0; index <= pos; index++) { + const element = this.stack.shift(); + // We know the stack has sufficient elements. + (_b = (_a = this.cbs).onclosetag) === null || _b === void 0 ? void 0 : _b.call(_a, element, index !== pos); + } + } + else if (this.htmlMode && name === "p") { + // Implicit open before close + this.emitOpenTag("p"); + this.closeCurrentTag(true); + } + } + else if (this.htmlMode && name === "br") { + // We can't use `emitOpenTag` for implicit open, as `br` would be implicitly closed. + (_d = (_c = this.cbs).onopentagname) === null || _d === void 0 ? void 0 : _d.call(_c, "br"); + (_f = (_e = this.cbs).onopentag) === null || _f === void 0 ? void 0 : _f.call(_e, "br", {}, true); + (_h = (_g = this.cbs).onclosetag) === null || _h === void 0 ? void 0 : _h.call(_g, "br", false); + } + // Set `startIndex` for next node + this.startIndex = endIndex + 1; + } + /** @internal */ + onselfclosingtag(endIndex) { + this.endIndex = endIndex; + if (this.recognizeSelfClosing || this.foreignContext[0]) { + this.closeCurrentTag(false); + // Set `startIndex` for next node + this.startIndex = endIndex + 1; + } + else { + // Ignore the fact that the tag is self-closing. + this.onopentagend(endIndex); + } + } + closeCurrentTag(isOpenImplied) { + var _a, _b; + const name = this.tagname; + this.endOpenTag(isOpenImplied); + // Self-closing tags will be on the top of the stack + if (this.stack[0] === name) { + // If the opening tag isn't implied, the closing tag has to be implied. + (_b = (_a = this.cbs).onclosetag) === null || _b === void 0 ? void 0 : _b.call(_a, name, !isOpenImplied); + this.stack.shift(); + } + } + /** @internal */ + onattribname(start, endIndex) { + this.startIndex = start; + const name = this.getSlice(start, endIndex); + this.attribname = this.lowerCaseAttributeNames + ? name.toLowerCase() + : name; + } + /** @internal */ + onattribdata(start, endIndex) { + this.attribvalue += this.getSlice(start, endIndex); + } + /** @internal */ + onattribentity(cp) { + this.attribvalue += fromCodePoint(cp); + } + /** @internal */ + onattribend(quote, endIndex) { + var _a, _b; + this.endIndex = endIndex; + (_b = (_a = this.cbs).onattribute) === null || _b === void 0 ? void 0 : _b.call(_a, this.attribname, this.attribvalue, quote === QuoteType.Double + ? '"' + : quote === QuoteType.Single + ? "'" + : quote === QuoteType.NoValue + ? undefined + : null); + if (this.attribs && + !Object.prototype.hasOwnProperty.call(this.attribs, this.attribname)) { + this.attribs[this.attribname] = this.attribvalue; + } + this.attribvalue = ""; + } + getInstructionName(value) { + const index = value.search(reNameEnd$1); + let name = index < 0 ? value : value.substr(0, index); + if (this.lowerCaseTagNames) { + name = name.toLowerCase(); + } + return name; + } + /** @internal */ + ondeclaration(start, endIndex) { + this.endIndex = endIndex; + const value = this.getSlice(start, endIndex); + if (this.cbs.onprocessinginstruction) { + const name = this.getInstructionName(value); + this.cbs.onprocessinginstruction(`!${name}`, `!${value}`); + } + // Set `startIndex` for next node + this.startIndex = endIndex + 1; + } + /** @internal */ + onprocessinginstruction(start, endIndex) { + this.endIndex = endIndex; + const value = this.getSlice(start, endIndex); + if (this.cbs.onprocessinginstruction) { + const name = this.getInstructionName(value); + this.cbs.onprocessinginstruction(`?${name}`, `?${value}`); + } + // Set `startIndex` for next node + this.startIndex = endIndex + 1; + } + /** @internal */ + oncomment(start, endIndex, offset) { + var _a, _b, _c, _d; + this.endIndex = endIndex; + (_b = (_a = this.cbs).oncomment) === null || _b === void 0 ? void 0 : _b.call(_a, this.getSlice(start, endIndex - offset)); + (_d = (_c = this.cbs).oncommentend) === null || _d === void 0 ? void 0 : _d.call(_c); + // Set `startIndex` for next node + this.startIndex = endIndex + 1; + } + /** @internal */ + oncdata(start, endIndex, offset) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + this.endIndex = endIndex; + const value = this.getSlice(start, endIndex - offset); + if (!this.htmlMode || this.options.recognizeCDATA) { + (_b = (_a = this.cbs).oncdatastart) === null || _b === void 0 ? void 0 : _b.call(_a); + (_d = (_c = this.cbs).ontext) === null || _d === void 0 ? void 0 : _d.call(_c, value); + (_f = (_e = this.cbs).oncdataend) === null || _f === void 0 ? void 0 : _f.call(_e); + } + else { + (_h = (_g = this.cbs).oncomment) === null || _h === void 0 ? void 0 : _h.call(_g, `[CDATA[${value}]]`); + (_k = (_j = this.cbs).oncommentend) === null || _k === void 0 ? void 0 : _k.call(_j); + } + // Set `startIndex` for next node + this.startIndex = endIndex + 1; + } + /** @internal */ + onend() { + var _a, _b; + if (this.cbs.onclosetag) { + // Set the end index for all remaining tags + this.endIndex = this.startIndex; + for (let index = 0; index < this.stack.length; index++) { + this.cbs.onclosetag(this.stack[index], true); + } + } + (_b = (_a = this.cbs).onend) === null || _b === void 0 ? void 0 : _b.call(_a); + } + /** + * Resets the parser to a blank state, ready to parse a new HTML document + */ + reset() { + var _a, _b, _c, _d; + (_b = (_a = this.cbs).onreset) === null || _b === void 0 ? void 0 : _b.call(_a); + this.tokenizer.reset(); + this.tagname = ""; + this.attribname = ""; + this.attribs = null; + this.stack.length = 0; + this.startIndex = 0; + this.endIndex = 0; + (_d = (_c = this.cbs).onparserinit) === null || _d === void 0 ? void 0 : _d.call(_c, this); + this.buffers.length = 0; + this.foreignContext.length = 0; + this.foreignContext.unshift(!this.htmlMode); + this.bufferOffset = 0; + this.writeIndex = 0; + this.ended = false; + } + /** + * Resets the parser, then parses a complete document and + * pushes it to the handler. + * + * @param data Document to parse. + */ + parseComplete(data) { + this.reset(); + this.end(data); + } + getSlice(start, end) { + while (start - this.bufferOffset >= this.buffers[0].length) { + this.shiftBuffer(); + } + let slice = this.buffers[0].slice(start - this.bufferOffset, end - this.bufferOffset); + while (end - this.bufferOffset > this.buffers[0].length) { + this.shiftBuffer(); + slice += this.buffers[0].slice(0, end - this.bufferOffset); + } + return slice; + } + shiftBuffer() { + this.bufferOffset += this.buffers[0].length; + this.writeIndex--; + this.buffers.shift(); + } + /** + * Parses a chunk of data and calls the corresponding callbacks. + * + * @param chunk Chunk to parse. + */ + write(chunk) { + var _a, _b; + if (this.ended) { + (_b = (_a = this.cbs).onerror) === null || _b === void 0 ? void 0 : _b.call(_a, new Error(".write() after done!")); + return; + } + this.buffers.push(chunk); + if (this.tokenizer.running) { + this.tokenizer.write(chunk); + this.writeIndex++; + } + } + /** + * Parses the end of the buffer and clears the stack, calls onend. + * + * @param chunk Optional final chunk to parse. + */ + end(chunk) { + var _a, _b; + if (this.ended) { + (_b = (_a = this.cbs).onerror) === null || _b === void 0 ? void 0 : _b.call(_a, new Error(".end() after done!")); + return; + } + if (chunk) + this.write(chunk); + this.ended = true; + this.tokenizer.end(); + } + /** + * Pauses parsing. The parser won't emit events until `resume` is called. + */ + pause() { + this.tokenizer.pause(); + } + /** + * Resumes parsing after `pause` was called. + */ + resume() { + this.tokenizer.resume(); + while (this.tokenizer.running && + this.writeIndex < this.buffers.length) { + this.tokenizer.write(this.buffers[this.writeIndex++]); + } + if (this.ended) + this.tokenizer.end(); + } + /** + * Alias of `write`, for backwards compatibility. + * + * @param chunk Chunk to parse. + * @deprecated + */ + parseChunk(chunk) { + this.write(chunk); + } + /** + * Alias of `end`, for backwards compatibility. + * + * @param chunk Optional final chunk to parse. + * @deprecated + */ + done(chunk) { + this.end(chunk); + } + }; + + /** Types of elements found in htmlparser2's DOM */ + var ElementType$1; + (function (ElementType) { + /** Type for the root element of a document */ + ElementType["Root"] = "root"; + /** Type for Text */ + ElementType["Text"] = "text"; + /** Type for <? ... ?> */ + ElementType["Directive"] = "directive"; + /** Type for <!-- ... --> */ + ElementType["Comment"] = "comment"; + /** Type for <script> tags */ + ElementType["Script"] = "script"; + /** Type for <style> tags */ + ElementType["Style"] = "style"; + /** Type for Any tag */ + ElementType["Tag"] = "tag"; + /** Type for <![CDATA[ ... ]]> */ + ElementType["CDATA"] = "cdata"; + /** Type for <!doctype ...> */ + ElementType["Doctype"] = "doctype"; + })(ElementType$1 || (ElementType$1 = {})); + /** + * Tests whether an element is a tag or not. + * + * @param elem Element to test + */ + function isTag$3(elem) { + return (elem.type === ElementType$1.Tag || + elem.type === ElementType$1.Script || + elem.type === ElementType$1.Style); + } + // Exports for backwards compatibility + /** Type for the root element of a document */ + const Root$7 = ElementType$1.Root; + /** Type for Text */ + const Text$4 = ElementType$1.Text; + /** Type for <? ... ?> */ + const Directive = ElementType$1.Directive; + /** Type for <!-- ... --> */ + const Comment$9 = ElementType$1.Comment; + /** Type for <script> tags */ + const Script = ElementType$1.Script; + /** Type for <style> tags */ + const Style = ElementType$1.Style; + /** Type for Any tag */ + const Tag = ElementType$1.Tag; + /** Type for <![CDATA[ ... ]]> */ + const CDATA$2 = ElementType$1.CDATA; + /** Type for <!doctype ...> */ + const Doctype = ElementType$1.Doctype; + + var index = /*#__PURE__*/Object.freeze({ + __proto__: null, + CDATA: CDATA$2, + Comment: Comment$9, + Directive: Directive, + Doctype: Doctype, + get ElementType () { return ElementType$1; }, + Root: Root$7, + Script: Script, + Style: Style, + Tag: Tag, + Text: Text$4, + isTag: isTag$3 + }); + + /** + * This object will be used as the prototype for Nodes when creating a + * DOM-Level-1-compliant structure. + */ + let Node$8 = class Node { + constructor() { + /** Parent of the node */ + this.parent = null; + /** Previous sibling */ + this.prev = null; + /** Next sibling */ + this.next = null; + /** The start index of the node. Requires `withStartIndices` on the handler to be `true. */ + this.startIndex = null; + /** The end index of the node. Requires `withEndIndices` on the handler to be `true. */ + this.endIndex = null; + } + // Read-write aliases for properties + /** + * Same as {@link parent}. + * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + get parentNode() { + return this.parent; + } + set parentNode(parent) { + this.parent = parent; + } + /** + * Same as {@link prev}. + * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + get previousSibling() { + return this.prev; + } + set previousSibling(prev) { + this.prev = prev; + } + /** + * Same as {@link next}. + * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + get nextSibling() { + return this.next; + } + set nextSibling(next) { + this.next = next; + } + /** + * Clone this node, and optionally its children. + * + * @param recursive Clone child nodes as well. + * @returns A clone of the node. + */ + cloneNode(recursive = false) { + return cloneNode$2(this, recursive); + } + }; + /** + * A node that contains some data. + */ + let DataNode$1 = class DataNode extends Node$8 { + /** + * @param data The content of the data node + */ + constructor(data) { + super(); + this.data = data; + } + /** + * Same as {@link data}. + * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + get nodeValue() { + return this.data; + } + set nodeValue(data) { + this.data = data; + } + }; + /** + * Text within the document. + */ + let Text$3 = class Text extends DataNode$1 { + constructor() { + super(...arguments); + this.type = ElementType$1.Text; + } + get nodeType() { + return 3; + } + }; + /** + * Comments within the document. + */ + let Comment$8 = class Comment extends DataNode$1 { + constructor() { + super(...arguments); + this.type = ElementType$1.Comment; + } + get nodeType() { + return 8; + } + }; + /** + * Processing instructions, including doc types. + */ + let ProcessingInstruction$1 = class ProcessingInstruction extends DataNode$1 { + constructor(name, data) { + super(data); + this.name = name; + this.type = ElementType$1.Directive; + } + get nodeType() { + return 1; + } + }; + /** + * A `Node` that can have children. + */ + let NodeWithChildren$1 = class NodeWithChildren extends Node$8 { + /** + * @param children Children of the node. Only certain node types can have children. + */ + constructor(children) { + super(); + this.children = children; + } + // Aliases + /** First child of the node. */ + get firstChild() { + var _a; + return (_a = this.children[0]) !== null && _a !== void 0 ? _a : null; + } + /** Last child of the node. */ + get lastChild() { + return this.children.length > 0 + ? this.children[this.children.length - 1] + : null; + } + /** + * Same as {@link children}. + * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + get childNodes() { + return this.children; + } + set childNodes(children) { + this.children = children; + } + }; + let CDATA$1 = class CDATA extends NodeWithChildren$1 { + constructor() { + super(...arguments); + this.type = ElementType$1.CDATA; + } + get nodeType() { + return 4; + } + }; + /** + * The root node of the document. + */ + let Document$7 = class Document extends NodeWithChildren$1 { + constructor() { + super(...arguments); + this.type = ElementType$1.Root; + } + get nodeType() { + return 9; + } + }; + /** + * An element within the DOM. + */ + let Element$3 = class Element extends NodeWithChildren$1 { + /** + * @param name Name of the tag, eg. `div`, `span`. + * @param attribs Object mapping attribute names to attribute values. + * @param children Children of the node. + */ + constructor(name, attribs, children = [], type = name === "script" + ? ElementType$1.Script + : name === "style" + ? ElementType$1.Style + : ElementType$1.Tag) { + super(children); + this.name = name; + this.attribs = attribs; + this.type = type; + } + get nodeType() { + return 1; + } + // DOM Level 1 aliases + /** + * Same as {@link name}. + * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + get tagName() { + return this.name; + } + set tagName(name) { + this.name = name; + } + get attributes() { + return Object.keys(this.attribs).map((name) => { + var _a, _b; + return ({ + name, + value: this.attribs[name], + namespace: (_a = this["x-attribsNamespace"]) === null || _a === void 0 ? void 0 : _a[name], + prefix: (_b = this["x-attribsPrefix"]) === null || _b === void 0 ? void 0 : _b[name], + }); + }); + } + }; + /** + * @param node Node to check. + * @returns `true` if the node is a `Element`, `false` otherwise. + */ + function isTag$2(node) { + return isTag$3(node); + } + /** + * @param node Node to check. + * @returns `true` if the node has the type `CDATA`, `false` otherwise. + */ + function isCDATA$1(node) { + return node.type === ElementType$1.CDATA; + } + /** + * @param node Node to check. + * @returns `true` if the node has the type `Text`, `false` otherwise. + */ + function isText$1(node) { + return node.type === ElementType$1.Text; + } + /** + * @param node Node to check. + * @returns `true` if the node has the type `Comment`, `false` otherwise. + */ + function isComment$1(node) { + return node.type === ElementType$1.Comment; + } + /** + * @param node Node to check. + * @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise. + */ + function isDirective$1(node) { + return node.type === ElementType$1.Directive; + } + /** + * @param node Node to check. + * @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise. + */ + function isDocument$1(node) { + return node.type === ElementType$1.Root; + } + /** + * @param node Node to check. + * @returns `true` if the node has children, `false` otherwise. + */ + function hasChildren$1(node) { + return Object.prototype.hasOwnProperty.call(node, "children"); + } + /** + * Clone a node, and optionally its children. + * + * @param recursive Clone child nodes as well. + * @returns A clone of the node. + */ + function cloneNode$2(node, recursive = false) { + let result; + if (isText$1(node)) { + result = new Text$3(node.data); + } + else if (isComment$1(node)) { + result = new Comment$8(node.data); + } + else if (isTag$2(node)) { + const children = recursive ? cloneChildren$1(node.children) : []; + const clone = new Element$3(node.name, { ...node.attribs }, children); + children.forEach((child) => (child.parent = clone)); + if (node.namespace != null) { + clone.namespace = node.namespace; + } + if (node["x-attribsNamespace"]) { + clone["x-attribsNamespace"] = { ...node["x-attribsNamespace"] }; + } + if (node["x-attribsPrefix"]) { + clone["x-attribsPrefix"] = { ...node["x-attribsPrefix"] }; + } + result = clone; + } + else if (isCDATA$1(node)) { + const children = recursive ? cloneChildren$1(node.children) : []; + const clone = new CDATA$1(children); + children.forEach((child) => (child.parent = clone)); + result = clone; + } + else if (isDocument$1(node)) { + const children = recursive ? cloneChildren$1(node.children) : []; + const clone = new Document$7(children); + children.forEach((child) => (child.parent = clone)); + if (node["x-mode"]) { + clone["x-mode"] = node["x-mode"]; + } + result = clone; + } + else if (isDirective$1(node)) { + const instruction = new ProcessingInstruction$1(node.name, node.data); + if (node["x-name"] != null) { + instruction["x-name"] = node["x-name"]; + instruction["x-publicId"] = node["x-publicId"]; + instruction["x-systemId"] = node["x-systemId"]; + } + result = instruction; + } + else { + throw new Error(`Not implemented yet: ${node.type}`); + } + result.startIndex = node.startIndex; + result.endIndex = node.endIndex; + if (node.sourceCodeLocation != null) { + result.sourceCodeLocation = node.sourceCodeLocation; + } + return result; + } + function cloneChildren$1(childs) { + const children = childs.map((child) => cloneNode$2(child, true)); + for (let i = 1; i < children.length; i++) { + children[i].prev = children[i - 1]; + children[i - 1].next = children[i]; + } + return children; + } + + // Default options + const defaultOpts = { + withStartIndices: false, + withEndIndices: false, + xmlMode: false, + }; + class DomHandler { + /** + * @param callback Called once parsing has completed. + * @param options Settings for the handler. + * @param elementCB Callback whenever a tag is closed. + */ + constructor(callback, options, elementCB) { + /** The elements of the DOM */ + this.dom = []; + /** The root element for the DOM */ + this.root = new Document$7(this.dom); + /** Indicated whether parsing has been completed. */ + this.done = false; + /** Stack of open tags. */ + this.tagStack = [this.root]; + /** A data node that is still being written to. */ + this.lastNode = null; + /** Reference to the parser instance. Used for location information. */ + this.parser = null; + // Make it possible to skip arguments, for backwards-compatibility + if (typeof options === "function") { + elementCB = options; + options = defaultOpts; + } + if (typeof callback === "object") { + options = callback; + callback = undefined; + } + this.callback = callback !== null && callback !== void 0 ? callback : null; + this.options = options !== null && options !== void 0 ? options : defaultOpts; + this.elementCB = elementCB !== null && elementCB !== void 0 ? elementCB : null; + } + onparserinit(parser) { + this.parser = parser; + } + // Resets the handler back to starting state + onreset() { + this.dom = []; + this.root = new Document$7(this.dom); + this.done = false; + this.tagStack = [this.root]; + this.lastNode = null; + this.parser = null; + } + // Signals the handler that parsing is done + onend() { + if (this.done) + return; + this.done = true; + this.parser = null; + this.handleCallback(null); + } + onerror(error) { + this.handleCallback(error); + } + onclosetag() { + this.lastNode = null; + const elem = this.tagStack.pop(); + if (this.options.withEndIndices) { + elem.endIndex = this.parser.endIndex; + } + if (this.elementCB) + this.elementCB(elem); + } + onopentag(name, attribs) { + const type = this.options.xmlMode ? ElementType$1.Tag : undefined; + const element = new Element$3(name, attribs, undefined, type); + this.addNode(element); + this.tagStack.push(element); + } + ontext(data) { + const { lastNode } = this; + if (lastNode && lastNode.type === ElementType$1.Text) { + lastNode.data += data; + if (this.options.withEndIndices) { + lastNode.endIndex = this.parser.endIndex; + } + } + else { + const node = new Text$3(data); + this.addNode(node); + this.lastNode = node; + } + } + oncomment(data) { + if (this.lastNode && this.lastNode.type === ElementType$1.Comment) { + this.lastNode.data += data; + return; + } + const node = new Comment$8(data); + this.addNode(node); + this.lastNode = node; + } + oncommentend() { + this.lastNode = null; + } + oncdatastart() { + const text = new Text$3(""); + const node = new CDATA$1([text]); + this.addNode(node); + text.parent = node; + this.lastNode = text; + } + oncdataend() { + this.lastNode = null; + } + onprocessinginstruction(name, data) { + const node = new ProcessingInstruction$1(name, data); + this.addNode(node); + } + handleCallback(error) { + if (typeof this.callback === "function") { + this.callback(error, this.dom); + } + else if (error) { + throw error; + } + } + addNode(node) { + const parent = this.tagStack[this.tagStack.length - 1]; + const previousSibling = parent.children[parent.children.length - 1]; + if (this.options.withStartIndices) { + node.startIndex = this.parser.startIndex; + } + if (this.options.withEndIndices) { + node.endIndex = this.parser.endIndex; + } + parent.children.push(node); + if (previousSibling) { + node.prev = previousSibling; + previousSibling.next = node; + } + node.parent = parent; + this.lastNode = null; + } + } + + const xmlReplacer = /["&'<>$\x80-\uFFFF]/g; + const xmlCodeMap = new Map([ + [34, """], + [38, "&"], + [39, "'"], + [60, "<"], + [62, ">"], + ]); + // For compatibility with node < 4, we wrap `codePointAt` + const getCodePoint = + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + String.prototype.codePointAt != null + ? (str, index) => str.codePointAt(index) + : // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + (c, index) => (c.charCodeAt(index) & 0xfc00) === 0xd800 + ? (c.charCodeAt(index) - 0xd800) * 0x400 + + c.charCodeAt(index + 1) - + 0xdc00 + + 0x10000 + : c.charCodeAt(index); + /** + * Encodes all non-ASCII characters, as well as characters not valid in XML + * documents using XML entities. + * + * If a character has no equivalent entity, a + * numeric hexadecimal reference (eg. `ü`) will be used. + */ + function encodeXML(str) { + let ret = ""; + let lastIdx = 0; + let match; + while ((match = xmlReplacer.exec(str)) !== null) { + const i = match.index; + const char = str.charCodeAt(i); + const next = xmlCodeMap.get(char); + if (next !== undefined) { + ret += str.substring(lastIdx, i) + next; + lastIdx = i + 1; + } + else { + ret += `${str.substring(lastIdx, i)}&#x${getCodePoint(str, i).toString(16)};`; + // Increase by 1 if we have a surrogate pair + lastIdx = xmlReplacer.lastIndex += Number((char & 0xfc00) === 0xd800); + } + } + return ret + str.substr(lastIdx); + } + /** + * Creates a function that escapes all characters matched by the given regular + * expression using the given map of characters to escape to their entities. + * + * @param regex Regular expression to match characters to escape. + * @param map Map of characters to escape to their entities. + * + * @returns Function that escapes all characters matched by the given regular + * expression using the given map of characters to escape to their entities. + */ + function getEscaper(regex, map) { + return function escape(data) { + let match; + let lastIdx = 0; + let result = ""; + while ((match = regex.exec(data))) { + if (lastIdx !== match.index) { + result += data.substring(lastIdx, match.index); + } + // We know that this character will be in the map. + result += map.get(match[0].charCodeAt(0)); + // Every match will be of length 1 + lastIdx = match.index + 1; + } + return result + data.substring(lastIdx); + }; + } + /** + * Encodes all characters that have to be escaped in HTML attributes, + * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}. + * + * @param data String to escape. + */ + const escapeAttribute = getEscaper(/["&\u00A0]/g, new Map([ + [34, """], + [38, "&"], + [160, " "], + ])); + /** + * Encodes all characters that have to be escaped in HTML text, + * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}. + * + * @param data String to escape. + */ + const escapeText = getEscaper(/[&<>\u00A0]/g, new Map([ + [38, "&"], + [60, "<"], + [62, ">"], + [160, " "], + ])); + + const elementNames = new Map([ + "altGlyph", + "altGlyphDef", + "altGlyphItem", + "animateColor", + "animateMotion", + "animateTransform", + "clipPath", + "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", + "foreignObject", + "glyphRef", + "linearGradient", + "radialGradient", + "textPath", + ].map((val) => [val.toLowerCase(), val])); + const attributeNames = new Map([ + "definitionURL", + "attributeName", + "attributeType", + "baseFrequency", + "baseProfile", + "calcMode", + "clipPathUnits", + "diffuseConstant", + "edgeMode", + "filterUnits", + "glyphRef", + "gradientTransform", + "gradientUnits", + "kernelMatrix", + "kernelUnitLength", + "keyPoints", + "keySplines", + "keyTimes", + "lengthAdjust", + "limitingConeAngle", + "markerHeight", + "markerUnits", + "markerWidth", + "maskContentUnits", + "maskUnits", + "numOctaves", + "pathLength", + "patternContentUnits", + "patternTransform", + "patternUnits", + "pointsAtX", + "pointsAtY", + "pointsAtZ", + "preserveAlpha", + "preserveAspectRatio", + "primitiveUnits", + "refX", + "refY", + "repeatCount", + "repeatDur", + "requiredExtensions", + "requiredFeatures", + "specularConstant", + "specularExponent", + "spreadMethod", + "startOffset", + "stdDeviation", + "stitchTiles", + "surfaceScale", + "systemLanguage", + "tableValues", + "targetX", + "targetY", + "textLength", + "viewBox", + "viewTarget", + "xChannelSelector", + "yChannelSelector", + "zoomAndPan", + ].map((val) => [val.toLowerCase(), val])); + + /* + * Module dependencies + */ + const unencodedElements$1 = new Set([ + "style", + "script", + "xmp", + "iframe", + "noembed", + "noframes", + "plaintext", + "noscript", + ]); + function replaceQuotes$1(value) { + return value.replace(/"/g, """); + } + /** + * Format attributes + */ + function formatAttributes$1(attributes, opts) { + var _a; + if (!attributes) + return; + const encode = ((_a = opts.encodeEntities) !== null && _a !== void 0 ? _a : opts.decodeEntities) === false + ? replaceQuotes$1 + : opts.xmlMode || opts.encodeEntities !== "utf8" + ? encodeXML + : escapeAttribute; + return Object.keys(attributes) + .map((key) => { + var _a, _b; + const value = (_a = attributes[key]) !== null && _a !== void 0 ? _a : ""; + if (opts.xmlMode === "foreign") { + /* Fix up mixed-case attribute names */ + key = (_b = attributeNames.get(key)) !== null && _b !== void 0 ? _b : key; + } + if (!opts.emptyAttrs && !opts.xmlMode && value === "") { + return key; + } + return `${key}="${encode(value)}"`; + }) + .join(" "); + } + /** + * Self-enclosing tags + */ + const singleTag$1 = new Set([ + "area", + "base", + "basefont", + "br", + "col", + "command", + "embed", + "frame", + "hr", + "img", + "input", + "isindex", + "keygen", + "link", + "meta", + "param", + "source", + "track", + "wbr", + ]); + /** + * Renders a DOM node or an array of DOM nodes to a string. + * + * Can be thought of as the equivalent of the `outerHTML` of the passed node(s). + * + * @param node Node to be rendered. + * @param options Changes serialization behavior + */ + function render$1(node, options = {}) { + const nodes = "length" in node ? node : [node]; + let output = ""; + for (let i = 0; i < nodes.length; i++) { + output += renderNode$1(nodes[i], options); + } + return output; + } + function renderNode$1(node, options) { + switch (node.type) { + case Root$7: + return render$1(node.children, options); + // @ts-expect-error We don't use `Doctype` yet + case Doctype: + case Directive: + return renderDirective$1(node); + case Comment$9: + return renderComment$1(node); + case CDATA$2: + return renderCdata$1(node); + case Script: + case Style: + case Tag: + return renderTag$1(node, options); + case Text$4: + return renderText$1(node, options); + } + } + const foreignModeIntegrationPoints$1 = new Set([ + "mi", + "mo", + "mn", + "ms", + "mtext", + "annotation-xml", + "foreignObject", + "desc", + "title", + ]); + const foreignElements$1 = new Set(["svg", "math"]); + function renderTag$1(elem, opts) { + var _a; + // Handle SVG / MathML in HTML + if (opts.xmlMode === "foreign") { + /* Fix up mixed-case element names */ + elem.name = (_a = elementNames.get(elem.name)) !== null && _a !== void 0 ? _a : elem.name; + /* Exit foreign mode at integration points */ + if (elem.parent && + foreignModeIntegrationPoints$1.has(elem.parent.name)) { + opts = { ...opts, xmlMode: false }; + } + } + if (!opts.xmlMode && foreignElements$1.has(elem.name)) { + opts = { ...opts, xmlMode: "foreign" }; + } + let tag = `<${elem.name}`; + const attribs = formatAttributes$1(elem.attribs, opts); + if (attribs) { + tag += ` ${attribs}`; + } + if (elem.children.length === 0 && + (opts.xmlMode + ? // In XML mode or foreign mode, and user hasn't explicitly turned off self-closing tags + opts.selfClosingTags !== false + : // User explicitly asked for self-closing tags, even in HTML mode + opts.selfClosingTags && singleTag$1.has(elem.name))) { + if (!opts.xmlMode) + tag += " "; + tag += "/>"; + } + else { + tag += ">"; + if (elem.children.length > 0) { + tag += render$1(elem.children, opts); + } + if (opts.xmlMode || !singleTag$1.has(elem.name)) { + tag += `</${elem.name}>`; + } + } + return tag; + } + function renderDirective$1(elem) { + return `<${elem.data}>`; + } + function renderText$1(elem, opts) { + var _a; + let data = elem.data || ""; + // If entities weren't decoded, no need to encode them back + if (((_a = opts.encodeEntities) !== null && _a !== void 0 ? _a : opts.decodeEntities) !== false && + !(!opts.xmlMode && + elem.parent && + unencodedElements$1.has(elem.parent.name))) { + data = + opts.xmlMode || opts.encodeEntities !== "utf8" + ? encodeXML(data) + : escapeText(data); + } + return data; + } + function renderCdata$1(elem) { + return `<![CDATA[${elem.children[0].data}]]>`; + } + function renderComment$1(elem) { + return `<!--${elem.data}-->`; + } + + /** + * @category Stringify + * @deprecated Use the `dom-serializer` module directly. + * @param node Node to get the outer HTML of. + * @param options Options for serialization. + * @returns `node`'s outer HTML. + */ + function getOuterHTML$1(node, options) { + return render$1(node, options); + } + /** + * @category Stringify + * @deprecated Use the `dom-serializer` module directly. + * @param node Node to get the inner HTML of. + * @param options Options for serialization. + * @returns `node`'s inner HTML. + */ + function getInnerHTML$1(node, options) { + return hasChildren$1(node) + ? node.children.map((node) => getOuterHTML$1(node, options)).join("") + : ""; + } + /** + * Get a node's inner text. Same as `textContent`, but inserts newlines for `<br>` tags. Ignores comments. + * + * @category Stringify + * @deprecated Use `textContent` instead. + * @param node Node to get the inner text of. + * @returns `node`'s inner text. + */ + function getText$2(node) { + if (Array.isArray(node)) + return node.map(getText$2).join(""); + if (isTag$2(node)) + return node.name === "br" ? "\n" : getText$2(node.children); + if (isCDATA$1(node)) + return getText$2(node.children); + if (isText$1(node)) + return node.data; + return ""; + } + /** + * Get a node's text content. Ignores comments. + * + * @category Stringify + * @param node Node to get the text content of. + * @returns `node`'s text content. + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent} + */ + function textContent$1(node) { + if (Array.isArray(node)) + return node.map(textContent$1).join(""); + if (hasChildren$1(node) && !isComment$1(node)) { + return textContent$1(node.children); + } + if (isText$1(node)) + return node.data; + return ""; + } + /** + * Get a node's inner text, ignoring `<script>` and `<style>` tags. Ignores comments. + * + * @category Stringify + * @param node Node to get the inner text of. + * @returns `node`'s inner text. + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/innerText} + */ + function innerText$1(node) { + if (Array.isArray(node)) + return node.map(innerText$1).join(""); + if (hasChildren$1(node) && (node.type === ElementType$1.Tag || isCDATA$1(node))) { + return innerText$1(node.children); + } + if (isText$1(node)) + return node.data; + return ""; + } + + /** + * Get a node's children. + * + * @category Traversal + * @param elem Node to get the children of. + * @returns `elem`'s children, or an empty array. + */ + function getChildren$2(elem) { + return hasChildren$1(elem) ? elem.children : []; + } + /** + * Get a node's parent. + * + * @category Traversal + * @param elem Node to get the parent of. + * @returns `elem`'s parent node, or `null` if `elem` is a root node. + */ + function getParent$2(elem) { + return elem.parent || null; + } + /** + * Gets an elements siblings, including the element itself. + * + * Attempts to get the children through the element's parent first. If we don't + * have a parent (the element is a root node), we walk the element's `prev` & + * `next` to get all remaining nodes. + * + * @category Traversal + * @param elem Element to get the siblings of. + * @returns `elem`'s siblings, including `elem`. + */ + function getSiblings$2(elem) { + const parent = getParent$2(elem); + if (parent != null) + return getChildren$2(parent); + const siblings = [elem]; + let { prev, next } = elem; + while (prev != null) { + siblings.unshift(prev); + ({ prev } = prev); + } + while (next != null) { + siblings.push(next); + ({ next } = next); + } + return siblings; + } + /** + * Gets an attribute from an element. + * + * @category Traversal + * @param elem Element to check. + * @param name Attribute name to retrieve. + * @returns The element's attribute value, or `undefined`. + */ + function getAttributeValue$2(elem, name) { + var _a; + return (_a = elem.attribs) === null || _a === void 0 ? void 0 : _a[name]; + } + /** + * Checks whether an element has an attribute. + * + * @category Traversal + * @param elem Element to check. + * @param name Attribute name to look for. + * @returns Returns whether `elem` has the attribute `name`. + */ + function hasAttrib$2(elem, name) { + return (elem.attribs != null && + Object.prototype.hasOwnProperty.call(elem.attribs, name) && + elem.attribs[name] != null); + } + /** + * Get the tag name of an element. + * + * @category Traversal + * @param elem The element to get the name for. + * @returns The tag name of `elem`. + */ + function getName$2(elem) { + return elem.name; + } + /** + * Returns the next element sibling of a node. + * + * @category Traversal + * @param elem The element to get the next sibling of. + * @returns `elem`'s next sibling that is a tag, or `null` if there is no next + * sibling. + */ + function nextElementSibling$2(elem) { + let { next } = elem; + while (next !== null && !isTag$2(next)) + ({ next } = next); + return next; + } + /** + * Returns the previous element sibling of a node. + * + * @category Traversal + * @param elem The element to get the previous sibling of. + * @returns `elem`'s previous sibling that is a tag, or `null` if there is no + * previous sibling. + */ + function prevElementSibling$1(elem) { + let { prev } = elem; + while (prev !== null && !isTag$2(prev)) + ({ prev } = prev); + return prev; + } + + /** + * Remove an element from the dom + * + * @category Manipulation + * @param elem The element to be removed + */ + function removeElement$1(elem) { + if (elem.prev) + elem.prev.next = elem.next; + if (elem.next) + elem.next.prev = elem.prev; + if (elem.parent) { + const childs = elem.parent.children; + const childsIndex = childs.lastIndexOf(elem); + if (childsIndex >= 0) { + childs.splice(childsIndex, 1); + } + } + elem.next = null; + elem.prev = null; + elem.parent = null; + } + /** + * Replace an element in the dom + * + * @category Manipulation + * @param elem The element to be replaced + * @param replacement The element to be added + */ + function replaceElement$1(elem, replacement) { + const prev = (replacement.prev = elem.prev); + if (prev) { + prev.next = replacement; + } + const next = (replacement.next = elem.next); + if (next) { + next.prev = replacement; + } + const parent = (replacement.parent = elem.parent); + if (parent) { + const childs = parent.children; + childs[childs.lastIndexOf(elem)] = replacement; + elem.parent = null; + } + } + /** + * Append a child to an element. + * + * @category Manipulation + * @param parent The element to append to. + * @param child The element to be added as a child. + */ + function appendChild$1(parent, child) { + removeElement$1(child); + child.next = null; + child.parent = parent; + if (parent.children.push(child) > 1) { + const sibling = parent.children[parent.children.length - 2]; + sibling.next = child; + child.prev = sibling; + } + else { + child.prev = null; + } + } + /** + * Append an element after another. + * + * @category Manipulation + * @param elem The element to append after. + * @param next The element be added. + */ + function append$2(elem, next) { + removeElement$1(next); + const { parent } = elem; + const currNext = elem.next; + next.next = currNext; + next.prev = elem; + elem.next = next; + next.parent = parent; + if (currNext) { + currNext.prev = next; + if (parent) { + const childs = parent.children; + childs.splice(childs.lastIndexOf(currNext), 0, next); + } + } + else if (parent) { + parent.children.push(next); + } + } + /** + * Prepend a child to an element. + * + * @category Manipulation + * @param parent The element to prepend before. + * @param child The element to be added as a child. + */ + function prependChild$1(parent, child) { + removeElement$1(child); + child.parent = parent; + child.prev = null; + if (parent.children.unshift(child) !== 1) { + const sibling = parent.children[1]; + sibling.prev = child; + child.next = sibling; + } + else { + child.next = null; + } + } + /** + * Prepend an element before another. + * + * @category Manipulation + * @param elem The element to prepend before. + * @param prev The element be added. + */ + function prepend$1(elem, prev) { + removeElement$1(prev); + const { parent } = elem; + if (parent) { + const childs = parent.children; + childs.splice(childs.indexOf(elem), 0, prev); + } + if (elem.prev) { + elem.prev.next = prev; + } + prev.parent = parent; + prev.prev = elem.prev; + prev.next = elem; + elem.prev = prev; + } + + /** + * Search a node and its children for nodes passing a test function. If `node` is not an array, it will be wrapped in one. + * + * @category Querying + * @param test Function to test nodes on. + * @param node Node to search. Will be included in the result set if it matches. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes passing `test`. + */ + function filter$3(test, node, recurse = true, limit = Infinity) { + return find$1(test, Array.isArray(node) ? node : [node], recurse, limit); + } + /** + * Search an array of nodes and their children for nodes passing a test function. + * + * @category Querying + * @param test Function to test nodes on. + * @param nodes Array of nodes to search. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes passing `test`. + */ + function find$1(test, nodes, recurse, limit) { + const result = []; + /** Stack of the arrays we are looking at. */ + const nodeStack = [nodes]; + /** Stack of the indices within the arrays. */ + const indexStack = [0]; + for (;;) { + // First, check if the current array has any more elements to look at. + if (indexStack[0] >= nodeStack[0].length) { + // If we have no more arrays to look at, we are done. + if (indexStack.length === 1) { + return result; + } + // Otherwise, remove the current array from the stack. + nodeStack.shift(); + indexStack.shift(); + // Loop back to the start to continue with the next array. + continue; + } + const elem = nodeStack[0][indexStack[0]++]; + if (test(elem)) { + result.push(elem); + if (--limit <= 0) + return result; + } + if (recurse && hasChildren$1(elem) && elem.children.length > 0) { + /* + * Add the children to the stack. We are depth-first, so this is + * the next array we look at. + */ + indexStack.unshift(0); + nodeStack.unshift(elem.children); + } + } + } + /** + * Finds the first element inside of an array that matches a test function. This is an alias for `Array.prototype.find`. + * + * @category Querying + * @param test Function to test nodes on. + * @param nodes Array of nodes to search. + * @returns The first node in the array that passes `test`. + * @deprecated Use `Array.prototype.find` directly. + */ + function findOneChild$1(test, nodes) { + return nodes.find(test); + } + /** + * Finds one element in a tree that passes a test. + * + * @category Querying + * @param test Function to test nodes on. + * @param nodes Node or array of nodes to search. + * @param recurse Also consider child nodes. + * @returns The first node that passes `test`. + */ + function findOne$2(test, nodes, recurse = true) { + let elem = null; + for (let i = 0; i < nodes.length && !elem; i++) { + const node = nodes[i]; + if (!isTag$2(node)) { + continue; + } + else if (test(node)) { + elem = node; + } + else if (recurse && node.children.length > 0) { + elem = findOne$2(test, node.children, true); + } + } + return elem; + } + /** + * Checks if a tree of nodes contains at least one node passing a test. + * + * @category Querying + * @param test Function to test nodes on. + * @param nodes Array of nodes to search. + * @returns Whether a tree of nodes contains at least one node passing the test. + */ + function existsOne$2(test, nodes) { + return nodes.some((checked) => isTag$2(checked) && + (test(checked) || existsOne$2(test, checked.children))); + } + /** + * Search an array of nodes and their children for elements passing a test function. + * + * Same as `find`, but limited to elements and with less options, leading to reduced complexity. + * + * @category Querying + * @param test Function to test nodes on. + * @param nodes Array of nodes to search. + * @returns All nodes passing `test`. + */ + function findAll$2(test, nodes) { + const result = []; + const nodeStack = [nodes]; + const indexStack = [0]; + for (;;) { + if (indexStack[0] >= nodeStack[0].length) { + if (nodeStack.length === 1) { + return result; + } + // Otherwise, remove the current array from the stack. + nodeStack.shift(); + indexStack.shift(); + // Loop back to the start to continue with the next array. + continue; + } + const elem = nodeStack[0][indexStack[0]++]; + if (!isTag$2(elem)) + continue; + if (test(elem)) + result.push(elem); + if (elem.children.length > 0) { + indexStack.unshift(0); + nodeStack.unshift(elem.children); + } + } + } + + /** + * A map of functions to check nodes against. + */ + const Checks$1 = { + tag_name(name) { + if (typeof name === "function") { + return (elem) => isTag$2(elem) && name(elem.name); + } + else if (name === "*") { + return isTag$2; + } + return (elem) => isTag$2(elem) && elem.name === name; + }, + tag_type(type) { + if (typeof type === "function") { + return (elem) => type(elem.type); + } + return (elem) => elem.type === type; + }, + tag_contains(data) { + if (typeof data === "function") { + return (elem) => isText$1(elem) && data(elem.data); + } + return (elem) => isText$1(elem) && elem.data === data; + }, + }; + /** + * Returns a function to check whether a node has an attribute with a particular + * value. + * + * @param attrib Attribute to check. + * @param value Attribute value to look for. + * @returns A function to check whether the a node has an attribute with a + * particular value. + */ + function getAttribCheck$1(attrib, value) { + if (typeof value === "function") { + return (elem) => isTag$2(elem) && value(elem.attribs[attrib]); + } + return (elem) => isTag$2(elem) && elem.attribs[attrib] === value; + } + /** + * Returns a function that returns `true` if either of the input functions + * returns `true` for a node. + * + * @param a First function to combine. + * @param b Second function to combine. + * @returns A function taking a node and returning `true` if either of the input + * functions returns `true` for the node. + */ + function combineFuncs$1(a, b) { + return (elem) => a(elem) || b(elem); + } + /** + * Returns a function that executes all checks in `options` and returns `true` + * if any of them match a node. + * + * @param options An object describing nodes to look for. + * @returns A function that executes all checks in `options` and returns `true` + * if any of them match a node. + */ + function compileTest$1(options) { + const funcs = Object.keys(options).map((key) => { + const value = options[key]; + return Object.prototype.hasOwnProperty.call(Checks$1, key) + ? Checks$1[key](value) + : getAttribCheck$1(key, value); + }); + return funcs.length === 0 ? null : funcs.reduce(combineFuncs$1); + } + /** + * Checks whether a node matches the description in `options`. + * + * @category Legacy Query Functions + * @param options An object describing nodes to look for. + * @param node The element to test. + * @returns Whether the element matches the description in `options`. + */ + function testElement$1(options, node) { + const test = compileTest$1(options); + return test ? test(node) : true; + } + /** + * Returns all nodes that match `options`. + * + * @category Legacy Query Functions + * @param options An object describing nodes to look for. + * @param nodes Nodes to search through. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes that match `options`. + */ + function getElements$1(options, nodes, recurse, limit = Infinity) { + const test = compileTest$1(options); + return test ? filter$3(test, nodes, recurse, limit) : []; + } + /** + * Returns the node with the supplied ID. + * + * @category Legacy Query Functions + * @param id The unique ID attribute value to look for. + * @param nodes Nodes to search through. + * @param recurse Also consider child nodes. + * @returns The node with the supplied ID. + */ + function getElementById$1(id, nodes, recurse = true) { + if (!Array.isArray(nodes)) + nodes = [nodes]; + return findOne$2(getAttribCheck$1("id", id), nodes, recurse); + } + /** + * Returns all nodes with the supplied `tagName`. + * + * @category Legacy Query Functions + * @param tagName Tag name to search for. + * @param nodes Nodes to search through. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes with the supplied `tagName`. + */ + function getElementsByTagName$1(tagName, nodes, recurse = true, limit = Infinity) { + return filter$3(Checks$1["tag_name"](tagName), nodes, recurse, limit); + } + /** + * Returns all nodes with the supplied `type`. + * + * @category Legacy Query Functions + * @param type Element type to look for. + * @param nodes Nodes to search through. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes with the supplied `type`. + */ + function getElementsByTagType$1(type, nodes, recurse = true, limit = Infinity) { + return filter$3(Checks$1["tag_type"](type), nodes, recurse, limit); + } + + /** + * Given an array of nodes, remove any member that is contained by another + * member. + * + * @category Helpers + * @param nodes Nodes to filter. + * @returns Remaining nodes that aren't contained by other nodes. + */ + function removeSubsets$1(nodes) { + let idx = nodes.length; + /* + * Check if each node (or one of its ancestors) is already contained in the + * array. + */ + while (--idx >= 0) { + const node = nodes[idx]; + /* + * Remove the node if it is not unique. + * We are going through the array from the end, so we only + * have to check nodes that preceed the node under consideration in the array. + */ + if (idx > 0 && nodes.lastIndexOf(node, idx - 1) >= 0) { + nodes.splice(idx, 1); + continue; + } + for (let ancestor = node.parent; ancestor; ancestor = ancestor.parent) { + if (nodes.includes(ancestor)) { + nodes.splice(idx, 1); + break; + } + } + } + return nodes; + } + /** + * @category Helpers + * @see {@link http://dom.spec.whatwg.org/#dom-node-comparedocumentposition} + */ + var DocumentPosition; + (function (DocumentPosition) { + DocumentPosition[DocumentPosition["DISCONNECTED"] = 1] = "DISCONNECTED"; + DocumentPosition[DocumentPosition["PRECEDING"] = 2] = "PRECEDING"; + DocumentPosition[DocumentPosition["FOLLOWING"] = 4] = "FOLLOWING"; + DocumentPosition[DocumentPosition["CONTAINS"] = 8] = "CONTAINS"; + DocumentPosition[DocumentPosition["CONTAINED_BY"] = 16] = "CONTAINED_BY"; + })(DocumentPosition || (DocumentPosition = {})); + /** + * Compare the position of one node against another node in any other document, + * returning a bitmask with the values from {@link DocumentPosition}. + * + * Document order: + * > There is an ordering, document order, defined on all the nodes in the + * > document corresponding to the order in which the first character of the + * > XML representation of each node occurs in the XML representation of the + * > document after expansion of general entities. Thus, the document element + * > node will be the first node. Element nodes occur before their children. + * > Thus, document order orders element nodes in order of the occurrence of + * > their start-tag in the XML (after expansion of entities). The attribute + * > nodes of an element occur after the element and before its children. The + * > relative order of attribute nodes is implementation-dependent. + * + * Source: + * http://www.w3.org/TR/DOM-Level-3-Core/glossary.html#dt-document-order + * + * @category Helpers + * @param nodeA The first node to use in the comparison + * @param nodeB The second node to use in the comparison + * @returns A bitmask describing the input nodes' relative position. + * + * See http://dom.spec.whatwg.org/#dom-node-comparedocumentposition for + * a description of these values. + */ + function compareDocumentPosition(nodeA, nodeB) { + const aParents = []; + const bParents = []; + if (nodeA === nodeB) { + return 0; + } + let current = hasChildren$1(nodeA) ? nodeA : nodeA.parent; + while (current) { + aParents.unshift(current); + current = current.parent; + } + current = hasChildren$1(nodeB) ? nodeB : nodeB.parent; + while (current) { + bParents.unshift(current); + current = current.parent; + } + const maxIdx = Math.min(aParents.length, bParents.length); + let idx = 0; + while (idx < maxIdx && aParents[idx] === bParents[idx]) { + idx++; + } + if (idx === 0) { + return DocumentPosition.DISCONNECTED; + } + const sharedParent = aParents[idx - 1]; + const siblings = sharedParent.children; + const aSibling = aParents[idx]; + const bSibling = bParents[idx]; + if (siblings.indexOf(aSibling) > siblings.indexOf(bSibling)) { + if (sharedParent === nodeB) { + return DocumentPosition.FOLLOWING | DocumentPosition.CONTAINED_BY; + } + return DocumentPosition.FOLLOWING; + } + if (sharedParent === nodeA) { + return DocumentPosition.PRECEDING | DocumentPosition.CONTAINS; + } + return DocumentPosition.PRECEDING; + } + /** + * Sort an array of nodes based on their relative position in the document, + * removing any duplicate nodes. If the array contains nodes that do not belong + * to the same document, sort order is unspecified. + * + * @category Helpers + * @param nodes Array of DOM nodes. + * @returns Collection of unique nodes, sorted in document order. + */ + function uniqueSort(nodes) { + nodes = nodes.filter((node, i, arr) => !arr.includes(node, i + 1)); + nodes.sort((a, b) => { + const relative = compareDocumentPosition(a, b); + if (relative & DocumentPosition.PRECEDING) { + return -1; + } + else if (relative & DocumentPosition.FOLLOWING) { + return 1; + } + return 0; + }); + return nodes; + } + + /** + * Get the feed object from the root of a DOM tree. + * + * @category Feeds + * @param doc - The DOM to to extract the feed from. + * @returns The feed. + */ + function getFeed$1(doc) { + const feedRoot = getOneElement$1(isValidFeed$1, doc); + return !feedRoot + ? null + : feedRoot.name === "feed" + ? getAtomFeed$1(feedRoot) + : getRssFeed$1(feedRoot); + } + /** + * Parse an Atom feed. + * + * @param feedRoot The root of the feed. + * @returns The parsed feed. + */ + function getAtomFeed$1(feedRoot) { + var _a; + const childs = feedRoot.children; + const feed = { + type: "atom", + items: getElementsByTagName$1("entry", childs).map((item) => { + var _a; + const { children } = item; + const entry = { media: getMediaElements$1(children) }; + addConditionally$1(entry, "id", "id", children); + addConditionally$1(entry, "title", "title", children); + const href = (_a = getOneElement$1("link", children)) === null || _a === void 0 ? void 0 : _a.attribs["href"]; + if (href) { + entry.link = href; + } + const description = fetch$1("summary", children) || fetch$1("content", children); + if (description) { + entry.description = description; + } + const pubDate = fetch$1("updated", children); + if (pubDate) { + entry.pubDate = new Date(pubDate); + } + return entry; + }), + }; + addConditionally$1(feed, "id", "id", childs); + addConditionally$1(feed, "title", "title", childs); + const href = (_a = getOneElement$1("link", childs)) === null || _a === void 0 ? void 0 : _a.attribs["href"]; + if (href) { + feed.link = href; + } + addConditionally$1(feed, "description", "subtitle", childs); + const updated = fetch$1("updated", childs); + if (updated) { + feed.updated = new Date(updated); + } + addConditionally$1(feed, "author", "email", childs, true); + return feed; + } + /** + * Parse a RSS feed. + * + * @param feedRoot The root of the feed. + * @returns The parsed feed. + */ + function getRssFeed$1(feedRoot) { + var _a, _b; + const childs = (_b = (_a = getOneElement$1("channel", feedRoot.children)) === null || _a === void 0 ? void 0 : _a.children) !== null && _b !== void 0 ? _b : []; + const feed = { + type: feedRoot.name.substr(0, 3), + id: "", + items: getElementsByTagName$1("item", feedRoot.children).map((item) => { + const { children } = item; + const entry = { media: getMediaElements$1(children) }; + addConditionally$1(entry, "id", "guid", children); + addConditionally$1(entry, "title", "title", children); + addConditionally$1(entry, "link", "link", children); + addConditionally$1(entry, "description", "description", children); + const pubDate = fetch$1("pubDate", children) || fetch$1("dc:date", children); + if (pubDate) + entry.pubDate = new Date(pubDate); + return entry; + }), + }; + addConditionally$1(feed, "title", "title", childs); + addConditionally$1(feed, "link", "link", childs); + addConditionally$1(feed, "description", "description", childs); + const updated = fetch$1("lastBuildDate", childs); + if (updated) { + feed.updated = new Date(updated); + } + addConditionally$1(feed, "author", "managingEditor", childs, true); + return feed; + } + const MEDIA_KEYS_STRING$1 = ["url", "type", "lang"]; + const MEDIA_KEYS_INT$1 = [ + "fileSize", + "bitrate", + "framerate", + "samplingrate", + "channels", + "duration", + "height", + "width", + ]; + /** + * Get all media elements of a feed item. + * + * @param where Nodes to search in. + * @returns Media elements. + */ + function getMediaElements$1(where) { + return getElementsByTagName$1("media:content", where).map((elem) => { + const { attribs } = elem; + const media = { + medium: attribs["medium"], + isDefault: !!attribs["isDefault"], + }; + for (const attrib of MEDIA_KEYS_STRING$1) { + if (attribs[attrib]) { + media[attrib] = attribs[attrib]; + } + } + for (const attrib of MEDIA_KEYS_INT$1) { + if (attribs[attrib]) { + media[attrib] = parseInt(attribs[attrib], 10); + } + } + if (attribs["expression"]) { + media.expression = attribs["expression"]; + } + return media; + }); + } + /** + * Get one element by tag name. + * + * @param tagName Tag name to look for + * @param node Node to search in + * @returns The element or null + */ + function getOneElement$1(tagName, node) { + return getElementsByTagName$1(tagName, node, true, 1)[0]; + } + /** + * Get the text content of an element with a certain tag name. + * + * @param tagName Tag name to look for. + * @param where Node to search in. + * @param recurse Whether to recurse into child nodes. + * @returns The text content of the element. + */ + function fetch$1(tagName, where, recurse = false) { + return textContent$1(getElementsByTagName$1(tagName, where, recurse, 1)).trim(); + } + /** + * Adds a property to an object if it has a value. + * + * @param obj Object to be extended + * @param prop Property name + * @param tagName Tag name that contains the conditionally added property + * @param where Element to search for the property + * @param recurse Whether to recurse into child nodes. + */ + function addConditionally$1(obj, prop, tagName, where, recurse = false) { + const val = fetch$1(tagName, where, recurse); + if (val) + obj[prop] = val; + } + /** + * Checks if an element is a feed root node. + * + * @param value The name of the element to check. + * @returns Whether an element is a feed root node. + */ + function isValidFeed$1(value) { + return value === "rss" || value === "feed" || value === "rdf:RDF"; + } + + var DomUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + get DocumentPosition () { return DocumentPosition; }, + append: append$2, + appendChild: appendChild$1, + compareDocumentPosition: compareDocumentPosition, + existsOne: existsOne$2, + filter: filter$3, + find: find$1, + findAll: findAll$2, + findOne: findOne$2, + findOneChild: findOneChild$1, + getAttributeValue: getAttributeValue$2, + getChildren: getChildren$2, + getElementById: getElementById$1, + getElements: getElements$1, + getElementsByTagName: getElementsByTagName$1, + getElementsByTagType: getElementsByTagType$1, + getFeed: getFeed$1, + getInnerHTML: getInnerHTML$1, + getName: getName$2, + getOuterHTML: getOuterHTML$1, + getParent: getParent$2, + getSiblings: getSiblings$2, + getText: getText$2, + hasAttrib: hasAttrib$2, + hasChildren: hasChildren$1, + innerText: innerText$1, + isCDATA: isCDATA$1, + isComment: isComment$1, + isDocument: isDocument$1, + isTag: isTag$2, + isText: isText$1, + nextElementSibling: nextElementSibling$2, + prepend: prepend$1, + prependChild: prependChild$1, + prevElementSibling: prevElementSibling$1, + removeElement: removeElement$1, + removeSubsets: removeSubsets$1, + replaceElement: replaceElement$1, + testElement: testElement$1, + textContent: textContent$1, + uniqueSort: uniqueSort + }); + + // Helper methods + /** + * Parses the data, returns the resulting document. + * + * @param data The data that should be parsed. + * @param options Optional options for the parser and DOM handler. + */ + function parseDocument(data, options) { + const handler = new DomHandler(undefined, options); + new Parser$5(handler, options).end(data); + return handler.root; + } + /** + * Parses data, returns an array of the root nodes. + * + * Note that the root nodes still have a `Document` node as their parent. + * Use `parseDocument` to get the `Document` node instead. + * + * @param data The data that should be parsed. + * @param options Optional options for the parser and DOM handler. + * @deprecated Use `parseDocument` instead. + */ + function parseDOM(data, options) { + return parseDocument(data, options).children; + } + /** + * Creates a parser instance, with an attached DOM handler. + * + * @param callback A callback that will be called once parsing has been completed, with the resulting document. + * @param options Optional options for the parser and DOM handler. + * @param elementCallback An optional callback that will be called every time a tag has been completed inside of the DOM. + */ + function createDocumentStream(callback, options, elementCallback) { + const handler = new DomHandler((error) => callback(error, handler.root), options, elementCallback); + return new Parser$5(handler, options); + } + /** + * Creates a parser instance, with an attached DOM handler. + * + * @param callback A callback that will be called once parsing has been completed, with an array of root nodes. + * @param options Optional options for the parser and DOM handler. + * @param elementCallback An optional callback that will be called every time a tag has been completed inside of the DOM. + * @deprecated Use `createDocumentStream` instead. + */ + function createDomStream(callback, options, elementCallback) { + const handler = new DomHandler(callback, options, elementCallback); + return new Parser$5(handler, options); + } + const parseFeedDefaultOptions = { xmlMode: true }; + /** + * Parse a feed. + * + * @param feed The feed that should be parsed, as a string. + * @param options Optionally, options for parsing. When using this, you should set `xmlMode` to `true`. + */ + function parseFeed(feed, options = parseFeedDefaultOptions) { + return getFeed$1(parseDOM(feed, options)); + } + + var HTMLParser2 = /*#__PURE__*/Object.freeze({ + __proto__: null, + DefaultHandler: DomHandler, + DomHandler: DomHandler, + DomUtils: DomUtils, + ElementType: index, + Parser: Parser$5, + get QuoteType () { return QuoteType; }, + Tokenizer: Tokenizer$1, + createDocumentStream: createDocumentStream, + createDomStream: createDomStream, + getFeed: getFeed$1, + parseDOM: parseDOM, + parseDocument: parseDocument, + parseFeed: parseFeed + }); + + // Internal + const NODE_END = -1; + + // Node + const ELEMENT_NODE = 1; + const ATTRIBUTE_NODE = 2; + const TEXT_NODE = 3; + const CDATA_SECTION_NODE = 4; + const COMMENT_NODE = 8; + const DOCUMENT_NODE = 9; + const DOCUMENT_TYPE_NODE = 10; + const DOCUMENT_FRAGMENT_NODE = 11; + + // Elements + const BLOCK_ELEMENTS = new Set(['ARTICLE', 'ASIDE', 'BLOCKQUOTE', 'BODY', 'BR', 'BUTTON', 'CANVAS', 'CAPTION', 'COL', 'COLGROUP', 'DD', 'DIV', 'DL', 'DT', 'EMBED', 'FIELDSET', 'FIGCAPTION', 'FIGURE', 'FOOTER', 'FORM', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'LI', 'UL', 'OL', 'P']); + + // TreeWalker + const SHOW_ALL = -1; + const SHOW_ELEMENT = 1; + const SHOW_TEXT = 4; + const SHOW_CDATA_SECTION = 8; + const SHOW_COMMENT = 128; + + // Document position + const DOCUMENT_POSITION_DISCONNECTED = 0x01; + const DOCUMENT_POSITION_PRECEDING = 0x02; + const DOCUMENT_POSITION_FOLLOWING = 0x04; + const DOCUMENT_POSITION_CONTAINS = 0x08; + const DOCUMENT_POSITION_CONTAINED_BY = 0x10; + const DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20; + + // SVG + const SVG_NAMESPACE = 'http://www.w3.org/2000/svg'; + + const { + assign, + create: create$1, + defineProperties, + entries, + getOwnPropertyDescriptors, + keys, + setPrototypeOf + } = Object; + + const $String = String; + + const getEnd = node => node.nodeType === ELEMENT_NODE ? node[END] : node; + + const ignoreCase = ({ownerDocument}) => ownerDocument[MIME].ignoreCase; + + const knownAdjacent = (prev, next) => { + prev[NEXT] = next; + next[PREV] = prev; + }; + + const knownBoundaries = (prev, current, next) => { + knownAdjacent(prev, current); + knownAdjacent(getEnd(current), next); + }; + + const knownSegment = (prev, start, end, next) => { + knownAdjacent(prev, start); + knownAdjacent(getEnd(end), next); + }; + + const knownSiblings = (prev, current, next) => { + knownAdjacent(prev, current); + knownAdjacent(current, next); + }; + + const localCase = ({localName, ownerDocument}) => { + return ownerDocument[MIME].ignoreCase ? localName.toUpperCase() : localName; + }; + + const setAdjacent = (prev, next) => { + if (prev) + prev[NEXT] = next; + if (next) + next[PREV] = prev; + }; + + const shadowRoots = new WeakMap; + + let reactive = false; + + const Classes = new WeakMap; + + const customElements = new WeakMap; + + const attributeChangedCallback$1 = (element, attributeName, oldValue, newValue) => { + if ( + reactive && + customElements.has(element) && + element.attributeChangedCallback && + element.constructor.observedAttributes.includes(attributeName) + ) { + element.attributeChangedCallback(attributeName, oldValue, newValue); + } + }; + + const createTrigger = (method, isConnected) => element => { + if (customElements.has(element)) { + const info = customElements.get(element); + if (info.connected !== isConnected && element.isConnected === isConnected) { + info.connected = isConnected; + if (method in element) + element[method](); + } + } + }; + + const triggerConnected = createTrigger('connectedCallback', true); + const connectedCallback = element => { + if (reactive) { + triggerConnected(element); + if (shadowRoots.has(element)) + element = shadowRoots.get(element).shadowRoot; + let {[NEXT]: next, [END]: end} = element; + while (next !== end) { + if (next.nodeType === ELEMENT_NODE) + triggerConnected(next); + next = next[NEXT]; + } + } + }; + + const triggerDisconnected = createTrigger('disconnectedCallback', false); + const disconnectedCallback = element => { + if (reactive) { + triggerDisconnected(element); + if (shadowRoots.has(element)) + element = shadowRoots.get(element).shadowRoot; + let {[NEXT]: next, [END]: end} = element; + while (next !== end) { + if (next.nodeType === ELEMENT_NODE) + triggerDisconnected(next); + next = next[NEXT]; + } + } + }; + + /** + * @implements globalThis.CustomElementRegistry + */ + class CustomElementRegistry { + + /** + * @param {Document} ownerDocument + */ + constructor(ownerDocument) { + /** + * @private + */ + this.ownerDocument = ownerDocument; + + /** + * @private + */ + this.registry = new Map; + + /** + * @private + */ + this.waiting = new Map; + + /** + * @private + */ + this.active = false; + } + + /** + * @param {string} localName the custom element definition name + * @param {Function} Class the custom element **Class** definition + * @param {object?} options the optional object with an `extends` property + */ + define(localName, Class, options = {}) { + const {ownerDocument, registry, waiting} = this; + + if (registry.has(localName)) + throw new Error('unable to redefine ' + localName); + + if (Classes.has(Class)) + throw new Error('unable to redefine the same class: ' + Class); + + this.active = (reactive = true); + + const {extends: extend} = options; + + Classes.set(Class, { + ownerDocument, + options: {is: extend ? localName : ''}, + localName: extend || localName + }); + + const check = extend ? + element => { + return element.localName === extend && + element.getAttribute('is') === localName; + } : + element => element.localName === localName; + registry.set(localName, {Class, check}); + if (waiting.has(localName)) { + for (const resolve of waiting.get(localName)) + resolve(Class); + waiting.delete(localName); + } + ownerDocument.querySelectorAll( + extend ? `${extend}[is="${localName}"]` : localName + ).forEach(this.upgrade, this); + } + + /** + * @param {Element} element + */ + upgrade(element) { + if (customElements.has(element)) + return; + const {ownerDocument, registry} = this; + const ce = element.getAttribute('is') || element.localName; + if (registry.has(ce)) { + const {Class, check} = registry.get(ce); + if (check(element)) { + const {attributes, isConnected} = element; + for (const attr of attributes) + element.removeAttributeNode(attr); + + const values = entries(element); + for (const [key] of values) + delete element[key]; + + setPrototypeOf(element, Class.prototype); + ownerDocument[UPGRADE] = {element, values}; + new Class(ownerDocument, ce); + + customElements.set(element, {connected: isConnected}); + + for (const attr of attributes) + element.setAttributeNode(attr); + + if (isConnected && element.connectedCallback) + element.connectedCallback(); + } + } + } + + /** + * @param {string} localName the custom element definition name + */ + whenDefined(localName) { + const {registry, waiting} = this; + return new Promise(resolve => { + if (registry.has(localName)) + resolve(registry.get(localName).Class); + else { + if (!waiting.has(localName)) + waiting.set(localName, []); + waiting.get(localName).push(resolve); + } + }); + } + + /** + * @param {string} localName the custom element definition name + * @returns {Function?} the custom element **Class**, if any + */ + get(localName) { + const info = this.registry.get(localName); + return info && info.Class; + } + + /** + * @param {Function} Class **Class** of custom element + * @returns {string?} found tag name or null + */ + getName(Class) { + if (Classes.has(Class)) { + const { localName } = Classes.get(Class); + return localName; + } + return null; + } + } + + const {Parser: Parser$4} = HTMLParser2; + + const append$1 = (self, node, active) => { + const end = self[END]; + node.parentNode = self; + knownBoundaries(end[PREV], node, end); + if (active && node.nodeType === ELEMENT_NODE) + connectedCallback(node); + return node; + }; + + const attribute = (element, end, attribute, value, active) => { + attribute[VALUE] = value; + attribute.ownerElement = element; + knownSiblings(end[PREV], attribute, end); + if (attribute.name === 'class') + element.className = value; + if (active) + attributeChangedCallback$1(element, attribute.name, null, value); + }; + + const parseFromString = (document, isHTML, markupLanguage) => { + const {active, registry} = document[CUSTOM_ELEMENTS]; + + let node = document; + let ownerSVGElement = null; + let parsingCData = false; + + const content = new Parser$4({ + // <!DOCTYPE ...> + onprocessinginstruction(name, data) { + if (name.toLowerCase() === '!doctype') + document.doctype = data.slice(name.length).trim(); + }, + + // <tagName> + onopentag(name, attributes) { + let create = true; + if (isHTML) { + if (ownerSVGElement) { + node = append$1(node, document.createElementNS(SVG_NAMESPACE, name), active); + node.ownerSVGElement = ownerSVGElement; + create = false; + } + else if (name === 'svg' || name === 'SVG') { + ownerSVGElement = document.createElementNS(SVG_NAMESPACE, name); + node = append$1(node, ownerSVGElement, active); + create = false; + } + else if (active) { + const ce = name.includes('-') ? name : (attributes.is || ''); + if (ce && registry.has(ce)) { + const {Class} = registry.get(ce); + node = append$1(node, new Class, active); + delete attributes.is; + create = false; + } + } + } + + if (create) + node = append$1(node, document.createElement(name), false); + + let end = node[END]; + for (const name of keys(attributes)) + attribute(node, end, document.createAttribute(name), attributes[name], active); + }, + + // #text, #comment + oncomment(data) { append$1(node, document.createComment(data), active); }, + ontext(text) { + if (parsingCData) { + append$1(node, document.createCDATASection(text), active); + } else { + append$1(node, document.createTextNode(text), active); + } + }, + + // #cdata + oncdatastart() { parsingCData = true; }, + oncdataend() { parsingCData = false; }, + + // </tagName> + onclosetag() { + if (isHTML && node === ownerSVGElement) + ownerSVGElement = null; + node = node.parentNode; + } + }, { + lowerCaseAttributeNames: false, + decodeEntities: true, + xmlMode: !isHTML + }); + + content.write(markupLanguage); + content.end(); + + return document; + }; + + const htmlClasses = new Map; + + const registerHTMLClass = (names, Class) => { + for (const name of [].concat(names)) { + htmlClasses.set(name, Class); + htmlClasses.set(name.toUpperCase(), Class); + } + }; + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function getDefaultExportFromCjs (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; + } + + function getAugmentedNamespace(n) { + if (n.__esModule) return n; + var f = n.default; + if (typeof f == "function") { + var a = function a () { + if (this instanceof a) { + return Reflect.construct(f, arguments, this.constructor); + } + return f.apply(this, arguments); + }; + a.prototype = f.prototype; + } else a = {}; + Object.defineProperty(a, '__esModule', {value: true}); + Object.keys(n).forEach(function (k) { + var d = Object.getOwnPropertyDescriptor(n, k); + Object.defineProperty(a, k, d.get ? d : { + enumerable: true, + get: function () { + return n[k]; + } + }); + }); + return a; + } + + var perf_hooks = {}; + + var _polyfillNode_perf_hooks = {}; + + var _polyfillNode_perf_hooks$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + default: _polyfillNode_perf_hooks + }); + + var require$$0$1 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_perf_hooks$1); + + /* c8 ignore start */ + + var performance_1; + try { + const {performance} = require$$0$1; + performance_1 = perf_hooks.performance = performance; + } + catch (fallback) { + performance_1 = perf_hooks.performance = {now() { return +new Date; }}; + } + + const loopSegment = ({[NEXT]: next, [END]: end}, json) => { + while (next !== end) { + switch (next.nodeType) { + case ATTRIBUTE_NODE: + attrAsJSON(next, json); + break; + case TEXT_NODE: + case COMMENT_NODE: + case CDATA_SECTION_NODE: + characterDataAsJSON(next, json); + break; + case ELEMENT_NODE: + elementAsJSON(next, json); + next = getEnd(next); + break; + case DOCUMENT_TYPE_NODE: + documentTypeAsJSON(next, json); + break; + } + next = next[NEXT]; + } + const last = json.length - 1; + const value = json[last]; + if (typeof value === 'number' && value < 0) + json[last] += NODE_END; + else + json.push(NODE_END); + }; + + const attrAsJSON = (attr, json) => { + json.push(ATTRIBUTE_NODE, attr.name); + const value = attr[VALUE].trim(); + if (value) + json.push(value); + }; + + const characterDataAsJSON = (node, json) => { + const value = node[VALUE]; + if (value.trim()) + json.push(node.nodeType, value); + }; + + const nonElementAsJSON = (node, json) => { + json.push(node.nodeType); + loopSegment(node, json); + }; + + const documentTypeAsJSON = ({name, publicId, systemId}, json) => { + json.push(DOCUMENT_TYPE_NODE, name); + if (publicId) + json.push(publicId); + if (systemId) + json.push(systemId); + }; + + const elementAsJSON = (element, json) => { + json.push(ELEMENT_NODE, element.localName); + loopSegment(element, json); + }; + + const createRecord = + (type, target, addedNodes, removedNodes, attributeName, oldValue) => + ({type, target, addedNodes, removedNodes, attributeName, oldValue}); + + const queueAttribute = ( + observer, target, attributeName, attributeFilter, attributeOldValue, oldValue + ) => { + if ((!attributeFilter || attributeFilter.includes(attributeName))) { + const {callback, records, scheduled} = observer; + records.push(createRecord( + 'attributes', target, + [], [], + attributeName, attributeOldValue ? oldValue : void 0 + )); + if (!scheduled) { + observer.scheduled = true; + Promise.resolve().then(() => { + observer.scheduled = false; + callback(records.splice(0), observer); + }); + } + } + }; + + const attributeChangedCallback = (element, attributeName, oldValue) => { + const {ownerDocument} = element; + const {active, observers} = ownerDocument[MUTATION_OBSERVER]; + if (active) { + for (const observer of observers) { + for (const [ + target, + { + childList, + subtree, + attributes, + attributeFilter, + attributeOldValue + } + ] of observer.nodes) { + if (childList) { + if ( + (subtree && (target === ownerDocument || target.contains(element))) || + (!subtree && target.children.includes(element)) + ) { + queueAttribute( + observer, element, + attributeName, attributeFilter, attributeOldValue, oldValue + ); + break; + } + } + else if ( + attributes && + target === element + ) { + queueAttribute( + observer, element, + attributeName, attributeFilter, attributeOldValue, oldValue + ); + break; + } + } + } + } + }; + + const moCallback = (element, parentNode) => { + const {ownerDocument} = element; + const {active, observers} = ownerDocument[MUTATION_OBSERVER]; + if (active) { + for (const observer of observers) { + for (const [target, {subtree, childList, characterData}] of observer.nodes) { + if (childList) { + if ( + (parentNode && (target === parentNode || /* c8 ignore next */(subtree && target.contains(parentNode)))) || + (!parentNode && ((subtree && (target === ownerDocument || /* c8 ignore next */target.contains(element))) || + (!subtree && target[characterData ? 'childNodes' : 'children'].includes(element)))) + ) { + const {callback, records, scheduled} = observer; + records.push(createRecord( + 'childList', target, + parentNode ? [] : [element], parentNode ? [element] : [] + )); + if (!scheduled) { + observer.scheduled = true; + Promise.resolve().then(() => { + observer.scheduled = false; + callback(records.splice(0), observer); + }); + } + break; + } + } + } + } + } + }; + + class MutationObserverClass { + constructor(ownerDocument) { + const observers = new Set; + this.observers = observers; + this.active = false; + + /** + * @implements globalThis.MutationObserver + */ + this.class = class MutationObserver { + + constructor(callback) { + /** + * @private + */ + this.callback = callback; + + /** + * @private + */ + this.nodes = new Map; + + /** + * @private + */ + this.records = []; + + /** + * @private + */ + this.scheduled = false; + } + + disconnect() { + this.records.splice(0); + this.nodes.clear(); + observers.delete(this); + ownerDocument[MUTATION_OBSERVER].active = !!observers.size; + } + + /** + * @param {Element} target + * @param {MutationObserverInit} options + */ + observe(target, options = { + subtree: false, + childList: false, + attributes: false, + attributeFilter: null, + attributeOldValue: false, + characterData: false, + // TODO: not implemented yet + // characterDataOldValue: false + }) { + if (('attributeOldValue' in options) || ('attributeFilter' in options)) + options.attributes = true; + // if ('characterDataOldValue' in options) + // options.characterData = true; + options.childList = !!options.childList; + options.subtree = !!options.subtree; + this.nodes.set(target, options); + observers.add(this); + ownerDocument[MUTATION_OBSERVER].active = true; + } + + /** + * @returns {MutationRecord[]} + */ + takeRecords() { return this.records.splice(0); } + }; + } + } + + const emptyAttributes = new Set([ + 'allowfullscreen', + 'allowpaymentrequest', + 'async', + 'autofocus', + 'autoplay', + 'checked', + 'class', + 'contenteditable', + 'controls', + 'default', + 'defer', + 'disabled', + 'draggable', + 'formnovalidate', + 'hidden', + 'id', + 'ismap', + 'itemscope', + 'loop', + 'multiple', + 'muted', + 'nomodule', + 'novalidate', + 'open', + 'playsinline', + 'readonly', + 'required', + 'reversed', + 'selected', + 'style', + 'truespeed' + ]); + + const setAttribute = (element, attribute) => { + const {[VALUE]: value, name} = attribute; + attribute.ownerElement = element; + knownSiblings(element, attribute, element[NEXT]); + if (name === 'class') + element.className = value; + attributeChangedCallback(element, name, null); + attributeChangedCallback$1(element, name, null, value); + }; + + const removeAttribute = (element, attribute) => { + const {[VALUE]: value, name} = attribute; + knownAdjacent(attribute[PREV], attribute[NEXT]); + attribute.ownerElement = attribute[PREV] = attribute[NEXT] = null; + if (name === 'class') + element[CLASS_LIST] = null; + attributeChangedCallback(element, name, value); + attributeChangedCallback$1(element, name, value, null); + }; + + const booleanAttribute = { + get(element, name) { + return element.hasAttribute(name); + }, + set(element, name, value) { + if (value) + element.setAttribute(name, ''); + else + element.removeAttribute(name); + } + }; + + const numericAttribute = { + get(element, name) { + return parseFloat(element.getAttribute(name) || 0); + }, + set(element, name, value) { + element.setAttribute(name, value); + } + }; + + const stringAttribute = { + get(element, name) { + return element.getAttribute(name) || ''; + }, + set(element, name, value) { + element.setAttribute(name, value); + } + }; + + /* oddly enough, this apparently is not a thing + export const nullableAttribute = { + get(element, name) { + return element.getAttribute(name); + }, + set(element, name, value) { + if (value === null) + element.removeAttribute(name); + else + element.setAttribute(name, value); + } + }; + */ + + // https://dom.spec.whatwg.org/#interface-eventtarget + + const wm = new WeakMap(); + + function dispatch(event, listener) { + if (typeof listener === 'function') + listener.call(event.target, event); + else + listener.handleEvent(event); + return event._stopImmediatePropagationFlag; + } + + function invokeListeners({currentTarget, target}) { + const map = wm.get(currentTarget); + if (map && map.has(this.type)) { + const listeners = map.get(this.type); + if (currentTarget === target) { + this.eventPhase = this.AT_TARGET; + } else { + this.eventPhase = this.BUBBLING_PHASE; + } + + this.currentTarget = currentTarget; + this.target = target; + for (const [listener, options] of listeners) { + if (options && options.once) + listeners.delete(listener); + if (dispatch(this, listener)) + break; + } + delete this.currentTarget; + delete this.target; + return this.cancelBubble; + } + } + + + /** + * @implements globalThis.EventTarget + */ + class DOMEventTarget { + + constructor() { + wm.set(this, new Map); + } + + /** + * @protected + */ + _getParent() { + return null; + } + + addEventListener(type, listener, options) { + const map = wm.get(this); + if (!map.has(type)) + map.set(type, new Map); + map.get(type).set(listener, options); + } + + removeEventListener(type, listener) { + const map = wm.get(this); + if (map.has(type)) { + const listeners = map.get(type); + if (listeners.delete(listener) && !listeners.size) + map.delete(type); + } + } + + dispatchEvent(event) { + let node = this; + event.eventPhase = event.CAPTURING_PHASE; + + // intentionally simplified, specs imply way more code: https://dom.spec.whatwg.org/#event-path + while (node) { + if (node.dispatchEvent) + event._path.push({currentTarget: node, target: this}); + node = event.bubbles && node._getParent && node._getParent(); + } + event._path.some(invokeListeners, event); + event._path = []; + event.eventPhase = event.NONE; + return !event.defaultPrevented; + } + + } + + // https://dom.spec.whatwg.org/#interface-nodelist + + /** + * @implements globalThis.NodeList + */ + class NodeList extends Array { + item(i) { return i < this.length ? this[i] : null; } + } + + // https://dom.spec.whatwg.org/#node + + + const getParentNodeCount = ({parentNode}) => { + let count = 0; + while (parentNode) { + count++; + parentNode = parentNode.parentNode; + } + return count; + }; + + /** + * @implements globalThis.Node + */ + let Node$7 = class Node extends DOMEventTarget { + + static get ELEMENT_NODE() { return ELEMENT_NODE; } + static get ATTRIBUTE_NODE() { return ATTRIBUTE_NODE; } + static get TEXT_NODE() { return TEXT_NODE; } + static get CDATA_SECTION_NODE() { return CDATA_SECTION_NODE; } + static get COMMENT_NODE() { return COMMENT_NODE; } + static get DOCUMENT_NODE() { return DOCUMENT_NODE; } + static get DOCUMENT_FRAGMENT_NODE() { return DOCUMENT_FRAGMENT_NODE; } + static get DOCUMENT_TYPE_NODE() { return DOCUMENT_TYPE_NODE; } + + constructor(ownerDocument, localName, nodeType) { + super(); + this.ownerDocument = ownerDocument; + this.localName = localName; + this.nodeType = nodeType; + this.parentNode = null; + this[NEXT] = null; + this[PREV] = null; + } + + get ELEMENT_NODE() { return ELEMENT_NODE; } + get ATTRIBUTE_NODE() { return ATTRIBUTE_NODE; } + get TEXT_NODE() { return TEXT_NODE; } + get CDATA_SECTION_NODE() { return CDATA_SECTION_NODE; } + get COMMENT_NODE() { return COMMENT_NODE; } + get DOCUMENT_NODE() { return DOCUMENT_NODE; } + get DOCUMENT_FRAGMENT_NODE() { return DOCUMENT_FRAGMENT_NODE; } + get DOCUMENT_TYPE_NODE() { return DOCUMENT_TYPE_NODE; } + + get baseURI() { + const ownerDocument = this.nodeType === DOCUMENT_NODE ? + this : this.ownerDocument; + if (ownerDocument) { + const base = ownerDocument.querySelector('base'); + if (base) + return base.getAttribute('href'); + + const {location} = ownerDocument.defaultView; + if (location) + return location.href; + } + + return null; + } + + /* c8 ignore start */ + // mixin: node + get isConnected() { return false; } + get nodeName() { return this.localName; } + get parentElement() { return null; } + get previousSibling() { return null; } + get previousElementSibling() { return null; } + get nextSibling() { return null; } + get nextElementSibling() { return null; } + get childNodes() { return new NodeList; } + get firstChild() { return null; } + get lastChild() { return null; } + + // default values + get nodeValue() { return null; } + set nodeValue(value) {} + get textContent() { return null; } + set textContent(value) {} + normalize() {} + cloneNode() { return null; } + contains() { return false; } + /** + * Inserts a node before a reference node as a child of this parent node. + * @param {Node} newNode The node to be inserted. + * @param {Node} referenceNode The node before which newNode is inserted. If this is null, then newNode is inserted at the end of node's child nodes. + * @returns The added child + */ + // eslint-disable-next-line no-unused-vars + insertBefore(newNode, referenceNode) { return newNode } + /** + * Adds a node to the end of the list of children of this node. + * @param {Node} child The node to append to the given parent node. + * @returns The appended child. + */ + appendChild(child) { return child } + /** + * Replaces a child node within this node + * @param {Node} newChild The new node to replace oldChild. + * @param {Node} oldChild The child to be replaced. + * @returns The replaced Node. This is the same node as oldChild. + */ + replaceChild(newChild, oldChild) { return oldChild } + /** + * Removes a child node from the DOM. + * @param {Node} child A Node that is the child node to be removed from the DOM. + * @returns The removed node. + */ + removeChild(child) { return child } + toString() { return ''; } + /* c8 ignore stop */ + + hasChildNodes() { return !!this.lastChild; } + isSameNode(node) { return this === node; } + + // TODO: attributes? + compareDocumentPosition(target) { + let result = 0; + if (this !== target) { + let self = getParentNodeCount(this); + let other = getParentNodeCount(target); + if (self < other) { + result += DOCUMENT_POSITION_FOLLOWING; + if (this.contains(target)) + result += DOCUMENT_POSITION_CONTAINED_BY; + } + else if (other < self) { + result += DOCUMENT_POSITION_PRECEDING; + if (target.contains(this)) + result += DOCUMENT_POSITION_CONTAINS; + } + else if (self && other) { + const {childNodes} = this.parentNode; + if (childNodes.indexOf(this) < childNodes.indexOf(target)) + result += DOCUMENT_POSITION_FOLLOWING; + else + result += DOCUMENT_POSITION_PRECEDING; + } + if (!self || !other) { + result += DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC; + result += DOCUMENT_POSITION_DISCONNECTED; + } + } + return result; + } + + isEqualNode(node) { + if (this === node) + return true; + if (this.nodeType === node.nodeType) { + switch (this.nodeType) { + case DOCUMENT_NODE: + case DOCUMENT_FRAGMENT_NODE: { + const aNodes = this.childNodes; + const bNodes = node.childNodes; + return aNodes.length === bNodes.length && aNodes.every((node, i) => node.isEqualNode(bNodes[i])); + } + } + return this.toString() === node.toString(); + } + return false; + } + + /** + * @protected + */ + _getParent() { + return this.parentNode; + } + + /** + * Calling it on an element inside a standard web page will return an HTMLDocument object representing the entire page (or <iframe>). + * Calling it on an element inside a shadow DOM will return the associated ShadowRoot. + * @return {ShadowRoot | HTMLDocument} + */ + getRootNode() { + let root = this; + while (root.parentNode) + root = root.parentNode; + return root; + } + }; + + const {replace} = ''; + + // escape + const ca = /[<>&\xA0]/g; + + const esca = { + '\xA0': ' ', + '&': '&', + '<': '<', + '>': '>' + }; + + const pe = m => esca[m]; + + /** + * Safely escape HTML entities such as `&`, `<`, `>` only. + * @param {string} es the input to safely escape + * @returns {string} the escaped input, and it **throws** an error if + * the input type is unexpected, except for boolean and numbers, + * converted as string. + */ + const escape$1 = es => replace.call(es, ca, pe); + + const QUOTE = /"/g; + + /** + * @implements globalThis.Attr + */ + let Attr$1 = class Attr extends Node$7 { + constructor(ownerDocument, name, value = '') { + super(ownerDocument, name, ATTRIBUTE_NODE); + this.ownerElement = null; + this.name = $String(name); + this[VALUE] = $String(value); + this[CHANGED] = false; + } + + get value() { return this[VALUE]; } + set value(newValue) { + const {[VALUE]: oldValue, name, ownerElement} = this; + this[VALUE] = $String(newValue); + this[CHANGED] = true; + if (ownerElement) { + attributeChangedCallback(ownerElement, name, oldValue); + attributeChangedCallback$1(ownerElement, name, oldValue, this[VALUE]); + } + } + + cloneNode() { + const {ownerDocument, name, [VALUE]: value} = this; + return new Attr(ownerDocument, name, value); + } + + toString() { + const {name, [VALUE]: value} = this; + if (emptyAttributes.has(name) && !value) { + return ignoreCase(this) ? name : `${name}=""`; + } + const escapedValue = ignoreCase(this) ? value.replace(QUOTE, '"') : escape$1(value); + return `${name}="${escapedValue}"`; + } + + toJSON() { + const json = []; + attrAsJSON(this, json); + return json; + } + }; + + const isConnected = ({ownerDocument, parentNode}) => { + while (parentNode) { + if (parentNode === ownerDocument) + return true; + parentNode = parentNode.parentNode || parentNode.host; + } + return false; + }; + + const parentElement = ({parentNode}) => { + if (parentNode) { + switch (parentNode.nodeType) { + case DOCUMENT_NODE: + case DOCUMENT_FRAGMENT_NODE: + return null; + } + } + return parentNode; + }; + + const previousSibling = ({[PREV]: prev}) => { + switch (prev ? prev.nodeType : 0) { + case NODE_END: + return prev[START]; + case TEXT_NODE: + case COMMENT_NODE: + case CDATA_SECTION_NODE: + return prev; + } + return null; + }; + + const nextSibling = node => { + const next = getEnd(node)[NEXT]; + return next && (next.nodeType === NODE_END ? null : next); + }; + + // https://dom.spec.whatwg.org/#nondocumenttypechildnode + // CharacterData, Element + + + const nextElementSibling$1 = node => { + let next = nextSibling(node); + while (next && next.nodeType !== ELEMENT_NODE) + next = nextSibling(next); + return next; + }; + + const previousElementSibling = node => { + let prev = previousSibling(node); + while (prev && prev.nodeType !== ELEMENT_NODE) + prev = previousSibling(prev); + return prev; + }; + + // https://dom.spec.whatwg.org/#childnode + // CharacterData, DocumentType, Element + + + const asFragment = (ownerDocument, nodes) => { + const fragment = ownerDocument.createDocumentFragment(); + fragment.append(...nodes); + return fragment; + }; + + const before = (node, nodes) => { + const {ownerDocument, parentNode} = node; + if (parentNode) + parentNode.insertBefore( + asFragment(ownerDocument, nodes), + node + ); + }; + + const after = (node, nodes) => { + const {ownerDocument, parentNode} = node; + if (parentNode) + parentNode.insertBefore( + asFragment(ownerDocument, nodes), + getEnd(node)[NEXT] + ); + }; + + const replaceWith = (node, nodes) => { + const {ownerDocument, parentNode} = node; + if (parentNode) { + if (nodes.includes(node)) + replaceWith(node, [node = node.cloneNode()]); + parentNode.insertBefore( + asFragment(ownerDocument, nodes), + node + ); + node.remove(); + } + }; + + const remove = (prev, current, next) => { + const {parentNode, nodeType} = current; + if (prev || next) { + setAdjacent(prev, next); + current[PREV] = null; + getEnd(current)[NEXT] = null; + } + if (parentNode) { + current.parentNode = null; + moCallback(current, parentNode); + if (nodeType === ELEMENT_NODE) + disconnectedCallback(current); + } + }; + + // https://dom.spec.whatwg.org/#interface-characterdata + + + /** + * @implements globalThis.CharacterData + */ + let CharacterData$1 = class CharacterData extends Node$7 { + + constructor(ownerDocument, localName, nodeType, data) { + super(ownerDocument, localName, nodeType); + this[VALUE] = $String(data); + } + + // <Mixins> + get isConnected() { return isConnected(this); } + get parentElement() { return parentElement(this); } + get previousSibling() { return previousSibling(this); } + get nextSibling() { return nextSibling(this); } + + get previousElementSibling() { return previousElementSibling(this); } + get nextElementSibling() { return nextElementSibling$1(this); } + + before(...nodes) { before(this, nodes); } + after(...nodes) { after(this, nodes); } + replaceWith(...nodes) { replaceWith(this, nodes); } + remove() { remove(this[PREV], this, this[NEXT]); } + // </Mixins> + + // CharacterData only + /* c8 ignore start */ + get data() { return this[VALUE]; } + set data(value) { + this[VALUE] = $String(value); + moCallback(this, this.parentNode); + } + + get nodeValue() { return this.data; } + set nodeValue(value) { this.data = value; } + + get textContent() { return this.data; } + set textContent(value) { this.data = value; } + + get length() { return this.data.length; } + + substringData(offset, count) { + return this.data.substr(offset, count); + } + + appendData(data) { + this.data += data; + } + + insertData(offset, data) { + const {data: t} = this; + this.data = t.slice(0, offset) + data + t.slice(offset); + } + + deleteData(offset, count) { + const {data: t} = this; + this.data = t.slice(0, offset) + t.slice(offset + count); + } + + replaceData(offset, count, data) { + const {data: t} = this; + this.data = t.slice(0, offset) + data + t.slice(offset + count); + } + /* c8 ignore stop */ + + toJSON() { + const json = []; + characterDataAsJSON(this, json); + return json; + } + }; + + /** + * @implements globalThis.CDATASection + */ + let CDATASection$1 = class CDATASection extends CharacterData$1 { + constructor(ownerDocument, data = '') { + super(ownerDocument, '#cdatasection', CDATA_SECTION_NODE, data); + } + + cloneNode() { + const {ownerDocument, [VALUE]: data} = this; + return new CDATASection(ownerDocument, data); + } + + toString() { return `<![CDATA[${this[VALUE]}]]>`; } + }; + + /** + * @implements globalThis.Comment + */ + let Comment$7 = class Comment extends CharacterData$1 { + constructor(ownerDocument, data = '') { + super(ownerDocument, '#comment', COMMENT_NODE, data); + } + + cloneNode() { + const {ownerDocument, [VALUE]: data} = this; + return new Comment(ownerDocument, data); + } + + toString() { return `<!--${this[VALUE]}-->`; } + }; + + var boolbase = { + trueFunc: function trueFunc(){ + return true; + }, + falseFunc: function falseFunc(){ + return false; + } + }; + + var boolbase$1 = /*@__PURE__*/getDefaultExportFromCjs(boolbase); + + var SelectorType; + (function (SelectorType) { + SelectorType["Attribute"] = "attribute"; + SelectorType["Pseudo"] = "pseudo"; + SelectorType["PseudoElement"] = "pseudo-element"; + SelectorType["Tag"] = "tag"; + SelectorType["Universal"] = "universal"; + // Traversals + SelectorType["Adjacent"] = "adjacent"; + SelectorType["Child"] = "child"; + SelectorType["Descendant"] = "descendant"; + SelectorType["Parent"] = "parent"; + SelectorType["Sibling"] = "sibling"; + SelectorType["ColumnCombinator"] = "column-combinator"; + })(SelectorType || (SelectorType = {})); + var AttributeAction; + (function (AttributeAction) { + AttributeAction["Any"] = "any"; + AttributeAction["Element"] = "element"; + AttributeAction["End"] = "end"; + AttributeAction["Equals"] = "equals"; + AttributeAction["Exists"] = "exists"; + AttributeAction["Hyphen"] = "hyphen"; + AttributeAction["Not"] = "not"; + AttributeAction["Start"] = "start"; + })(AttributeAction || (AttributeAction = {})); + + const reName = /^[^\\#]?(?:\\(?:[\da-f]{1,6}\s?|.)|[\w\-\u00b0-\uFFFF])+/; + const reEscape = /\\([\da-f]{1,6}\s?|(\s)|.)/gi; + const actionTypes = new Map([ + [126 /* Tilde */, AttributeAction.Element], + [94 /* Circumflex */, AttributeAction.Start], + [36 /* Dollar */, AttributeAction.End], + [42 /* Asterisk */, AttributeAction.Any], + [33 /* ExclamationMark */, AttributeAction.Not], + [124 /* Pipe */, AttributeAction.Hyphen], + ]); + // Pseudos, whose data property is parsed as well. + const unpackPseudos = new Set([ + "has", + "not", + "matches", + "is", + "where", + "host", + "host-context", + ]); + /** + * Checks whether a specific selector is a traversal. + * This is useful eg. in swapping the order of elements that + * are not traversals. + * + * @param selector Selector to check. + */ + function isTraversal$1(selector) { + switch (selector.type) { + case SelectorType.Adjacent: + case SelectorType.Child: + case SelectorType.Descendant: + case SelectorType.Parent: + case SelectorType.Sibling: + case SelectorType.ColumnCombinator: + return true; + default: + return false; + } + } + const stripQuotesFromPseudos = new Set(["contains", "icontains"]); + // Unescape function taken from https://github.com/jquery/sizzle/blob/master/src/sizzle.js#L152 + function funescape(_, escaped, escapedWhitespace) { + const high = parseInt(escaped, 16) - 0x10000; + // NaN means non-codepoint + return high !== high || escapedWhitespace + ? escaped + : high < 0 + ? // BMP codepoint + String.fromCharCode(high + 0x10000) + : // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode((high >> 10) | 0xd800, (high & 0x3ff) | 0xdc00); + } + function unescapeCSS(str) { + return str.replace(reEscape, funescape); + } + function isQuote(c) { + return c === 39 /* SingleQuote */ || c === 34 /* DoubleQuote */; + } + function isWhitespace(c) { + return (c === 32 /* Space */ || + c === 9 /* Tab */ || + c === 10 /* NewLine */ || + c === 12 /* FormFeed */ || + c === 13 /* CarriageReturn */); + } + /** + * Parses `selector`, optionally with the passed `options`. + * + * @param selector Selector to parse. + * @param options Options for parsing. + * @returns Returns a two-dimensional array. + * The first dimension represents selectors separated by commas (eg. `sub1, sub2`), + * the second contains the relevant tokens for that selector. + */ + function parse$a(selector) { + const subselects = []; + const endIndex = parseSelector(subselects, `${selector}`, 0); + if (endIndex < selector.length) { + throw new Error(`Unmatched selector: ${selector.slice(endIndex)}`); + } + return subselects; + } + function parseSelector(subselects, selector, selectorIndex) { + let tokens = []; + function getName(offset) { + const match = selector.slice(selectorIndex + offset).match(reName); + if (!match) { + throw new Error(`Expected name, found ${selector.slice(selectorIndex)}`); + } + const [name] = match; + selectorIndex += offset + name.length; + return unescapeCSS(name); + } + function stripWhitespace(offset) { + selectorIndex += offset; + while (selectorIndex < selector.length && + isWhitespace(selector.charCodeAt(selectorIndex))) { + selectorIndex++; + } + } + function readValueWithParenthesis() { + selectorIndex += 1; + const start = selectorIndex; + let counter = 1; + for (; counter > 0 && selectorIndex < selector.length; selectorIndex++) { + if (selector.charCodeAt(selectorIndex) === + 40 /* LeftParenthesis */ && + !isEscaped(selectorIndex)) { + counter++; + } + else if (selector.charCodeAt(selectorIndex) === + 41 /* RightParenthesis */ && + !isEscaped(selectorIndex)) { + counter--; + } + } + if (counter) { + throw new Error("Parenthesis not matched"); + } + return unescapeCSS(selector.slice(start, selectorIndex - 1)); + } + function isEscaped(pos) { + let slashCount = 0; + while (selector.charCodeAt(--pos) === 92 /* BackSlash */) + slashCount++; + return (slashCount & 1) === 1; + } + function ensureNotTraversal() { + if (tokens.length > 0 && isTraversal$1(tokens[tokens.length - 1])) { + throw new Error("Did not expect successive traversals."); + } + } + function addTraversal(type) { + if (tokens.length > 0 && + tokens[tokens.length - 1].type === SelectorType.Descendant) { + tokens[tokens.length - 1].type = type; + return; + } + ensureNotTraversal(); + tokens.push({ type }); + } + function addSpecialAttribute(name, action) { + tokens.push({ + type: SelectorType.Attribute, + name, + action, + value: getName(1), + namespace: null, + ignoreCase: "quirks", + }); + } + /** + * We have finished parsing the current part of the selector. + * + * Remove descendant tokens at the end if they exist, + * and return the last index, so that parsing can be + * picked up from here. + */ + function finalizeSubselector() { + if (tokens.length && + tokens[tokens.length - 1].type === SelectorType.Descendant) { + tokens.pop(); + } + if (tokens.length === 0) { + throw new Error("Empty sub-selector"); + } + subselects.push(tokens); + } + stripWhitespace(0); + if (selector.length === selectorIndex) { + return selectorIndex; + } + loop: while (selectorIndex < selector.length) { + const firstChar = selector.charCodeAt(selectorIndex); + switch (firstChar) { + // Whitespace + case 32 /* Space */: + case 9 /* Tab */: + case 10 /* NewLine */: + case 12 /* FormFeed */: + case 13 /* CarriageReturn */: { + if (tokens.length === 0 || + tokens[0].type !== SelectorType.Descendant) { + ensureNotTraversal(); + tokens.push({ type: SelectorType.Descendant }); + } + stripWhitespace(1); + break; + } + // Traversals + case 62 /* GreaterThan */: { + addTraversal(SelectorType.Child); + stripWhitespace(1); + break; + } + case 60 /* LessThan */: { + addTraversal(SelectorType.Parent); + stripWhitespace(1); + break; + } + case 126 /* Tilde */: { + addTraversal(SelectorType.Sibling); + stripWhitespace(1); + break; + } + case 43 /* Plus */: { + addTraversal(SelectorType.Adjacent); + stripWhitespace(1); + break; + } + // Special attribute selectors: .class, #id + case 46 /* Period */: { + addSpecialAttribute("class", AttributeAction.Element); + break; + } + case 35 /* Hash */: { + addSpecialAttribute("id", AttributeAction.Equals); + break; + } + case 91 /* LeftSquareBracket */: { + stripWhitespace(1); + // Determine attribute name and namespace + let name; + let namespace = null; + if (selector.charCodeAt(selectorIndex) === 124 /* Pipe */) { + // Equivalent to no namespace + name = getName(1); + } + else if (selector.startsWith("*|", selectorIndex)) { + namespace = "*"; + name = getName(2); + } + else { + name = getName(0); + if (selector.charCodeAt(selectorIndex) === 124 /* Pipe */ && + selector.charCodeAt(selectorIndex + 1) !== + 61 /* Equal */) { + namespace = name; + name = getName(1); + } + } + stripWhitespace(0); + // Determine comparison operation + let action = AttributeAction.Exists; + const possibleAction = actionTypes.get(selector.charCodeAt(selectorIndex)); + if (possibleAction) { + action = possibleAction; + if (selector.charCodeAt(selectorIndex + 1) !== + 61 /* Equal */) { + throw new Error("Expected `=`"); + } + stripWhitespace(2); + } + else if (selector.charCodeAt(selectorIndex) === 61 /* Equal */) { + action = AttributeAction.Equals; + stripWhitespace(1); + } + // Determine value + let value = ""; + let ignoreCase = null; + if (action !== "exists") { + if (isQuote(selector.charCodeAt(selectorIndex))) { + const quote = selector.charCodeAt(selectorIndex); + let sectionEnd = selectorIndex + 1; + while (sectionEnd < selector.length && + (selector.charCodeAt(sectionEnd) !== quote || + isEscaped(sectionEnd))) { + sectionEnd += 1; + } + if (selector.charCodeAt(sectionEnd) !== quote) { + throw new Error("Attribute value didn't end"); + } + value = unescapeCSS(selector.slice(selectorIndex + 1, sectionEnd)); + selectorIndex = sectionEnd + 1; + } + else { + const valueStart = selectorIndex; + while (selectorIndex < selector.length && + ((!isWhitespace(selector.charCodeAt(selectorIndex)) && + selector.charCodeAt(selectorIndex) !== + 93 /* RightSquareBracket */) || + isEscaped(selectorIndex))) { + selectorIndex += 1; + } + value = unescapeCSS(selector.slice(valueStart, selectorIndex)); + } + stripWhitespace(0); + // See if we have a force ignore flag + const forceIgnore = selector.charCodeAt(selectorIndex) | 0x20; + // If the forceIgnore flag is set (either `i` or `s`), use that value + if (forceIgnore === 115 /* LowerS */) { + ignoreCase = false; + stripWhitespace(1); + } + else if (forceIgnore === 105 /* LowerI */) { + ignoreCase = true; + stripWhitespace(1); + } + } + if (selector.charCodeAt(selectorIndex) !== + 93 /* RightSquareBracket */) { + throw new Error("Attribute selector didn't terminate"); + } + selectorIndex += 1; + const attributeSelector = { + type: SelectorType.Attribute, + name, + action, + value, + namespace, + ignoreCase, + }; + tokens.push(attributeSelector); + break; + } + case 58 /* Colon */: { + if (selector.charCodeAt(selectorIndex + 1) === 58 /* Colon */) { + tokens.push({ + type: SelectorType.PseudoElement, + name: getName(2).toLowerCase(), + data: selector.charCodeAt(selectorIndex) === + 40 /* LeftParenthesis */ + ? readValueWithParenthesis() + : null, + }); + continue; + } + const name = getName(1).toLowerCase(); + let data = null; + if (selector.charCodeAt(selectorIndex) === + 40 /* LeftParenthesis */) { + if (unpackPseudos.has(name)) { + if (isQuote(selector.charCodeAt(selectorIndex + 1))) { + throw new Error(`Pseudo-selector ${name} cannot be quoted`); + } + data = []; + selectorIndex = parseSelector(data, selector, selectorIndex + 1); + if (selector.charCodeAt(selectorIndex) !== + 41 /* RightParenthesis */) { + throw new Error(`Missing closing parenthesis in :${name} (${selector})`); + } + selectorIndex += 1; + } + else { + data = readValueWithParenthesis(); + if (stripQuotesFromPseudos.has(name)) { + const quot = data.charCodeAt(0); + if (quot === data.charCodeAt(data.length - 1) && + isQuote(quot)) { + data = data.slice(1, -1); + } + } + data = unescapeCSS(data); + } + } + tokens.push({ type: SelectorType.Pseudo, name, data }); + break; + } + case 44 /* Comma */: { + finalizeSubselector(); + tokens = []; + stripWhitespace(1); + break; + } + default: { + if (selector.startsWith("/*", selectorIndex)) { + const endIndex = selector.indexOf("*/", selectorIndex + 2); + if (endIndex < 0) { + throw new Error("Comment was not terminated"); + } + selectorIndex = endIndex + 2; + // Remove leading whitespace + if (tokens.length === 0) { + stripWhitespace(0); + } + break; + } + let namespace = null; + let name; + if (firstChar === 42 /* Asterisk */) { + selectorIndex += 1; + name = "*"; + } + else if (firstChar === 124 /* Pipe */) { + name = ""; + if (selector.charCodeAt(selectorIndex + 1) === 124 /* Pipe */) { + addTraversal(SelectorType.ColumnCombinator); + stripWhitespace(2); + break; + } + } + else if (reName.test(selector.slice(selectorIndex))) { + name = getName(0); + } + else { + break loop; + } + if (selector.charCodeAt(selectorIndex) === 124 /* Pipe */ && + selector.charCodeAt(selectorIndex + 1) !== 124 /* Pipe */) { + namespace = name; + if (selector.charCodeAt(selectorIndex + 1) === + 42 /* Asterisk */) { + name = "*"; + selectorIndex += 2; + } + else { + name = getName(1); + } + } + tokens.push(name === "*" + ? { type: SelectorType.Universal, namespace } + : { type: SelectorType.Tag, name, namespace }); + } + } + } + finalizeSubselector(); + return selectorIndex; + } + + const procedure = new Map([ + [SelectorType.Universal, 50], + [SelectorType.Tag, 30], + [SelectorType.Attribute, 1], + [SelectorType.Pseudo, 0], + ]); + function isTraversal(token) { + return !procedure.has(token.type); + } + const attributes = new Map([ + [AttributeAction.Exists, 10], + [AttributeAction.Equals, 8], + [AttributeAction.Not, 7], + [AttributeAction.Start, 6], + [AttributeAction.End, 6], + [AttributeAction.Any, 5], + ]); + /** + * Sort the parts of the passed selector, + * as there is potential for optimization + * (some types of selectors are faster than others) + * + * @param arr Selector to sort + */ + function sortByProcedure(arr) { + const procs = arr.map(getProcedure); + for (let i = 1; i < arr.length; i++) { + const procNew = procs[i]; + if (procNew < 0) + continue; + for (let j = i - 1; j >= 0 && procNew < procs[j]; j--) { + const token = arr[j + 1]; + arr[j + 1] = arr[j]; + arr[j] = token; + procs[j + 1] = procs[j]; + procs[j] = procNew; + } + } + } + function getProcedure(token) { + var _a, _b; + let proc = (_a = procedure.get(token.type)) !== null && _a !== void 0 ? _a : -1; + if (token.type === SelectorType.Attribute) { + proc = (_b = attributes.get(token.action)) !== null && _b !== void 0 ? _b : 4; + if (token.action === AttributeAction.Equals && token.name === "id") { + // Prefer ID selectors (eg. #ID) + proc = 9; + } + if (token.ignoreCase) { + /* + * IgnoreCase adds some overhead, prefer "normal" token + * this is a binary operation, to ensure it's still an int + */ + proc >>= 1; + } + } + else if (token.type === SelectorType.Pseudo) { + if (!token.data) { + proc = 3; + } + else if (token.name === "has" || token.name === "contains") { + proc = 0; // Expensive in any case + } + else if (Array.isArray(token.data)) { + // Eg. :matches, :not + proc = Math.min(...token.data.map((d) => Math.min(...d.map(getProcedure)))); + // If we have traversals, try to avoid executing this selector + if (proc < 0) { + proc = 0; + } + } + else { + proc = 2; + } + } + return proc; + } + + /** + * All reserved characters in a regex, used for escaping. + * + * Taken from XRegExp, (c) 2007-2020 Steven Levithan under the MIT license + * https://github.com/slevithan/xregexp/blob/95eeebeb8fac8754d54eafe2b4743661ac1cf028/src/xregexp.js#L794 + */ + const reChars = /[-[\]{}()*+?.,\\^$|#\s]/g; + function escapeRegex(value) { + return value.replace(reChars, "\\$&"); + } + /** + * Attributes that are case-insensitive in HTML. + * + * @private + * @see https://html.spec.whatwg.org/multipage/semantics-other.html#case-sensitivity-of-selectors + */ + const caseInsensitiveAttributes = new Set([ + "accept", + "accept-charset", + "align", + "alink", + "axis", + "bgcolor", + "charset", + "checked", + "clear", + "codetype", + "color", + "compact", + "declare", + "defer", + "dir", + "direction", + "disabled", + "enctype", + "face", + "frame", + "hreflang", + "http-equiv", + "lang", + "language", + "link", + "media", + "method", + "multiple", + "nohref", + "noresize", + "noshade", + "nowrap", + "readonly", + "rel", + "rev", + "rules", + "scope", + "scrolling", + "selected", + "shape", + "target", + "text", + "type", + "valign", + "valuetype", + "vlink", + ]); + function shouldIgnoreCase(selector, options) { + return typeof selector.ignoreCase === "boolean" + ? selector.ignoreCase + : selector.ignoreCase === "quirks" + ? !!options.quirksMode + : !options.xmlMode && caseInsensitiveAttributes.has(selector.name); + } + /** + * Attribute selectors + */ + const attributeRules = { + equals(next, data, options) { + const { adapter } = options; + const { name } = data; + let { value } = data; + if (shouldIgnoreCase(data, options)) { + value = value.toLowerCase(); + return (elem) => { + const attr = adapter.getAttributeValue(elem, name); + return (attr != null && + attr.length === value.length && + attr.toLowerCase() === value && + next(elem)); + }; + } + return (elem) => adapter.getAttributeValue(elem, name) === value && next(elem); + }, + hyphen(next, data, options) { + const { adapter } = options; + const { name } = data; + let { value } = data; + const len = value.length; + if (shouldIgnoreCase(data, options)) { + value = value.toLowerCase(); + return function hyphenIC(elem) { + const attr = adapter.getAttributeValue(elem, name); + return (attr != null && + (attr.length === len || attr.charAt(len) === "-") && + attr.substr(0, len).toLowerCase() === value && + next(elem)); + }; + } + return function hyphen(elem) { + const attr = adapter.getAttributeValue(elem, name); + return (attr != null && + (attr.length === len || attr.charAt(len) === "-") && + attr.substr(0, len) === value && + next(elem)); + }; + }, + element(next, data, options) { + const { adapter } = options; + const { name, value } = data; + if (/\s/.test(value)) { + return boolbase$1.falseFunc; + } + const regex = new RegExp(`(?:^|\\s)${escapeRegex(value)}(?:$|\\s)`, shouldIgnoreCase(data, options) ? "i" : ""); + return function element(elem) { + const attr = adapter.getAttributeValue(elem, name); + return (attr != null && + attr.length >= value.length && + regex.test(attr) && + next(elem)); + }; + }, + exists(next, { name }, { adapter }) { + return (elem) => adapter.hasAttrib(elem, name) && next(elem); + }, + start(next, data, options) { + const { adapter } = options; + const { name } = data; + let { value } = data; + const len = value.length; + if (len === 0) { + return boolbase$1.falseFunc; + } + if (shouldIgnoreCase(data, options)) { + value = value.toLowerCase(); + return (elem) => { + const attr = adapter.getAttributeValue(elem, name); + return (attr != null && + attr.length >= len && + attr.substr(0, len).toLowerCase() === value && + next(elem)); + }; + } + return (elem) => { + var _a; + return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.startsWith(value)) && + next(elem); + }; + }, + end(next, data, options) { + const { adapter } = options; + const { name } = data; + let { value } = data; + const len = -value.length; + if (len === 0) { + return boolbase$1.falseFunc; + } + if (shouldIgnoreCase(data, options)) { + value = value.toLowerCase(); + return (elem) => { + var _a; + return ((_a = adapter + .getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.substr(len).toLowerCase()) === value && next(elem); + }; + } + return (elem) => { + var _a; + return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.endsWith(value)) && + next(elem); + }; + }, + any(next, data, options) { + const { adapter } = options; + const { name, value } = data; + if (value === "") { + return boolbase$1.falseFunc; + } + if (shouldIgnoreCase(data, options)) { + const regex = new RegExp(escapeRegex(value), "i"); + return function anyIC(elem) { + const attr = adapter.getAttributeValue(elem, name); + return (attr != null && + attr.length >= value.length && + regex.test(attr) && + next(elem)); + }; + } + return (elem) => { + var _a; + return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.includes(value)) && + next(elem); + }; + }, + not(next, data, options) { + const { adapter } = options; + const { name } = data; + let { value } = data; + if (value === "") { + return (elem) => !!adapter.getAttributeValue(elem, name) && next(elem); + } + else if (shouldIgnoreCase(data, options)) { + value = value.toLowerCase(); + return (elem) => { + const attr = adapter.getAttributeValue(elem, name); + return ((attr == null || + attr.length !== value.length || + attr.toLowerCase() !== value) && + next(elem)); + }; + } + return (elem) => adapter.getAttributeValue(elem, name) !== value && next(elem); + }, + }; + + // Following http://www.w3.org/TR/css3-selectors/#nth-child-pseudo + // Whitespace as per https://www.w3.org/TR/selectors-3/#lex is " \t\r\n\f" + const whitespace = new Set([9, 10, 12, 13, 32]); + const ZERO = "0".charCodeAt(0); + const NINE = "9".charCodeAt(0); + /** + * Parses an expression. + * + * @throws An `Error` if parsing fails. + * @returns An array containing the integer step size and the integer offset of the nth rule. + * @example nthCheck.parse("2n+3"); // returns [2, 3] + */ + function parse$9(formula) { + formula = formula.trim().toLowerCase(); + if (formula === "even") { + return [2, 0]; + } + else if (formula === "odd") { + return [2, 1]; + } + // Parse [ ['-'|'+']? INTEGER? {N} [ S* ['-'|'+'] S* INTEGER ]? + let idx = 0; + let a = 0; + let sign = readSign(); + let number = readNumber(); + if (idx < formula.length && formula.charAt(idx) === "n") { + idx++; + a = sign * (number !== null && number !== void 0 ? number : 1); + skipWhitespace(); + if (idx < formula.length) { + sign = readSign(); + skipWhitespace(); + number = readNumber(); + } + else { + sign = number = 0; + } + } + // Throw if there is anything else + if (number === null || idx < formula.length) { + throw new Error(`n-th rule couldn't be parsed ('${formula}')`); + } + return [a, sign * number]; + function readSign() { + if (formula.charAt(idx) === "-") { + idx++; + return -1; + } + if (formula.charAt(idx) === "+") { + idx++; + } + return 1; + } + function readNumber() { + const start = idx; + let value = 0; + while (idx < formula.length && + formula.charCodeAt(idx) >= ZERO && + formula.charCodeAt(idx) <= NINE) { + value = value * 10 + (formula.charCodeAt(idx) - ZERO); + idx++; + } + // Return `null` if we didn't read anything. + return idx === start ? null : value; + } + function skipWhitespace() { + while (idx < formula.length && + whitespace.has(formula.charCodeAt(idx))) { + idx++; + } + } + } + + /** + * Returns a function that checks if an elements index matches the given rule + * highly optimized to return the fastest solution. + * + * @param parsed A tuple [a, b], as returned by `parse`. + * @returns A highly optimized function that returns whether an index matches the nth-check. + * @example + * + * ```js + * const check = nthCheck.compile([2, 3]); + * + * check(0); // `false` + * check(1); // `false` + * check(2); // `true` + * check(3); // `false` + * check(4); // `true` + * check(5); // `false` + * check(6); // `true` + * ``` + */ + function compile$2(parsed) { + const a = parsed[0]; + // Subtract 1 from `b`, to convert from one- to zero-indexed. + const b = parsed[1] - 1; + /* + * When `b <= 0`, `a * n` won't be lead to any matches for `a < 0`. + * Besides, the specification states that no elements are + * matched when `a` and `b` are 0. + * + * `b < 0` here as we subtracted 1 from `b` above. + */ + if (b < 0 && a <= 0) + return boolbase$1.falseFunc; + // When `a` is in the range -1..1, it matches any element (so only `b` is checked). + if (a === -1) + return (index) => index <= b; + if (a === 0) + return (index) => index === b; + // When `b <= 0` and `a === 1`, they match any element. + if (a === 1) + return b < 0 ? boolbase$1.trueFunc : (index) => index >= b; + /* + * Otherwise, modulo can be used to check if there is a match. + * + * Modulo doesn't care about the sign, so let's use `a`s absolute value. + */ + const absA = Math.abs(a); + // Get `b mod a`, + a if this is negative. + const bMod = ((b % absA) + absA) % absA; + return a > 1 + ? (index) => index >= b && index % absA === bMod + : (index) => index <= b && index % absA === bMod; + } + + /** + * Parses and compiles a formula to a highly optimized function. + * Combination of {@link parse} and {@link compile}. + * + * If the formula doesn't match any elements, + * it returns [`boolbase`](https://github.com/fb55/boolbase)'s `falseFunc`. + * Otherwise, a function accepting an _index_ is returned, which returns + * whether or not the passed _index_ matches the formula. + * + * Note: The nth-rule starts counting at `1`, the returned function at `0`. + * + * @param formula The formula to compile. + * @example + * const check = nthCheck("2n+3"); + * + * check(0); // `false` + * check(1); // `false` + * check(2); // `true` + * check(3); // `false` + * check(4); // `true` + * check(5); // `false` + * check(6); // `true` + */ + function nthCheck(formula) { + return compile$2(parse$9(formula)); + } + + function getChildFunc(next, adapter) { + return (elem) => { + const parent = adapter.getParent(elem); + return parent != null && adapter.isTag(parent) && next(elem); + }; + } + const filters = { + contains(next, text, { adapter }) { + return function contains(elem) { + return next(elem) && adapter.getText(elem).includes(text); + }; + }, + icontains(next, text, { adapter }) { + const itext = text.toLowerCase(); + return function icontains(elem) { + return (next(elem) && + adapter.getText(elem).toLowerCase().includes(itext)); + }; + }, + // Location specific methods + "nth-child"(next, rule, { adapter, equals }) { + const func = nthCheck(rule); + if (func === boolbase$1.falseFunc) + return boolbase$1.falseFunc; + if (func === boolbase$1.trueFunc) + return getChildFunc(next, adapter); + return function nthChild(elem) { + const siblings = adapter.getSiblings(elem); + let pos = 0; + for (let i = 0; i < siblings.length; i++) { + if (equals(elem, siblings[i])) + break; + if (adapter.isTag(siblings[i])) { + pos++; + } + } + return func(pos) && next(elem); + }; + }, + "nth-last-child"(next, rule, { adapter, equals }) { + const func = nthCheck(rule); + if (func === boolbase$1.falseFunc) + return boolbase$1.falseFunc; + if (func === boolbase$1.trueFunc) + return getChildFunc(next, adapter); + return function nthLastChild(elem) { + const siblings = adapter.getSiblings(elem); + let pos = 0; + for (let i = siblings.length - 1; i >= 0; i--) { + if (equals(elem, siblings[i])) + break; + if (adapter.isTag(siblings[i])) { + pos++; + } + } + return func(pos) && next(elem); + }; + }, + "nth-of-type"(next, rule, { adapter, equals }) { + const func = nthCheck(rule); + if (func === boolbase$1.falseFunc) + return boolbase$1.falseFunc; + if (func === boolbase$1.trueFunc) + return getChildFunc(next, adapter); + return function nthOfType(elem) { + const siblings = adapter.getSiblings(elem); + let pos = 0; + for (let i = 0; i < siblings.length; i++) { + const currentSibling = siblings[i]; + if (equals(elem, currentSibling)) + break; + if (adapter.isTag(currentSibling) && + adapter.getName(currentSibling) === adapter.getName(elem)) { + pos++; + } + } + return func(pos) && next(elem); + }; + }, + "nth-last-of-type"(next, rule, { adapter, equals }) { + const func = nthCheck(rule); + if (func === boolbase$1.falseFunc) + return boolbase$1.falseFunc; + if (func === boolbase$1.trueFunc) + return getChildFunc(next, adapter); + return function nthLastOfType(elem) { + const siblings = adapter.getSiblings(elem); + let pos = 0; + for (let i = siblings.length - 1; i >= 0; i--) { + const currentSibling = siblings[i]; + if (equals(elem, currentSibling)) + break; + if (adapter.isTag(currentSibling) && + adapter.getName(currentSibling) === adapter.getName(elem)) { + pos++; + } + } + return func(pos) && next(elem); + }; + }, + // TODO determine the actual root element + root(next, _rule, { adapter }) { + return (elem) => { + const parent = adapter.getParent(elem); + return (parent == null || !adapter.isTag(parent)) && next(elem); + }; + }, + scope(next, rule, options, context) { + const { equals } = options; + if (!context || context.length === 0) { + // Equivalent to :root + return filters["root"](next, rule, options); + } + if (context.length === 1) { + // NOTE: can't be unpacked, as :has uses this for side-effects + return (elem) => equals(context[0], elem) && next(elem); + } + return (elem) => context.includes(elem) && next(elem); + }, + hover: dynamicStatePseudo("isHovered"), + visited: dynamicStatePseudo("isVisited"), + active: dynamicStatePseudo("isActive"), + }; + /** + * Dynamic state pseudos. These depend on optional Adapter methods. + * + * @param name The name of the adapter method to call. + * @returns Pseudo for the `filters` object. + */ + function dynamicStatePseudo(name) { + return function dynamicPseudo(next, _rule, { adapter }) { + const func = adapter[name]; + if (typeof func !== "function") { + return boolbase$1.falseFunc; + } + return function active(elem) { + return func(elem) && next(elem); + }; + }; + } + + // While filters are precompiled, pseudos get called when they are needed + const pseudos = { + empty(elem, { adapter }) { + return !adapter.getChildren(elem).some((elem) => + // FIXME: `getText` call is potentially expensive. + adapter.isTag(elem) || adapter.getText(elem) !== ""); + }, + "first-child"(elem, { adapter, equals }) { + if (adapter.prevElementSibling) { + return adapter.prevElementSibling(elem) == null; + } + const firstChild = adapter + .getSiblings(elem) + .find((elem) => adapter.isTag(elem)); + return firstChild != null && equals(elem, firstChild); + }, + "last-child"(elem, { adapter, equals }) { + const siblings = adapter.getSiblings(elem); + for (let i = siblings.length - 1; i >= 0; i--) { + if (equals(elem, siblings[i])) + return true; + if (adapter.isTag(siblings[i])) + break; + } + return false; + }, + "first-of-type"(elem, { adapter, equals }) { + const siblings = adapter.getSiblings(elem); + const elemName = adapter.getName(elem); + for (let i = 0; i < siblings.length; i++) { + const currentSibling = siblings[i]; + if (equals(elem, currentSibling)) + return true; + if (adapter.isTag(currentSibling) && + adapter.getName(currentSibling) === elemName) { + break; + } + } + return false; + }, + "last-of-type"(elem, { adapter, equals }) { + const siblings = adapter.getSiblings(elem); + const elemName = adapter.getName(elem); + for (let i = siblings.length - 1; i >= 0; i--) { + const currentSibling = siblings[i]; + if (equals(elem, currentSibling)) + return true; + if (adapter.isTag(currentSibling) && + adapter.getName(currentSibling) === elemName) { + break; + } + } + return false; + }, + "only-of-type"(elem, { adapter, equals }) { + const elemName = adapter.getName(elem); + return adapter + .getSiblings(elem) + .every((sibling) => equals(elem, sibling) || + !adapter.isTag(sibling) || + adapter.getName(sibling) !== elemName); + }, + "only-child"(elem, { adapter, equals }) { + return adapter + .getSiblings(elem) + .every((sibling) => equals(elem, sibling) || !adapter.isTag(sibling)); + }, + }; + function verifyPseudoArgs(func, name, subselect, argIndex) { + if (subselect === null) { + if (func.length > argIndex) { + throw new Error(`Pseudo-class :${name} requires an argument`); + } + } + else if (func.length === argIndex) { + throw new Error(`Pseudo-class :${name} doesn't have any arguments`); + } + } + + /** + * Aliases are pseudos that are expressed as selectors. + */ + const aliases = { + // Links + "any-link": ":is(a, area, link)[href]", + link: ":any-link:not(:visited)", + // Forms + // https://html.spec.whatwg.org/multipage/scripting.html#disabled-elements + disabled: `:is( + :is(button, input, select, textarea, optgroup, option)[disabled], + optgroup[disabled] > option, + fieldset[disabled]:not(fieldset[disabled] legend:first-of-type *) + )`, + enabled: ":not(:disabled)", + checked: ":is(:is(input[type=radio], input[type=checkbox])[checked], option:selected)", + required: ":is(input, select, textarea)[required]", + optional: ":is(input, select, textarea):not([required])", + // JQuery extensions + // https://html.spec.whatwg.org/multipage/form-elements.html#concept-option-selectedness + selected: "option:is([selected], select:not([multiple]):not(:has(> option[selected])) > :first-of-type)", + checkbox: "[type=checkbox]", + file: "[type=file]", + password: "[type=password]", + radio: "[type=radio]", + reset: "[type=reset]", + image: "[type=image]", + submit: "[type=submit]", + parent: ":not(:empty)", + header: ":is(h1, h2, h3, h4, h5, h6)", + button: ":is(button, input[type=button])", + input: ":is(input, textarea, select, button)", + text: "input:is(:not([type!='']), [type=text])", + }; + + /** Used as a placeholder for :has. Will be replaced with the actual element. */ + const PLACEHOLDER_ELEMENT = {}; + function ensureIsTag(next, adapter) { + if (next === boolbase$1.falseFunc) + return boolbase$1.falseFunc; + return (elem) => adapter.isTag(elem) && next(elem); + } + function getNextSiblings(elem, adapter) { + const siblings = adapter.getSiblings(elem); + if (siblings.length <= 1) + return []; + const elemIndex = siblings.indexOf(elem); + if (elemIndex < 0 || elemIndex === siblings.length - 1) + return []; + return siblings.slice(elemIndex + 1).filter(adapter.isTag); + } + function copyOptions(options) { + // Not copied: context, rootFunc + return { + xmlMode: !!options.xmlMode, + lowerCaseAttributeNames: !!options.lowerCaseAttributeNames, + lowerCaseTags: !!options.lowerCaseTags, + quirksMode: !!options.quirksMode, + cacheResults: !!options.cacheResults, + pseudos: options.pseudos, + adapter: options.adapter, + equals: options.equals, + }; + } + const is$1 = (next, token, options, context, compileToken) => { + const func = compileToken(token, copyOptions(options), context); + return func === boolbase$1.trueFunc + ? next + : func === boolbase$1.falseFunc + ? boolbase$1.falseFunc + : (elem) => func(elem) && next(elem); + }; + /* + * :not, :has, :is, :matches and :where have to compile selectors + * doing this in src/pseudos.ts would lead to circular dependencies, + * so we add them here + */ + const subselects = { + is: is$1, + /** + * `:matches` and `:where` are aliases for `:is`. + */ + matches: is$1, + where: is$1, + not(next, token, options, context, compileToken) { + const func = compileToken(token, copyOptions(options), context); + return func === boolbase$1.falseFunc + ? next + : func === boolbase$1.trueFunc + ? boolbase$1.falseFunc + : (elem) => !func(elem) && next(elem); + }, + has(next, subselect, options, _context, compileToken) { + const { adapter } = options; + const opts = copyOptions(options); + opts.relativeSelector = true; + const context = subselect.some((s) => s.some(isTraversal)) + ? // Used as a placeholder. Will be replaced with the actual element. + [PLACEHOLDER_ELEMENT] + : undefined; + const compiled = compileToken(subselect, opts, context); + if (compiled === boolbase$1.falseFunc) + return boolbase$1.falseFunc; + const hasElement = ensureIsTag(compiled, adapter); + // If `compiled` is `trueFunc`, we can skip this. + if (context && compiled !== boolbase$1.trueFunc) { + /* + * `shouldTestNextSiblings` will only be true if the query starts with + * a traversal (sibling or adjacent). That means we will always have a context. + */ + const { shouldTestNextSiblings = false } = compiled; + return (elem) => { + if (!next(elem)) + return false; + context[0] = elem; + const childs = adapter.getChildren(elem); + const nextElements = shouldTestNextSiblings + ? [...childs, ...getNextSiblings(elem, adapter)] + : childs; + return adapter.existsOne(hasElement, nextElements); + }; + } + return (elem) => next(elem) && + adapter.existsOne(hasElement, adapter.getChildren(elem)); + }, + }; + + function compilePseudoSelector(next, selector, options, context, compileToken) { + var _a; + const { name, data } = selector; + if (Array.isArray(data)) { + if (!(name in subselects)) { + throw new Error(`Unknown pseudo-class :${name}(${data})`); + } + return subselects[name](next, data, options, context, compileToken); + } + const userPseudo = (_a = options.pseudos) === null || _a === void 0 ? void 0 : _a[name]; + const stringPseudo = typeof userPseudo === "string" ? userPseudo : aliases[name]; + if (typeof stringPseudo === "string") { + if (data != null) { + throw new Error(`Pseudo ${name} doesn't have any arguments`); + } + // The alias has to be parsed here, to make sure options are respected. + const alias = parse$a(stringPseudo); + return subselects["is"](next, alias, options, context, compileToken); + } + if (typeof userPseudo === "function") { + verifyPseudoArgs(userPseudo, name, data, 1); + return (elem) => userPseudo(elem, data) && next(elem); + } + if (name in filters) { + return filters[name](next, data, options, context); + } + if (name in pseudos) { + const pseudo = pseudos[name]; + verifyPseudoArgs(pseudo, name, data, 2); + return (elem) => pseudo(elem, options, data) && next(elem); + } + throw new Error(`Unknown pseudo-class :${name}`); + } + + function getElementParent(node, adapter) { + const parent = adapter.getParent(node); + if (parent && adapter.isTag(parent)) { + return parent; + } + return null; + } + /* + * All available rules + */ + function compileGeneralSelector(next, selector, options, context, compileToken) { + const { adapter, equals } = options; + switch (selector.type) { + case SelectorType.PseudoElement: { + throw new Error("Pseudo-elements are not supported by css-select"); + } + case SelectorType.ColumnCombinator: { + throw new Error("Column combinators are not yet supported by css-select"); + } + case SelectorType.Attribute: { + if (selector.namespace != null) { + throw new Error("Namespaced attributes are not yet supported by css-select"); + } + if (!options.xmlMode || options.lowerCaseAttributeNames) { + selector.name = selector.name.toLowerCase(); + } + return attributeRules[selector.action](next, selector, options); + } + case SelectorType.Pseudo: { + return compilePseudoSelector(next, selector, options, context, compileToken); + } + // Tags + case SelectorType.Tag: { + if (selector.namespace != null) { + throw new Error("Namespaced tag names are not yet supported by css-select"); + } + let { name } = selector; + if (!options.xmlMode || options.lowerCaseTags) { + name = name.toLowerCase(); + } + return function tag(elem) { + return adapter.getName(elem) === name && next(elem); + }; + } + // Traversal + case SelectorType.Descendant: { + if (options.cacheResults === false || + typeof WeakSet === "undefined") { + return function descendant(elem) { + let current = elem; + while ((current = getElementParent(current, adapter))) { + if (next(current)) { + return true; + } + } + return false; + }; + } + // @ts-expect-error `ElementNode` is not extending object + const isFalseCache = new WeakSet(); + return function cachedDescendant(elem) { + let current = elem; + while ((current = getElementParent(current, adapter))) { + if (!isFalseCache.has(current)) { + if (adapter.isTag(current) && next(current)) { + return true; + } + isFalseCache.add(current); + } + } + return false; + }; + } + case "_flexibleDescendant": { + // Include element itself, only used while querying an array + return function flexibleDescendant(elem) { + let current = elem; + do { + if (next(current)) + return true; + } while ((current = getElementParent(current, adapter))); + return false; + }; + } + case SelectorType.Parent: { + return function parent(elem) { + return adapter + .getChildren(elem) + .some((elem) => adapter.isTag(elem) && next(elem)); + }; + } + case SelectorType.Child: { + return function child(elem) { + const parent = adapter.getParent(elem); + return parent != null && adapter.isTag(parent) && next(parent); + }; + } + case SelectorType.Sibling: { + return function sibling(elem) { + const siblings = adapter.getSiblings(elem); + for (let i = 0; i < siblings.length; i++) { + const currentSibling = siblings[i]; + if (equals(elem, currentSibling)) + break; + if (adapter.isTag(currentSibling) && next(currentSibling)) { + return true; + } + } + return false; + }; + } + case SelectorType.Adjacent: { + if (adapter.prevElementSibling) { + return function adjacent(elem) { + const previous = adapter.prevElementSibling(elem); + return previous != null && next(previous); + }; + } + return function adjacent(elem) { + const siblings = adapter.getSiblings(elem); + let lastElement; + for (let i = 0; i < siblings.length; i++) { + const currentSibling = siblings[i]; + if (equals(elem, currentSibling)) + break; + if (adapter.isTag(currentSibling)) { + lastElement = currentSibling; + } + } + return !!lastElement && next(lastElement); + }; + } + case SelectorType.Universal: { + if (selector.namespace != null && selector.namespace !== "*") { + throw new Error("Namespaced universal selectors are not yet supported by css-select"); + } + return next; + } + } + } + + /** + * Compiles a selector to an executable function. + * + * @param selector Selector to compile. + * @param options Compilation options. + * @param context Optional context for the selector. + */ + function compile$1(selector, options, context) { + const next = compileUnsafe(selector, options, context); + return ensureIsTag(next, options.adapter); + } + function compileUnsafe(selector, options, context) { + const token = typeof selector === "string" ? parse$a(selector) : selector; + return compileToken(token, options, context); + } + function includesScopePseudo(t) { + return (t.type === SelectorType.Pseudo && + (t.name === "scope" || + (Array.isArray(t.data) && + t.data.some((data) => data.some(includesScopePseudo))))); + } + const DESCENDANT_TOKEN = { type: SelectorType.Descendant }; + const FLEXIBLE_DESCENDANT_TOKEN = { + type: "_flexibleDescendant", + }; + const SCOPE_TOKEN = { + type: SelectorType.Pseudo, + name: "scope", + data: null, + }; + /* + * CSS 4 Spec (Draft): 3.4.1. Absolutizing a Relative Selector + * http://www.w3.org/TR/selectors4/#absolutizing + */ + function absolutize(token, { adapter }, context) { + // TODO Use better check if the context is a document + const hasContext = !!(context === null || context === void 0 ? void 0 : context.every((e) => { + const parent = adapter.isTag(e) && adapter.getParent(e); + return e === PLACEHOLDER_ELEMENT || (parent && adapter.isTag(parent)); + })); + for (const t of token) { + if (t.length > 0 && + isTraversal(t[0]) && + t[0].type !== SelectorType.Descendant) ; + else if (hasContext && !t.some(includesScopePseudo)) { + t.unshift(DESCENDANT_TOKEN); + } + else { + continue; + } + t.unshift(SCOPE_TOKEN); + } + } + function compileToken(token, options, context) { + var _a; + token.forEach(sortByProcedure); + context = (_a = options.context) !== null && _a !== void 0 ? _a : context; + const isArrayContext = Array.isArray(context); + const finalContext = context && (Array.isArray(context) ? context : [context]); + // Check if the selector is relative + if (options.relativeSelector !== false) { + absolutize(token, options, finalContext); + } + else if (token.some((t) => t.length > 0 && isTraversal(t[0]))) { + throw new Error("Relative selectors are not allowed when the `relativeSelector` option is disabled"); + } + let shouldTestNextSiblings = false; + const query = token + .map((rules) => { + if (rules.length >= 2) { + const [first, second] = rules; + if (first.type !== SelectorType.Pseudo || + first.name !== "scope") ; + else if (isArrayContext && + second.type === SelectorType.Descendant) { + rules[1] = FLEXIBLE_DESCENDANT_TOKEN; + } + else if (second.type === SelectorType.Adjacent || + second.type === SelectorType.Sibling) { + shouldTestNextSiblings = true; + } + } + return compileRules(rules, options, finalContext); + }) + .reduce(reduceRules, boolbase$1.falseFunc); + query.shouldTestNextSiblings = shouldTestNextSiblings; + return query; + } + function compileRules(rules, options, context) { + var _a; + return rules.reduce((previous, rule) => previous === boolbase$1.falseFunc + ? boolbase$1.falseFunc + : compileGeneralSelector(previous, rule, options, context, compileToken), (_a = options.rootFunc) !== null && _a !== void 0 ? _a : boolbase$1.trueFunc); + } + function reduceRules(a, b) { + if (b === boolbase$1.falseFunc || a === boolbase$1.trueFunc) { + return a; + } + if (a === boolbase$1.falseFunc || b === boolbase$1.trueFunc) { + return b; + } + return function combine(elem) { + return a(elem) || b(elem); + }; + } + + const defaultEquals = (a, b) => a === b; + const defaultOptions = { + adapter: DomUtils, + equals: defaultEquals, + }; + function convertOptionFormats(options) { + var _a, _b, _c, _d; + /* + * We force one format of options to the other one. + */ + // @ts-expect-error Default options may have incompatible `Node` / `ElementNode`. + const opts = options !== null && options !== void 0 ? options : defaultOptions; + // @ts-expect-error Same as above. + (_a = opts.adapter) !== null && _a !== void 0 ? _a : (opts.adapter = DomUtils); + // @ts-expect-error `equals` does not exist on `Options` + (_b = opts.equals) !== null && _b !== void 0 ? _b : (opts.equals = (_d = (_c = opts.adapter) === null || _c === void 0 ? void 0 : _c.equals) !== null && _d !== void 0 ? _d : defaultEquals); + return opts; + } + function wrapCompile(func) { + return function addAdapter(selector, options, context) { + const opts = convertOptionFormats(options); + return func(selector, opts, context); + }; + } + /** + * Compiles the query, returns a function. + */ + const compile = wrapCompile(compile$1); + /** + * Tests whether or not an element is matched by query. + * + * @template Node The generic Node type for the DOM adapter being used. + * @template ElementNode The Node type for elements for the DOM adapter being used. + * @param elem The element to test if it matches the query. + * @param query can be either a CSS selector string or a compiled query function. + * @param [options] options for querying the document. + * @see compile for supported selector queries. + * @returns + */ + function is(elem, query, options) { + const opts = convertOptionFormats(options); + return (typeof query === "function" ? query : compile$1(query, opts))(elem); + } + + const {isArray: isArray$2} = Array; + + /* c8 ignore start */ + const isTag$1 = ({nodeType}) => nodeType === ELEMENT_NODE; + + const existsOne$1 = (test, elements) => elements.some( + element => isTag$1(element) && ( + test(element) || + existsOne$1(test, getChildren$1(element)) + ) + ); + + const getAttributeValue$1 = (element, name) => name === 'class' ? + element.classList.value : element.getAttribute(name); + + const getChildren$1 = ({childNodes}) => childNodes; + + const getName$1 = (element) => { + const {localName} = element; + return ignoreCase(element) ? localName.toLowerCase() : localName; + }; + + const getParent$1 = ({parentNode}) => parentNode; + + const getSiblings$1 = element => { + const {parentNode} = element; + return parentNode ? getChildren$1(parentNode) : element; + }; + + const getText$1 = node => { + if (isArray$2(node)) + return node.map(getText$1).join(''); + if (isTag$1(node)) + return getText$1(getChildren$1(node)); + if (node.nodeType === TEXT_NODE) + return node.data; + return ''; + }; + + const hasAttrib$1 = (element, name) => element.hasAttribute(name); + + const removeSubsets = nodes => { + let {length} = nodes; + while (length--) { + const node = nodes[length]; + if (length && -1 < nodes.lastIndexOf(node, length - 1)) { + nodes.splice(length, 1); + continue; + } + for (let {parentNode} = node; parentNode; parentNode = parentNode.parentNode) { + if (nodes.includes(parentNode)) { + nodes.splice(length, 1); + break; + } + } + } + return nodes; + }; + + const findAll$1 = (test, nodes) => { + const matches = []; + for (const node of nodes) { + if (isTag$1(node)) { + if (test(node)) + matches.push(node); + matches.push(...findAll$1(test, getChildren$1(node))); + } + } + return matches; + }; + + const findOne$1 = (test, nodes) => { + for (let node of nodes) + if (test(node) || (node = findOne$1(test, getChildren$1(node)))) + return node; + return null; + }; + /* c8 ignore stop */ + + const adapter = { + isTag: isTag$1, + existsOne: existsOne$1, + getAttributeValue: getAttributeValue$1, + getChildren: getChildren$1, + getName: getName$1, + getParent: getParent$1, + getSiblings: getSiblings$1, + getText: getText$1, + hasAttrib: hasAttrib$1, + removeSubsets, + findAll: findAll$1, + findOne: findOne$1 + }; + + const prepareMatch = (element, selectors) => compile( + selectors, + { + context: selectors.includes(':scope') ? element : void 0, + xmlMode: !ignoreCase(element), + adapter + } + ); + + const matches = (element, selectors) => is( + element, + selectors, + { + strict: true, + context: selectors.includes(':scope') ? element : void 0, + xmlMode: !ignoreCase(element), + adapter + } + ); + + /** + * @implements globalThis.Text + */ + let Text$2 = class Text extends CharacterData$1 { + constructor(ownerDocument, data = '') { + super(ownerDocument, '#text', TEXT_NODE, data); + } + + get wholeText() { + const text = []; + let {previousSibling, nextSibling} = this; + while (previousSibling) { + if (previousSibling.nodeType === TEXT_NODE) + text.unshift(previousSibling[VALUE]); + else + break; + previousSibling = previousSibling.previousSibling; + } + text.push(this[VALUE]); + while (nextSibling) { + if (nextSibling.nodeType === TEXT_NODE) + text.push(nextSibling[VALUE]); + else + break; + nextSibling = nextSibling.nextSibling; + } + return text.join(''); + } + + cloneNode() { + const {ownerDocument, [VALUE]: data} = this; + return new Text(ownerDocument, data); + } + + toString() { return escape$1(this[VALUE]); } + }; + + // https://dom.spec.whatwg.org/#interface-parentnode + // Document, DocumentFragment, Element + + + const isNode = node => node instanceof Node$7; + + const insert = (parentNode, child, nodes) => { + const {ownerDocument} = parentNode; + for (const node of nodes) + parentNode.insertBefore( + isNode(node) ? node : new Text$2(ownerDocument, node), + child + ); + }; + + /** @typedef { import('../interface/element.js').Element & { + [typeof NEXT]: NodeStruct, + [typeof PREV]: NodeStruct, + [typeof START]: NodeStruct, + nodeType: typeof ATTRIBUTE_NODE | typeof DOCUMENT_FRAGMENT_NODE | typeof ELEMENT_NODE | typeof TEXT_NODE | typeof NODE_END | typeof COMMENT_NODE | typeof CDATA_SECTION_NODE, + ownerDocument: Document, + parentNode: ParentNode, + }} NodeStruct */ + + class ParentNode extends Node$7 { + constructor(ownerDocument, localName, nodeType) { + super(ownerDocument, localName, nodeType); + this[PRIVATE] = null; + /** @type {NodeStruct} */ + this[NEXT] = this[END] = { + [NEXT]: null, + [PREV]: this, + [START]: this, + nodeType: NODE_END, + ownerDocument: this.ownerDocument, + parentNode: null + }; + } + + get childNodes() { + const childNodes = new NodeList; + let {firstChild} = this; + while (firstChild) { + childNodes.push(firstChild); + firstChild = nextSibling(firstChild); + } + return childNodes; + } + + get children() { + const children = new NodeList; + let {firstElementChild} = this; + while (firstElementChild) { + children.push(firstElementChild); + firstElementChild = nextElementSibling$1(firstElementChild); + } + return children; + } + + /** + * @returns {NodeStruct | null} + */ + get firstChild() { + let {[NEXT]: next, [END]: end} = this; + while (next.nodeType === ATTRIBUTE_NODE) + next = next[NEXT]; + return next === end ? null : next; + } + + /** + * @returns {NodeStruct | null} + */ + get firstElementChild() { + let {firstChild} = this; + while (firstChild) { + if (firstChild.nodeType === ELEMENT_NODE) + return firstChild; + firstChild = nextSibling(firstChild); + } + return null; + } + + get lastChild() { + const prev = this[END][PREV]; + switch (prev.nodeType) { + case NODE_END: + return prev[START]; + case ATTRIBUTE_NODE: + return null; + } + return prev === this ? null : prev; + } + + get lastElementChild() { + let {lastChild} = this; + while (lastChild) { + if (lastChild.nodeType === ELEMENT_NODE) + return lastChild; + lastChild = previousSibling(lastChild); + } + return null; + } + + get childElementCount() { + return this.children.length; + } + + prepend(...nodes) { + insert(this, this.firstChild, nodes); + } + + append(...nodes) { + insert(this, this[END], nodes); + } + + replaceChildren(...nodes) { + let {[NEXT]: next, [END]: end} = this; + while (next !== end && next.nodeType === ATTRIBUTE_NODE) + next = next[NEXT]; + while (next !== end) { + const after = getEnd(next)[NEXT]; + next.remove(); + next = after; + } + if (nodes.length) + insert(this, end, nodes); + } + + getElementsByClassName(className) { + const elements = new NodeList; + let {[NEXT]: next, [END]: end} = this; + while (next !== end) { + if ( + next.nodeType === ELEMENT_NODE && + next.hasAttribute('class') && + next.classList.has(className) + ) + elements.push(next); + next = next[NEXT]; + } + return elements; + } + + getElementsByTagName(tagName) { + const elements = new NodeList; + let {[NEXT]: next, [END]: end} = this; + while (next !== end) { + if (next.nodeType === ELEMENT_NODE && ( + next.localName === tagName || + localCase(next) === tagName + )) + elements.push(next); + next = next[NEXT]; + } + return elements; + } + + querySelector(selectors) { + const matches = prepareMatch(this, selectors); + let {[NEXT]: next, [END]: end} = this; + while (next !== end) { + if (next.nodeType === ELEMENT_NODE && matches(next)) + return next; + next = next.nodeType === ELEMENT_NODE && next.localName === 'template' ? next[END] : next[NEXT]; + } + return null; + } + + querySelectorAll(selectors) { + const matches = prepareMatch(this, selectors); + const elements = new NodeList; + let {[NEXT]: next, [END]: end} = this; + while (next !== end) { + if (next.nodeType === ELEMENT_NODE && matches(next)) + elements.push(next); + next = next.nodeType === ELEMENT_NODE && next.localName === 'template' ? next[END] : next[NEXT]; + } + return elements; + } + + appendChild(node) { + return this.insertBefore(node, this[END]); + } + + contains(node) { + let parentNode = node; + while (parentNode && parentNode !== this) + parentNode = parentNode.parentNode; + return parentNode === this; + } + + insertBefore(node, before = null) { + if (node === before) + return node; + if (node === this) + throw new Error('unable to append a node to itself'); + const next = before || this[END]; + switch (node.nodeType) { + case ELEMENT_NODE: + node.remove(); + node.parentNode = this; + knownBoundaries(next[PREV], node, next); + moCallback(node, null); + connectedCallback(node); + break; + case DOCUMENT_FRAGMENT_NODE: { + let {[PRIVATE]: parentNode, firstChild, lastChild} = node; + if (firstChild) { + knownSegment(next[PREV], firstChild, lastChild, next); + knownAdjacent(node, node[END]); + if (parentNode) + parentNode.replaceChildren(); + do { + firstChild.parentNode = this; + moCallback(firstChild, null); + if (firstChild.nodeType === ELEMENT_NODE) + connectedCallback(firstChild); + } while ( + firstChild !== lastChild && + (firstChild = nextSibling(firstChild)) + ); + } + break; + } + case TEXT_NODE: + case COMMENT_NODE: + case CDATA_SECTION_NODE: + node.remove(); + /* eslint no-fallthrough:0 */ + // this covers DOCUMENT_TYPE_NODE too + default: + node.parentNode = this; + knownSiblings(next[PREV], node, next); + moCallback(node, null); + break; + } + return node; + } + + normalize() { + let {[NEXT]: next, [END]: end} = this; + while (next !== end) { + const {[NEXT]: $next, [PREV]: $prev, nodeType} = next; + if (nodeType === TEXT_NODE) { + if (!next[VALUE]) + next.remove(); + else if ($prev && $prev.nodeType === TEXT_NODE) { + $prev.textContent += next.textContent; + next.remove(); + } + } + next = $next; + } + } + + removeChild(node) { + if (node.parentNode !== this) + throw new Error('node is not a child'); + node.remove(); + return node; + } + + replaceChild(node, replaced) { + const next = getEnd(replaced)[NEXT]; + replaced.remove(); + this.insertBefore(node, next); + return replaced; + } + } + + // https://dom.spec.whatwg.org/#interface-nonelementparentnode + // Document, DocumentFragment + + + class NonElementParentNode extends ParentNode { + getElementById(id) { + let {[NEXT]: next, [END]: end} = this; + while (next !== end) { + if (next.nodeType === ELEMENT_NODE && next.id === id) + return next; + next = next[NEXT]; + } + return null; + } + + cloneNode(deep) { + const {ownerDocument, constructor} = this; + const nonEPN = new constructor(ownerDocument); + if (deep) { + const {[END]: end} = nonEPN; + for (const node of this.childNodes) + nonEPN.insertBefore(node.cloneNode(deep), end); + } + return nonEPN; + } + + toString() { + const {childNodes, localName} = this; + return `<${localName}>${childNodes.join('')}</${localName}>`; + } + + toJSON() { + const json = []; + nonElementAsJSON(this, json); + return json; + } + } + + /** + * @implements globalThis.DocumentFragment + */ + let DocumentFragment$1 = class DocumentFragment extends NonElementParentNode { + constructor(ownerDocument) { + super(ownerDocument, '#document-fragment', DOCUMENT_FRAGMENT_NODE); + } + }; + + /** + * @implements globalThis.DocumentType + */ + let DocumentType$1 = class DocumentType extends Node$7 { + constructor(ownerDocument, name, publicId = '', systemId = '') { + super(ownerDocument, '#document-type', DOCUMENT_TYPE_NODE); + this.name = name; + this.publicId = publicId; + this.systemId = systemId; + } + + cloneNode() { + const {ownerDocument, name, publicId, systemId} = this; + return new DocumentType(ownerDocument, name, publicId, systemId); + } + + toString() { + const {name, publicId, systemId} = this; + const hasPublic = 0 < publicId.length; + const str = [name]; + if (hasPublic) + str.push('PUBLIC', `"${publicId}"`); + if (systemId.length) { + if (!hasPublic) + str.push('SYSTEM'); + str.push(`"${systemId}"`); + } + return `<!DOCTYPE ${str.join(' ')}>`; + } + + toJSON() { + const json = []; + documentTypeAsJSON(this, json); + return json; + } + }; + + /** + * @param {Node} node + * @returns {String} + */ + const getInnerHtml = node => node.childNodes.join(''); + + /** + * @param {Node} node + * @param {String} html + */ + const setInnerHtml = (node, html) => { + const {ownerDocument} = node; + const {constructor} = ownerDocument; + const document = new constructor; + document[CUSTOM_ELEMENTS] = ownerDocument[CUSTOM_ELEMENTS]; + const {childNodes} = parseFromString(document, ignoreCase(node), html); + + node.replaceChildren(...childNodes.map(setOwnerDocument, ownerDocument)); + }; + + function setOwnerDocument(node) { + node.ownerDocument = this; + switch (node.nodeType) { + case ELEMENT_NODE: + case DOCUMENT_FRAGMENT_NODE: + node.childNodes.forEach(setOwnerDocument, this); + break; + } + return node; + } + + var uhyphen = camel => camel.replace(/(([A-Z0-9])([A-Z0-9][a-z]))|(([a-z0-9]+)([A-Z]))/g, '$2$5-$3$6') + .toLowerCase(); + + const refs$1 = new WeakMap; + + const key = name => `data-${uhyphen(name)}`; + const prop = name => name.slice(5).replace(/-([a-z])/g, (_, $1) => $1.toUpperCase()); + + const handler$2 = { + get(dataset, name) { + if (name in dataset) + return refs$1.get(dataset).getAttribute(key(name)); + }, + + set(dataset, name, value) { + dataset[name] = value; + refs$1.get(dataset).setAttribute(key(name), value); + return true; + }, + + deleteProperty(dataset, name) { + if (name in dataset) + refs$1.get(dataset).removeAttribute(key(name)); + return delete dataset[name]; + } + }; + + /** + * @implements globalThis.DOMStringMap + */ + class DOMStringMap { + /** + * @param {Element} ref + */ + constructor(ref) { + for (const {name, value} of ref.attributes) { + if (/^data-/.test(name)) + this[prop(name)] = value; + } + refs$1.set(this, ref); + return new Proxy(this, handler$2); + } + } + + setPrototypeOf(DOMStringMap.prototype, null); + + const {add: add$1} = Set.prototype; + const addTokens = (self, tokens) => { + for (const token of tokens) { + if (token) + add$1.call(self, token); + } + }; + + const update = ({[OWNER_ELEMENT]: ownerElement, value}) => { + const attribute = ownerElement.getAttributeNode('class'); + if (attribute) + attribute.value = value; + else + setAttribute( + ownerElement, + new Attr$1(ownerElement.ownerDocument, 'class', value) + ); + }; + + /** + * @implements globalThis.DOMTokenList + */ + class DOMTokenList extends Set { + + constructor(ownerElement) { + super(); + this[OWNER_ELEMENT] = ownerElement; + const attribute = ownerElement.getAttributeNode('class'); + if (attribute) + addTokens(this, attribute.value.split(/\s+/)); + } + + get length() { return this.size; } + + get value() { return [...this].join(' '); } + + /** + * @param {...string} tokens + */ + add(...tokens) { + addTokens(this, tokens); + update(this); + } + + /** + * @param {string} token + */ + contains(token) { return this.has(token); } + + /** + * @param {...string} tokens + */ + remove(...tokens) { + for (const token of tokens) + this.delete(token); + update(this); + } + + /** + * @param {string} token + * @param {boolean?} force + */ + toggle(token, force) { + if (this.has(token)) { + if (force) + return true; + this.delete(token); + update(this); + } + else if (force || arguments.length === 1) { + super.add(token); + update(this); + return true; + } + return false; + } + + /** + * @param {string} token + * @param {string} newToken + */ + replace(token, newToken) { + if (this.has(token)) { + this.delete(token); + super.add(newToken); + update(this); + return true; + } + return false; + } + + /** + * @param {string} token + */ + supports() { return true; } + } + + const refs = new WeakMap; + + const getKeys$1 = style => [...style.keys()].filter(key => key !== PRIVATE); + + const updateKeys = style => { + const attr = refs.get(style).getAttributeNode('style'); + if (!attr || attr[CHANGED] || style.get(PRIVATE) !== attr) { + style.clear(); + if (attr) { + style.set(PRIVATE, attr); + for (const rule of attr[VALUE].split(/\s*;\s*/)) { + let [key, ...rest] = rule.split(':'); + if (rest.length > 0) { + key = key.trim(); + const value = rest.join(':').trim(); + if (key && value) + style.set(key, value); + } + } + } + } + return attr; + }; + + const handler$1 = { + get(style, name) { + if (name in prototype) + return style[name]; + updateKeys(style); + if (name === 'length') + return getKeys$1(style).length; + if (/^\d+$/.test(name)) + return getKeys$1(style)[name]; + return style.get(uhyphen(name)); + }, + + set(style, name, value) { + if (name === 'cssText') + style[name] = value; + else { + let attr = updateKeys(style); + if (value == null) + style.delete(uhyphen(name)); + else + style.set(uhyphen(name), value); + if (!attr) { + const element = refs.get(style); + attr = element.ownerDocument.createAttribute('style'); + element.setAttributeNode(attr); + style.set(PRIVATE, attr); + } + attr[CHANGED] = false; + attr[VALUE] = style.toString(); + } + return true; + } + }; + + /** + * @implements globalThis.CSSStyleDeclaration + */ + let CSSStyleDeclaration$1 = class CSSStyleDeclaration extends Map { + constructor(element) { + super(); + refs.set(this, element); + /* c8 ignore start */ + return new Proxy(this, handler$1); + /* c8 ignore stop */ + } + + get cssText() { + return this.toString(); + } + + set cssText(value) { + refs.get(this).setAttribute('style', value); + } + + getPropertyValue(name) { + const self = this[PRIVATE]; + return handler$1.get(self, name); + } + + setProperty(name, value) { + const self = this[PRIVATE]; + handler$1.set(self, name, value); + } + + removeProperty(name) { + const self = this[PRIVATE]; + handler$1.set(self, name, null); + } + + [Symbol.iterator]() { + const self = this[PRIVATE]; + updateKeys(self); + const keys = getKeys$1(self); + const {length} = keys; + let i = 0; + return { + next() { + const done = i === length; + return {done, value: done ? null : keys[i++]}; + } + }; + } + + get[PRIVATE]() { return this; } + + toString() { + const self = this[PRIVATE]; + updateKeys(self); + const cssText = []; + self.forEach(push, cssText); + return cssText.join(';'); + } + }; + + const {prototype} = CSSStyleDeclaration$1; + + function push(value, key) { + if (key !== PRIVATE) + this.push(`${key}:${value}`); + } + + // https://dom.spec.whatwg.org/#interface-event + + /* c8 ignore start */ + + // Node 15 has Event but 14 and 12 don't + const BUBBLING_PHASE = 3; + const AT_TARGET = 2; + const CAPTURING_PHASE = 1; + const NONE = 0; + + function getCurrentTarget(ev) { + return ev.currentTarget; + } + + /** + * @implements globalThis.Event + */ + class GlobalEvent { + static get BUBBLING_PHASE() { return BUBBLING_PHASE; } + static get AT_TARGET() { return AT_TARGET; } + static get CAPTURING_PHASE() { return CAPTURING_PHASE; } + static get NONE() { return NONE; } + + constructor(type, eventInitDict = {}) { + this.type = type; + this.bubbles = !!eventInitDict.bubbles; + this.cancelBubble = false; + this._stopImmediatePropagationFlag = false; + this.cancelable = !!eventInitDict.cancelable; + this.eventPhase = this.NONE; + this.timeStamp = Date.now(); + this.defaultPrevented = false; + this.originalTarget = null; + this.returnValue = null; + this.srcElement = null; + this.target = null; + this._path = []; + } + + get BUBBLING_PHASE() { return BUBBLING_PHASE; } + get AT_TARGET() { return AT_TARGET; } + get CAPTURING_PHASE() { return CAPTURING_PHASE; } + get NONE() { return NONE; } + + preventDefault() { this.defaultPrevented = true; } + + // simplified implementation, should be https://dom.spec.whatwg.org/#dom-event-composedpath + composedPath() { + return this._path.map(getCurrentTarget); + } + + stopPropagation() { + this.cancelBubble = true; + } + + stopImmediatePropagation() { + this.stopPropagation(); + this._stopImmediatePropagationFlag = true; + } + } + + /* c8 ignore stop */ + + /** + * @implements globalThis.NamedNodeMap + */ + class NamedNodeMap extends Array { + constructor(ownerElement) { + super(); + this.ownerElement = ownerElement; + } + + getNamedItem(name) { + return this.ownerElement.getAttributeNode(name); + } + + setNamedItem(attr) { + this.ownerElement.setAttributeNode(attr); + this.unshift(attr); + } + + removeNamedItem(name) { + const item = this.getNamedItem(name); + this.ownerElement.removeAttribute(name); + this.splice(this.indexOf(item), 1); + } + + item(index) { + return index < this.length ? this[index] : null; + } + + /* c8 ignore start */ + getNamedItemNS(_, name) { + return this.getNamedItem(name); + } + + setNamedItemNS(_, attr) { + return this.setNamedItem(attr); + } + + removeNamedItemNS(_, name) { + return this.removeNamedItem(name); + } + /* c8 ignore stop */ + } + + /** + * @implements globalThis.ShadowRoot + */ + let ShadowRoot$1 = class ShadowRoot extends NonElementParentNode { + constructor(host) { + super(host.ownerDocument, '#shadow-root', DOCUMENT_FRAGMENT_NODE); + this.host = host; + } + + get innerHTML() { + return getInnerHtml(this); + } + set innerHTML(html) { + setInnerHtml(this, html); + } + }; + + // https://dom.spec.whatwg.org/#interface-element + + + // <utils> + const attributesHandler = { + get(target, key) { + return key in target ? target[key] : target.find(({name}) => name === key); + } + }; + + const create = (ownerDocument, element, localName) => { + if ('ownerSVGElement' in element) { + const svg = ownerDocument.createElementNS(SVG_NAMESPACE, localName); + svg.ownerSVGElement = element.ownerSVGElement; + return svg; + } + return ownerDocument.createElement(localName); + }; + + const isVoid = ({localName, ownerDocument}) => { + return ownerDocument[MIME].voidElements.test(localName); + }; + + // </utils> + + /** + * @implements globalThis.Element + */ + let Element$2 = class Element extends ParentNode { + constructor(ownerDocument, localName) { + super(ownerDocument, localName, ELEMENT_NODE); + this[CLASS_LIST] = null; + this[DATASET] = null; + this[STYLE] = null; + } + + // <Mixins> + get isConnected() { return isConnected(this); } + get parentElement() { return parentElement(this); } + get previousSibling() { return previousSibling(this); } + get nextSibling() { return nextSibling(this); } + get namespaceURI() { + return 'http://www.w3.org/1999/xhtml'; + } + + get previousElementSibling() { return previousElementSibling(this); } + get nextElementSibling() { return nextElementSibling$1(this); } + + before(...nodes) { before(this, nodes); } + after(...nodes) { after(this, nodes); } + replaceWith(...nodes) { replaceWith(this, nodes); } + remove() { remove(this[PREV], this, this[END][NEXT]); } + // </Mixins> + + // <specialGetters> + get id() { return stringAttribute.get(this, 'id'); } + set id(value) { stringAttribute.set(this, 'id', value); } + + get className() { return this.classList.value; } + set className(value) { + const {classList} = this; + classList.clear(); + classList.add(...($String(value).split(/\s+/))); + } + + get nodeName() { return localCase(this); } + get tagName() { return localCase(this); } + + get classList() { + return this[CLASS_LIST] || ( + this[CLASS_LIST] = new DOMTokenList(this) + ); + } + + get dataset() { + return this[DATASET] || ( + this[DATASET] = new DOMStringMap(this) + ); + } + + getBoundingClientRect() { + return { + x: 0, + y: 0, + bottom: 0, + height: 0, + left: 0, + right: 0, + top: 0, + width: 0 + }; + } + + get nonce() { return stringAttribute.get(this, 'nonce'); } + set nonce(value) { stringAttribute.set(this, 'nonce', value); } + + get style() { + return this[STYLE] || ( + this[STYLE] = new CSSStyleDeclaration$1(this) + ); + } + + get tabIndex() { return numericAttribute.get(this, 'tabindex') || -1; } + set tabIndex(value) { numericAttribute.set(this, 'tabindex', value); } + + get slot() { return stringAttribute.get(this, 'slot'); } + set slot(value) { stringAttribute.set(this, 'slot', value); } + // </specialGetters> + + + // <contentRelated> + get innerText() { + const text = []; + let {[NEXT]: next, [END]: end} = this; + while (next !== end) { + if (next.nodeType === TEXT_NODE) { + text.push(next.textContent.replace(/\s+/g, ' ')); + } else if( + text.length && next[NEXT] != end && + BLOCK_ELEMENTS.has(next.tagName) + ) { + text.push('\n'); + } + next = next[NEXT]; + } + return text.join(''); + } + + /** + * @returns {String} + */ + get textContent() { + const text = []; + let {[NEXT]: next, [END]: end} = this; + while (next !== end) { + if (next.nodeType === TEXT_NODE) + text.push(next.textContent); + next = next[NEXT]; + } + return text.join(''); + } + + set textContent(text) { + this.replaceChildren(); + if (text != null && text !== '') + this.appendChild(new Text$2(this.ownerDocument, text)); + } + + get innerHTML() { + return getInnerHtml(this); + } + set innerHTML(html) { + setInnerHtml(this, html); + } + + get outerHTML() { return this.toString(); } + set outerHTML(html) { + const template = this.ownerDocument.createElement(''); + template.innerHTML = html; + this.replaceWith(...template.childNodes); + } + // </contentRelated> + + // <attributes> + get attributes() { + const attributes = new NamedNodeMap(this); + let next = this[NEXT]; + while (next.nodeType === ATTRIBUTE_NODE) { + attributes.push(next); + next = next[NEXT]; + } + return new Proxy(attributes, attributesHandler); + } + + focus() { this.dispatchEvent(new GlobalEvent('focus')); } + + getAttribute(name) { + if (name === 'class') + return this.className; + const attribute = this.getAttributeNode(name); + return attribute && (ignoreCase(this) ? attribute.value : escape$1(attribute.value)); + } + + getAttributeNode(name) { + let next = this[NEXT]; + while (next.nodeType === ATTRIBUTE_NODE) { + if (next.name === name) + return next; + next = next[NEXT]; + } + return null; + } + + getAttributeNames() { + const attributes = new NodeList; + let next = this[NEXT]; + while (next.nodeType === ATTRIBUTE_NODE) { + attributes.push(next.name); + next = next[NEXT]; + } + return attributes; + } + + hasAttribute(name) { return !!this.getAttributeNode(name); } + hasAttributes() { return this[NEXT].nodeType === ATTRIBUTE_NODE; } + + removeAttribute(name) { + if (name === 'class' && this[CLASS_LIST]) + this[CLASS_LIST].clear(); + let next = this[NEXT]; + while (next.nodeType === ATTRIBUTE_NODE) { + if (next.name === name) { + removeAttribute(this, next); + return; + } + next = next[NEXT]; + } + } + + removeAttributeNode(attribute) { + let next = this[NEXT]; + while (next.nodeType === ATTRIBUTE_NODE) { + if (next === attribute) { + removeAttribute(this, next); + return; + } + next = next[NEXT]; + } + } + + setAttribute(name, value) { + if (name === 'class') + this.className = value; + else { + const attribute = this.getAttributeNode(name); + if (attribute) + attribute.value = value; + else + setAttribute(this, new Attr$1(this.ownerDocument, name, value)); + } + } + + setAttributeNode(attribute) { + const {name} = attribute; + const previously = this.getAttributeNode(name); + if (previously !== attribute) { + if (previously) + this.removeAttributeNode(previously); + const {ownerElement} = attribute; + if (ownerElement) + ownerElement.removeAttributeNode(attribute); + setAttribute(this, attribute); + } + return previously; + } + + toggleAttribute(name, force) { + if (this.hasAttribute(name)) { + if (!force) { + this.removeAttribute(name); + return false; + } + return true; + } + else if (force || arguments.length === 1) { + this.setAttribute(name, ''); + return true; + } + return false; + } + // </attributes> + + // <ShadowDOM> + get shadowRoot() { + if (shadowRoots.has(this)) { + const {mode, shadowRoot} = shadowRoots.get(this); + if (mode === 'open') + return shadowRoot; + } + return null; + } + + attachShadow(init) { + if (shadowRoots.has(this)) + throw new Error('operation not supported'); + // TODO: shadowRoot should be likely a specialized class that extends DocumentFragment + // but until DSD is out, I am not sure I should spend time on this. + const shadowRoot = new ShadowRoot$1(this); + shadowRoots.set(this, { + mode: init.mode, + shadowRoot + }); + return shadowRoot; + } + // </ShadowDOM> + + // <selectors> + matches(selectors) { return matches(this, selectors); } + closest(selectors) { + let parentElement = this; + const matches = prepareMatch(parentElement, selectors); + while (parentElement && !matches(parentElement)) + parentElement = parentElement.parentElement; + return parentElement; + } + // </selectors> + + // <insertAdjacent> + insertAdjacentElement(position, element) { + const {parentElement} = this; + switch (position) { + case 'beforebegin': + if (parentElement) { + parentElement.insertBefore(element, this); + break; + } + return null; + case 'afterbegin': + this.insertBefore(element, this.firstChild); + break; + case 'beforeend': + this.insertBefore(element, null); + break; + case 'afterend': + if (parentElement) { + parentElement.insertBefore(element, this.nextSibling); + break; + } + return null; + } + return element; + } + + insertAdjacentHTML(position, html) { + const template = this.ownerDocument.createElement('template'); + template.innerHTML = html; + this.insertAdjacentElement(position, template.content); + } + + insertAdjacentText(position, text) { + const node = this.ownerDocument.createTextNode(text); + this.insertAdjacentElement(position, node); + } + // </insertAdjacent> + + cloneNode(deep = false) { + const {ownerDocument, localName} = this; + const addNext = next => { + next.parentNode = parentNode; + knownAdjacent($next, next); + $next = next; + }; + const clone = create(ownerDocument, this, localName); + let parentNode = clone, $next = clone; + let {[NEXT]: next, [END]: prev} = this; + while (next !== prev && (deep || next.nodeType === ATTRIBUTE_NODE)) { + switch (next.nodeType) { + case NODE_END: + knownAdjacent($next, parentNode[END]); + $next = parentNode[END]; + parentNode = parentNode.parentNode; + break; + case ELEMENT_NODE: { + const node = create(ownerDocument, next, next.localName); + addNext(node); + parentNode = node; + break; + } + case ATTRIBUTE_NODE: { + const attr = next.cloneNode(deep); + attr.ownerElement = parentNode; + addNext(attr); + break; + } + case TEXT_NODE: + case COMMENT_NODE: + case CDATA_SECTION_NODE: + addNext(next.cloneNode(deep)); + break; + } + next = next[NEXT]; + } + knownAdjacent($next, clone[END]); + return clone; + } + + // <custom> + toString() { + const out = []; + const {[END]: end} = this; + let next = {[NEXT]: this}; + let isOpened = false; + do { + next = next[NEXT]; + switch (next.nodeType) { + case ATTRIBUTE_NODE: { + const attr = ' ' + next; + switch (attr) { + case ' id': + case ' class': + case ' style': + break; + default: + out.push(attr); + } + break; + } + case NODE_END: { + const start = next[START]; + if (isOpened) { + if ('ownerSVGElement' in start) + out.push(' />'); + else if (isVoid(start)) + out.push(ignoreCase(start) ? '>' : ' />'); + else + out.push(`></${start.localName}>`); + isOpened = false; + } + else + out.push(`</${start.localName}>`); + break; + } + case ELEMENT_NODE: + if (isOpened) + out.push('>'); + if (next.toString !== this.toString) { + out.push(next.toString()); + next = next[END]; + isOpened = false; + } + else { + out.push(`<${next.localName}`); + isOpened = true; + } + break; + case TEXT_NODE: + case COMMENT_NODE: + case CDATA_SECTION_NODE: + out.push((isOpened ? '>' : '') + next); + isOpened = false; + break; + } + } while (next !== end); + return out.join(''); + } + + toJSON() { + const json = []; + elementAsJSON(this, json); + return json; + } + // </custom> + + + /* c8 ignore start */ + getAttributeNS(_, name) { return this.getAttribute(name); } + getElementsByTagNameNS(_, name) { return this.getElementsByTagName(name); } + hasAttributeNS(_, name) { return this.hasAttribute(name); } + removeAttributeNS(_, name) { this.removeAttribute(name); } + setAttributeNS(_, name, value) { this.setAttribute(name, value); } + setAttributeNodeNS(attr) { return this.setAttributeNode(attr); } + /* c8 ignore stop */ + }; + + const classNames = new WeakMap; + + const handler = { + get(target, name) { + return target[name]; + }, + set(target, name, value) { + target[name] = value; + return true; + } + }; + + /** + * @implements globalThis.SVGElement + */ + let SVGElement$1 = class SVGElement extends Element$2 { + constructor(ownerDocument, localName, ownerSVGElement = null) { + super(ownerDocument, localName); + this.ownerSVGElement = ownerSVGElement; + } + + get className() { + if (!classNames.has(this)) + classNames.set(this, new Proxy({baseVal: '', animVal: ''}, handler)); + return classNames.get(this); + } + + /* c8 ignore start */ + set className(value) { + const {classList} = this; + classList.clear(); + classList.add(...($String(value).split(/\s+/))); + } + /* c8 ignore stop */ + + get namespaceURI() { + return 'http://www.w3.org/2000/svg'; + } + + getAttribute(name) { + return name === 'class' ? + [...this.classList].join(' ') : + super.getAttribute(name); + } + + setAttribute(name, value) { + if (name === 'class') + this.className = value; + else if (name === 'style') { + const {className} = this; + className.baseVal = className.animVal = value; + } + super.setAttribute(name, value); + } + }; + + /* c8 ignore start */ + const illegalConstructor = () => { + throw new TypeError('Illegal constructor'); + }; + + function Attr() { illegalConstructor(); } + setPrototypeOf(Attr, Attr$1); + Attr.prototype = Attr$1.prototype; + + function CDATASection() { illegalConstructor(); } + setPrototypeOf(CDATASection, CDATASection$1); + CDATASection.prototype = CDATASection$1.prototype; + + function CharacterData() { illegalConstructor(); } + setPrototypeOf(CharacterData, CharacterData$1); + CharacterData.prototype = CharacterData$1.prototype; + + function Comment$6() { illegalConstructor(); } + setPrototypeOf(Comment$6, Comment$7); + Comment$6.prototype = Comment$7.prototype; + + function DocumentFragment() { illegalConstructor(); } + setPrototypeOf(DocumentFragment, DocumentFragment$1); + DocumentFragment.prototype = DocumentFragment$1.prototype; + + function DocumentType() { illegalConstructor(); } + setPrototypeOf(DocumentType, DocumentType$1); + DocumentType.prototype = DocumentType$1.prototype; + + function Element$1() { illegalConstructor(); } + setPrototypeOf(Element$1, Element$2); + Element$1.prototype = Element$2.prototype; + + function Node$6() { illegalConstructor(); } + setPrototypeOf(Node$6, Node$7); + Node$6.prototype = Node$7.prototype; + + function ShadowRoot() { illegalConstructor(); } + setPrototypeOf(ShadowRoot, ShadowRoot$1); + ShadowRoot.prototype = ShadowRoot$1.prototype; + + function Text$1() { illegalConstructor(); } + setPrototypeOf(Text$1, Text$2); + Text$1.prototype = Text$2.prototype; + + function SVGElement() { illegalConstructor(); } + setPrototypeOf(SVGElement, SVGElement$1); + SVGElement.prototype = SVGElement$1.prototype; + /* c8 ignore stop */ + + const Facades = { + Attr, + CDATASection, + CharacterData, + Comment: Comment$6, + DocumentFragment, + DocumentType, + Element: Element$1, + Node: Node$6, + ShadowRoot, + Text: Text$1, + SVGElement + }; + + const Level0 = new WeakMap; + const level0 = { + get(element, name) { + return Level0.has(element) && Level0.get(element)[name] || null; + }, + set(element, name, value) { + if (!Level0.has(element)) + Level0.set(element, {}); + const handlers = Level0.get(element); + const type = name.slice(2); + if (handlers[name]) + element.removeEventListener(type, handlers[name], false); + if ((handlers[name] = value)) + element.addEventListener(type, value, false); + } + }; + + /** + * @implements globalThis.HTMLElement + */ + class HTMLElement extends Element$2 { + + static get observedAttributes() { return []; } + + constructor(ownerDocument = null, localName = '') { + super(ownerDocument, localName); + + const ownerLess = !ownerDocument; + let options; + + if (ownerLess) { + const {constructor: Class} = this; + if (!Classes.has(Class)) + throw new Error('unable to initialize this Custom Element'); + ({ownerDocument, localName, options} = Classes.get(Class)); + } + + if (ownerDocument[UPGRADE]) { + const {element, values} = ownerDocument[UPGRADE]; + ownerDocument[UPGRADE] = null; + for (const [key, value] of values) + element[key] = value; + return element; + } + + if (ownerLess) { + this.ownerDocument = this[END].ownerDocument = ownerDocument; + this.localName = localName; + customElements.set(this, {connected: false}); + if (options.is) + this.setAttribute('is', options.is); + } + } + + /* c8 ignore start */ + + /* TODO: what about these? + offsetHeight + offsetLeft + offsetParent + offsetTop + offsetWidth + */ + + blur() { this.dispatchEvent(new GlobalEvent('blur')); } + click() { + const clickEvent = new GlobalEvent('click', {bubbles: true, cancelable: true}); + clickEvent.button = 0; + + this.dispatchEvent(clickEvent); + } + + // Boolean getters + get accessKeyLabel() { + const {accessKey} = this; + return accessKey && `Alt+Shift+${accessKey}`; + } + get isContentEditable() { return this.hasAttribute('contenteditable'); } + + // Boolean Accessors + get contentEditable() { return booleanAttribute.get(this, 'contenteditable'); } + set contentEditable(value) { booleanAttribute.set(this, 'contenteditable', value); } + get draggable() { return booleanAttribute.get(this, 'draggable'); } + set draggable(value) { booleanAttribute.set(this, 'draggable', value); } + get hidden() { return booleanAttribute.get(this, 'hidden'); } + set hidden(value) { booleanAttribute.set(this, 'hidden', value); } + get spellcheck() { return booleanAttribute.get(this, 'spellcheck'); } + set spellcheck(value) { booleanAttribute.set(this, 'spellcheck', value); } + + // String Accessors + get accessKey() { return stringAttribute.get(this, 'accesskey'); } + set accessKey(value) { stringAttribute.set(this, 'accesskey', value); } + get dir() { return stringAttribute.get(this, 'dir'); } + set dir(value) { stringAttribute.set(this, 'dir', value); } + get lang() { return stringAttribute.get(this, 'lang'); } + set lang(value) { stringAttribute.set(this, 'lang', value); } + get title() { return stringAttribute.get(this, 'title'); } + set title(value) { stringAttribute.set(this, 'title', value); } + + // DOM Level 0 + get onabort() { return level0.get(this, 'onabort'); } + set onabort(value) { level0.set(this, 'onabort', value); } + + get onblur() { return level0.get(this, 'onblur'); } + set onblur(value) { level0.set(this, 'onblur', value); } + + get oncancel() { return level0.get(this, 'oncancel'); } + set oncancel(value) { level0.set(this, 'oncancel', value); } + + get oncanplay() { return level0.get(this, 'oncanplay'); } + set oncanplay(value) { level0.set(this, 'oncanplay', value); } + + get oncanplaythrough() { return level0.get(this, 'oncanplaythrough'); } + set oncanplaythrough(value) { level0.set(this, 'oncanplaythrough', value); } + + get onchange() { return level0.get(this, 'onchange'); } + set onchange(value) { level0.set(this, 'onchange', value); } + + get onclick() { return level0.get(this, 'onclick'); } + set onclick(value) { level0.set(this, 'onclick', value); } + + get onclose() { return level0.get(this, 'onclose'); } + set onclose(value) { level0.set(this, 'onclose', value); } + + get oncontextmenu() { return level0.get(this, 'oncontextmenu'); } + set oncontextmenu(value) { level0.set(this, 'oncontextmenu', value); } + + get oncuechange() { return level0.get(this, 'oncuechange'); } + set oncuechange(value) { level0.set(this, 'oncuechange', value); } + + get ondblclick() { return level0.get(this, 'ondblclick'); } + set ondblclick(value) { level0.set(this, 'ondblclick', value); } + + get ondrag() { return level0.get(this, 'ondrag'); } + set ondrag(value) { level0.set(this, 'ondrag', value); } + + get ondragend() { return level0.get(this, 'ondragend'); } + set ondragend(value) { level0.set(this, 'ondragend', value); } + + get ondragenter() { return level0.get(this, 'ondragenter'); } + set ondragenter(value) { level0.set(this, 'ondragenter', value); } + + get ondragleave() { return level0.get(this, 'ondragleave'); } + set ondragleave(value) { level0.set(this, 'ondragleave', value); } + + get ondragover() { return level0.get(this, 'ondragover'); } + set ondragover(value) { level0.set(this, 'ondragover', value); } + + get ondragstart() { return level0.get(this, 'ondragstart'); } + set ondragstart(value) { level0.set(this, 'ondragstart', value); } + + get ondrop() { return level0.get(this, 'ondrop'); } + set ondrop(value) { level0.set(this, 'ondrop', value); } + + get ondurationchange() { return level0.get(this, 'ondurationchange'); } + set ondurationchange(value) { level0.set(this, 'ondurationchange', value); } + + get onemptied() { return level0.get(this, 'onemptied'); } + set onemptied(value) { level0.set(this, 'onemptied', value); } + + get onended() { return level0.get(this, 'onended'); } + set onended(value) { level0.set(this, 'onended', value); } + + get onerror() { return level0.get(this, 'onerror'); } + set onerror(value) { level0.set(this, 'onerror', value); } + + get onfocus() { return level0.get(this, 'onfocus'); } + set onfocus(value) { level0.set(this, 'onfocus', value); } + + get oninput() { return level0.get(this, 'oninput'); } + set oninput(value) { level0.set(this, 'oninput', value); } + + get oninvalid() { return level0.get(this, 'oninvalid'); } + set oninvalid(value) { level0.set(this, 'oninvalid', value); } + + get onkeydown() { return level0.get(this, 'onkeydown'); } + set onkeydown(value) { level0.set(this, 'onkeydown', value); } + + get onkeypress() { return level0.get(this, 'onkeypress'); } + set onkeypress(value) { level0.set(this, 'onkeypress', value); } + + get onkeyup() { return level0.get(this, 'onkeyup'); } + set onkeyup(value) { level0.set(this, 'onkeyup', value); } + + get onload() { return level0.get(this, 'onload'); } + set onload(value) { level0.set(this, 'onload', value); } + + get onloadeddata() { return level0.get(this, 'onloadeddata'); } + set onloadeddata(value) { level0.set(this, 'onloadeddata', value); } + + get onloadedmetadata() { return level0.get(this, 'onloadedmetadata'); } + set onloadedmetadata(value) { level0.set(this, 'onloadedmetadata', value); } + + get onloadstart() { return level0.get(this, 'onloadstart'); } + set onloadstart(value) { level0.set(this, 'onloadstart', value); } + + get onmousedown() { return level0.get(this, 'onmousedown'); } + set onmousedown(value) { level0.set(this, 'onmousedown', value); } + + get onmouseenter() { return level0.get(this, 'onmouseenter'); } + set onmouseenter(value) { level0.set(this, 'onmouseenter', value); } + + get onmouseleave() { return level0.get(this, 'onmouseleave'); } + set onmouseleave(value) { level0.set(this, 'onmouseleave', value); } + + get onmousemove() { return level0.get(this, 'onmousemove'); } + set onmousemove(value) { level0.set(this, 'onmousemove', value); } + + get onmouseout() { return level0.get(this, 'onmouseout'); } + set onmouseout(value) { level0.set(this, 'onmouseout', value); } + + get onmouseover() { return level0.get(this, 'onmouseover'); } + set onmouseover(value) { level0.set(this, 'onmouseover', value); } + + get onmouseup() { return level0.get(this, 'onmouseup'); } + set onmouseup(value) { level0.set(this, 'onmouseup', value); } + + get onmousewheel() { return level0.get(this, 'onmousewheel'); } + set onmousewheel(value) { level0.set(this, 'onmousewheel', value); } + + get onpause() { return level0.get(this, 'onpause'); } + set onpause(value) { level0.set(this, 'onpause', value); } + + get onplay() { return level0.get(this, 'onplay'); } + set onplay(value) { level0.set(this, 'onplay', value); } + + get onplaying() { return level0.get(this, 'onplaying'); } + set onplaying(value) { level0.set(this, 'onplaying', value); } + + get onprogress() { return level0.get(this, 'onprogress'); } + set onprogress(value) { level0.set(this, 'onprogress', value); } + + get onratechange() { return level0.get(this, 'onratechange'); } + set onratechange(value) { level0.set(this, 'onratechange', value); } + + get onreset() { return level0.get(this, 'onreset'); } + set onreset(value) { level0.set(this, 'onreset', value); } + + get onresize() { return level0.get(this, 'onresize'); } + set onresize(value) { level0.set(this, 'onresize', value); } + + get onscroll() { return level0.get(this, 'onscroll'); } + set onscroll(value) { level0.set(this, 'onscroll', value); } + + get onseeked() { return level0.get(this, 'onseeked'); } + set onseeked(value) { level0.set(this, 'onseeked', value); } + + get onseeking() { return level0.get(this, 'onseeking'); } + set onseeking(value) { level0.set(this, 'onseeking', value); } + + get onselect() { return level0.get(this, 'onselect'); } + set onselect(value) { level0.set(this, 'onselect', value); } + + get onshow() { return level0.get(this, 'onshow'); } + set onshow(value) { level0.set(this, 'onshow', value); } + + get onstalled() { return level0.get(this, 'onstalled'); } + set onstalled(value) { level0.set(this, 'onstalled', value); } + + get onsubmit() { return level0.get(this, 'onsubmit'); } + set onsubmit(value) { level0.set(this, 'onsubmit', value); } + + get onsuspend() { return level0.get(this, 'onsuspend'); } + set onsuspend(value) { level0.set(this, 'onsuspend', value); } + + get ontimeupdate() { return level0.get(this, 'ontimeupdate'); } + set ontimeupdate(value) { level0.set(this, 'ontimeupdate', value); } + + get ontoggle() { return level0.get(this, 'ontoggle'); } + set ontoggle(value) { level0.set(this, 'ontoggle', value); } + + get onvolumechange() { return level0.get(this, 'onvolumechange'); } + set onvolumechange(value) { level0.set(this, 'onvolumechange', value); } + + get onwaiting() { return level0.get(this, 'onwaiting'); } + set onwaiting(value) { level0.set(this, 'onwaiting', value); } + + get onauxclick() { return level0.get(this, 'onauxclick'); } + set onauxclick(value) { level0.set(this, 'onauxclick', value); } + + get ongotpointercapture() { return level0.get(this, 'ongotpointercapture'); } + set ongotpointercapture(value) { level0.set(this, 'ongotpointercapture', value); } + + get onlostpointercapture() { return level0.get(this, 'onlostpointercapture'); } + set onlostpointercapture(value) { level0.set(this, 'onlostpointercapture', value); } + + get onpointercancel() { return level0.get(this, 'onpointercancel'); } + set onpointercancel(value) { level0.set(this, 'onpointercancel', value); } + + get onpointerdown() { return level0.get(this, 'onpointerdown'); } + set onpointerdown(value) { level0.set(this, 'onpointerdown', value); } + + get onpointerenter() { return level0.get(this, 'onpointerenter'); } + set onpointerenter(value) { level0.set(this, 'onpointerenter', value); } + + get onpointerleave() { return level0.get(this, 'onpointerleave'); } + set onpointerleave(value) { level0.set(this, 'onpointerleave', value); } + + get onpointermove() { return level0.get(this, 'onpointermove'); } + set onpointermove(value) { level0.set(this, 'onpointermove', value); } + + get onpointerout() { return level0.get(this, 'onpointerout'); } + set onpointerout(value) { level0.set(this, 'onpointerout', value); } + + get onpointerover() { return level0.get(this, 'onpointerover'); } + set onpointerover(value) { level0.set(this, 'onpointerover', value); } + + get onpointerup() { return level0.get(this, 'onpointerup'); } + set onpointerup(value) { level0.set(this, 'onpointerup', value); } + /* c8 ignore stop */ + + } + + const tagName$h = 'template'; + + /** + * @implements globalThis.HTMLTemplateElement + */ + class HTMLTemplateElement extends HTMLElement { + constructor(ownerDocument) { + super(ownerDocument, tagName$h); + const content = this.ownerDocument.createDocumentFragment(); + (this[CONTENT] = content)[PRIVATE] = this; + } + + get content() { + if (this.hasChildNodes() && !this[CONTENT].hasChildNodes()) { + for (const node of this.childNodes) + this[CONTENT].appendChild(node.cloneNode(true)); + } + return this[CONTENT]; + } + } + + registerHTMLClass(tagName$h, HTMLTemplateElement); + + /** + * @implements globalThis.HTMLHtmlElement + */ + class HTMLHtmlElement extends HTMLElement { + constructor(ownerDocument, localName = 'html') { + super(ownerDocument, localName); + } + } + + const {toString: toString$1} = HTMLElement.prototype; + + class TextElement extends HTMLElement { + + get innerHTML() { return this.textContent; } + set innerHTML(html) { this.textContent = html; } + + toString() { + const outerHTML = toString$1.call(this.cloneNode()); + return outerHTML.replace(/></, `>${this.textContent}<`); + } + } + + const tagName$g = 'script'; + + /** + * @implements globalThis.HTMLScriptElement + */ + class HTMLScriptElement extends TextElement { + constructor(ownerDocument, localName = tagName$g) { + super(ownerDocument, localName); + } + + get type() { + return stringAttribute.get(this, 'type'); + } + set type(value) { + stringAttribute.set(this, 'type', value); + } + + get src() { + return stringAttribute.get(this, 'src'); + } + set src(value) { + stringAttribute.set(this, 'src', value); + } + + get defer() { + return booleanAttribute.get(this, 'defer'); + } + + set defer(value) { + booleanAttribute.set(this, 'defer', value); + } + + get crossOrigin() { + return stringAttribute.get(this, 'crossorigin'); + } + set crossOrigin(value) { + stringAttribute.set(this, 'crossorigin', value); + } + + get nomodule() { + return booleanAttribute.get(this, 'nomodule'); + } + set nomodule(value) { + booleanAttribute.set(this, 'nomodule', value); + } + + get referrerPolicy() { + return stringAttribute.get(this, 'referrerpolicy'); + } + set referrerPolicy(value) { + stringAttribute.set(this, 'referrerpolicy', value); + } + + get nonce() { + return stringAttribute.get(this, 'nonce'); + } + set nonce(value) { + stringAttribute.set(this, 'nonce', value); + } + + get async() { + return booleanAttribute.get(this, 'async'); + } + set async(value) { + booleanAttribute.set(this, 'async', value); + } + + get text() { return this.textContent; } + set text(content) { this.textContent = content; } + } + + registerHTMLClass(tagName$g, HTMLScriptElement); + + /** + * @implements globalThis.HTMLFrameElement + */ + class HTMLFrameElement extends HTMLElement { + constructor(ownerDocument, localName = 'frame') { + super(ownerDocument, localName); + } + } + + const tagName$f = 'iframe'; + + /** + * @implements globalThis.HTMLIFrameElement + */ + class HTMLIFrameElement extends HTMLElement { + constructor(ownerDocument, localName = tagName$f) { + super(ownerDocument, localName); + } + + /* c8 ignore start */ + get src() { return stringAttribute.get(this, 'src'); } + set src(value) { stringAttribute.set(this, 'src', value); } + + get srcdoc() { return stringAttribute.get(this, "srcdoc"); } + set srcdoc(value) { stringAttribute.set(this, "srcdoc", value); } + + get name() { return stringAttribute.get(this, "name"); } + set name(value) { stringAttribute.set(this, "name", value); } + + get allow() { return stringAttribute.get(this, "allow"); } + set allow(value) { stringAttribute.set(this, "allow", value); } + + get allowFullscreen() { return booleanAttribute.get(this, "allowfullscreen"); } + set allowFullscreen(value) { booleanAttribute.set(this, "allowfullscreen", value); } + + get referrerPolicy() { return stringAttribute.get(this, "referrerpolicy"); } + set referrerPolicy(value) { stringAttribute.set(this, "referrerpolicy", value); } + + get loading() { return stringAttribute.get(this, "loading"); } + set loading(value) { stringAttribute.set(this, "loading", value); } + /* c8 ignore stop */ + } + + registerHTMLClass(tagName$f, HTMLIFrameElement); + + /** + * @implements globalThis.HTMLObjectElement + */ + class HTMLObjectElement extends HTMLElement { + constructor(ownerDocument, localName = 'object') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLHeadElement + */ + class HTMLHeadElement extends HTMLElement { + constructor(ownerDocument, localName = 'head') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLBodyElement + */ + class HTMLBodyElement extends HTMLElement { + constructor(ownerDocument, localName = 'body') { + super(ownerDocument, localName); + } + } + + var CSSStyleDeclaration = {}; + + var parse$8 = {}; + + var CSSStyleSheet = {}; + + var StyleSheet = {}; + + //.CommonJS + var CSSOM$c = {}; + ///CommonJS + + + /** + * @constructor + * @see http://dev.w3.org/csswg/cssom/#the-stylesheet-interface + */ + CSSOM$c.StyleSheet = function StyleSheet() { + this.parentStyleSheet = null; + }; + + + //.CommonJS + StyleSheet.StyleSheet = CSSOM$c.StyleSheet; + + var CSSStyleRule = {}; + + var CSSRule = {}; + + //.CommonJS + var CSSOM$b = {}; + ///CommonJS + + + /** + * @constructor + * @see http://dev.w3.org/csswg/cssom/#the-cssrule-interface + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSRule + */ + CSSOM$b.CSSRule = function CSSRule() { + this.parentRule = null; + this.parentStyleSheet = null; + }; + + CSSOM$b.CSSRule.UNKNOWN_RULE = 0; // obsolete + CSSOM$b.CSSRule.STYLE_RULE = 1; + CSSOM$b.CSSRule.CHARSET_RULE = 2; // obsolete + CSSOM$b.CSSRule.IMPORT_RULE = 3; + CSSOM$b.CSSRule.MEDIA_RULE = 4; + CSSOM$b.CSSRule.FONT_FACE_RULE = 5; + CSSOM$b.CSSRule.PAGE_RULE = 6; + CSSOM$b.CSSRule.KEYFRAMES_RULE = 7; + CSSOM$b.CSSRule.KEYFRAME_RULE = 8; + CSSOM$b.CSSRule.MARGIN_RULE = 9; + CSSOM$b.CSSRule.NAMESPACE_RULE = 10; + CSSOM$b.CSSRule.COUNTER_STYLE_RULE = 11; + CSSOM$b.CSSRule.SUPPORTS_RULE = 12; + CSSOM$b.CSSRule.DOCUMENT_RULE = 13; + CSSOM$b.CSSRule.FONT_FEATURE_VALUES_RULE = 14; + CSSOM$b.CSSRule.VIEWPORT_RULE = 15; + CSSOM$b.CSSRule.REGION_STYLE_RULE = 16; + + + CSSOM$b.CSSRule.prototype = { + constructor: CSSOM$b.CSSRule + //FIXME + }; + + + //.CommonJS + CSSRule.CSSRule = CSSOM$b.CSSRule; + + var hasRequiredCSSStyleRule; + + function requireCSSStyleRule () { + if (hasRequiredCSSStyleRule) return CSSStyleRule; + hasRequiredCSSStyleRule = 1; + //.CommonJS + var CSSOM = { + CSSStyleDeclaration: requireCSSStyleDeclaration().CSSStyleDeclaration, + CSSRule: CSSRule.CSSRule + }; + ///CommonJS + + + /** + * @constructor + * @see http://dev.w3.org/csswg/cssom/#cssstylerule + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleRule + */ + CSSOM.CSSStyleRule = function CSSStyleRule() { + CSSOM.CSSRule.call(this); + this.selectorText = ""; + this.style = new CSSOM.CSSStyleDeclaration(); + this.style.parentRule = this; + }; + + CSSOM.CSSStyleRule.prototype = new CSSOM.CSSRule(); + CSSOM.CSSStyleRule.prototype.constructor = CSSOM.CSSStyleRule; + CSSOM.CSSStyleRule.prototype.type = 1; + + Object.defineProperty(CSSOM.CSSStyleRule.prototype, "cssText", { + get: function() { + var text; + if (this.selectorText) { + text = this.selectorText + " {" + this.style.cssText + "}"; + } else { + text = ""; + } + return text; + }, + set: function(cssText) { + var rule = CSSOM.CSSStyleRule.parse(cssText); + this.style = rule.style; + this.selectorText = rule.selectorText; + } + }); + + + /** + * NON-STANDARD + * lightweight version of parse.js. + * @param {string} ruleText + * @return CSSStyleRule + */ + CSSOM.CSSStyleRule.parse = function(ruleText) { + var i = 0; + var state = "selector"; + var index; + var j = i; + var buffer = ""; + + var SIGNIFICANT_WHITESPACE = { + "selector": true, + "value": true + }; + + var styleRule = new CSSOM.CSSStyleRule(); + var name, priority=""; + + for (var character; (character = ruleText.charAt(i)); i++) { + + switch (character) { + + case " ": + case "\t": + case "\r": + case "\n": + case "\f": + if (SIGNIFICANT_WHITESPACE[state]) { + // Squash 2 or more white-spaces in the row into 1 + switch (ruleText.charAt(i - 1)) { + case " ": + case "\t": + case "\r": + case "\n": + case "\f": + break; + default: + buffer += " "; + break; + } + } + break; + + // String + case '"': + j = i + 1; + index = ruleText.indexOf('"', j) + 1; + if (!index) { + throw '" is missing'; + } + buffer += ruleText.slice(i, index); + i = index - 1; + break; + + case "'": + j = i + 1; + index = ruleText.indexOf("'", j) + 1; + if (!index) { + throw "' is missing"; + } + buffer += ruleText.slice(i, index); + i = index - 1; + break; + + // Comment + case "/": + if (ruleText.charAt(i + 1) === "*") { + i += 2; + index = ruleText.indexOf("*/", i); + if (index === -1) { + throw new SyntaxError("Missing */"); + } else { + i = index + 1; + } + } else { + buffer += character; + } + break; + + case "{": + if (state === "selector") { + styleRule.selectorText = buffer.trim(); + buffer = ""; + state = "name"; + } + break; + + case ":": + if (state === "name") { + name = buffer.trim(); + buffer = ""; + state = "value"; + } else { + buffer += character; + } + break; + + case "!": + if (state === "value" && ruleText.indexOf("!important", i) === i) { + priority = "important"; + i += "important".length; + } else { + buffer += character; + } + break; + + case ";": + if (state === "value") { + styleRule.style.setProperty(name, buffer.trim(), priority); + priority = ""; + buffer = ""; + state = "name"; + } else { + buffer += character; + } + break; + + case "}": + if (state === "value") { + styleRule.style.setProperty(name, buffer.trim(), priority); + priority = ""; + buffer = ""; + } else if (state === "name") { + break; + } else { + buffer += character; + } + state = "selector"; + break; + + default: + buffer += character; + break; + + } + } + + return styleRule; + + }; + + + //.CommonJS + CSSStyleRule.CSSStyleRule = CSSOM.CSSStyleRule; + ///CommonJS + return CSSStyleRule; + } + + var hasRequiredCSSStyleSheet; + + function requireCSSStyleSheet () { + if (hasRequiredCSSStyleSheet) return CSSStyleSheet; + hasRequiredCSSStyleSheet = 1; + //.CommonJS + var CSSOM = { + StyleSheet: StyleSheet.StyleSheet, + CSSStyleRule: requireCSSStyleRule().CSSStyleRule + }; + ///CommonJS + + + /** + * @constructor + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet + */ + CSSOM.CSSStyleSheet = function CSSStyleSheet() { + CSSOM.StyleSheet.call(this); + this.cssRules = []; + }; + + + CSSOM.CSSStyleSheet.prototype = new CSSOM.StyleSheet(); + CSSOM.CSSStyleSheet.prototype.constructor = CSSOM.CSSStyleSheet; + + + /** + * Used to insert a new rule into the style sheet. The new rule now becomes part of the cascade. + * + * sheet = new Sheet("body {margin: 0}") + * sheet.toString() + * -> "body{margin:0;}" + * sheet.insertRule("img {border: none}", 0) + * -> 0 + * sheet.toString() + * -> "img{border:none;}body{margin:0;}" + * + * @param {string} rule + * @param {number} index + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-insertRule + * @return {number} The index within the style sheet's rule collection of the newly inserted rule. + */ + CSSOM.CSSStyleSheet.prototype.insertRule = function(rule, index) { + if (index < 0 || index > this.cssRules.length) { + throw new RangeError("INDEX_SIZE_ERR"); + } + var cssRule = CSSOM.parse(rule).cssRules[0]; + cssRule.parentStyleSheet = this; + this.cssRules.splice(index, 0, cssRule); + return index; + }; + + + /** + * Used to delete a rule from the style sheet. + * + * sheet = new Sheet("img{border:none} body{margin:0}") + * sheet.toString() + * -> "img{border:none;}body{margin:0;}" + * sheet.deleteRule(0) + * sheet.toString() + * -> "body{margin:0;}" + * + * @param {number} index within the style sheet's rule list of the rule to remove. + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-deleteRule + */ + CSSOM.CSSStyleSheet.prototype.deleteRule = function(index) { + if (index < 0 || index >= this.cssRules.length) { + throw new RangeError("INDEX_SIZE_ERR"); + } + this.cssRules.splice(index, 1); + }; + + + /** + * NON-STANDARD + * @return {string} serialize stylesheet + */ + CSSOM.CSSStyleSheet.prototype.toString = function() { + var result = ""; + var rules = this.cssRules; + for (var i=0; i<rules.length; i++) { + result += rules[i].cssText + "\n"; + } + return result; + }; + + + //.CommonJS + CSSStyleSheet.CSSStyleSheet = CSSOM.CSSStyleSheet; + CSSOM.parse = requireParse().parse; // Cannot be included sooner due to the mutual dependency between parse.js and CSSStyleSheet.js + ///CommonJS + return CSSStyleSheet; + } + + var CSSImportRule = {}; + + var MediaList = {}; + + //.CommonJS + var CSSOM$a = {}; + ///CommonJS + + + /** + * @constructor + * @see http://dev.w3.org/csswg/cssom/#the-medialist-interface + */ + CSSOM$a.MediaList = function MediaList(){ + this.length = 0; + }; + + CSSOM$a.MediaList.prototype = { + + constructor: CSSOM$a.MediaList, + + /** + * @return {string} + */ + get mediaText() { + return Array.prototype.join.call(this, ", "); + }, + + /** + * @param {string} value + */ + set mediaText(value) { + var values = value.split(","); + var length = this.length = values.length; + for (var i=0; i<length; i++) { + this[i] = values[i].trim(); + } + }, + + /** + * @param {string} medium + */ + appendMedium: function(medium) { + if (Array.prototype.indexOf.call(this, medium) === -1) { + this[this.length] = medium; + this.length++; + } + }, + + /** + * @param {string} medium + */ + deleteMedium: function(medium) { + var index = Array.prototype.indexOf.call(this, medium); + if (index !== -1) { + Array.prototype.splice.call(this, index, 1); + } + } + + }; + + + //.CommonJS + MediaList.MediaList = CSSOM$a.MediaList; + + var hasRequiredCSSImportRule; + + function requireCSSImportRule () { + if (hasRequiredCSSImportRule) return CSSImportRule; + hasRequiredCSSImportRule = 1; + //.CommonJS + var CSSOM = { + CSSRule: CSSRule.CSSRule, + CSSStyleSheet: requireCSSStyleSheet().CSSStyleSheet, + MediaList: MediaList.MediaList + }; + ///CommonJS + + + /** + * @constructor + * @see http://dev.w3.org/csswg/cssom/#cssimportrule + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSImportRule + */ + CSSOM.CSSImportRule = function CSSImportRule() { + CSSOM.CSSRule.call(this); + this.href = ""; + this.media = new CSSOM.MediaList(); + this.styleSheet = new CSSOM.CSSStyleSheet(); + }; + + CSSOM.CSSImportRule.prototype = new CSSOM.CSSRule(); + CSSOM.CSSImportRule.prototype.constructor = CSSOM.CSSImportRule; + CSSOM.CSSImportRule.prototype.type = 3; + + Object.defineProperty(CSSOM.CSSImportRule.prototype, "cssText", { + get: function() { + var mediaText = this.media.mediaText; + return "@import url(" + this.href + ")" + (mediaText ? " " + mediaText : "") + ";"; + }, + set: function(cssText) { + var i = 0; + + /** + * @import url(partial.css) screen, handheld; + * || | + * after-import media + * | + * url + */ + var state = ''; + + var buffer = ''; + var index; + for (var character; (character = cssText.charAt(i)); i++) { + + switch (character) { + case ' ': + case '\t': + case '\r': + case '\n': + case '\f': + if (state === 'after-import') { + state = 'url'; + } else { + buffer += character; + } + break; + + case '@': + if (!state && cssText.indexOf('@import', i) === i) { + state = 'after-import'; + i += 'import'.length; + buffer = ''; + } + break; + + case 'u': + if (state === 'url' && cssText.indexOf('url(', i) === i) { + index = cssText.indexOf(')', i + 1); + if (index === -1) { + throw i + ': ")" not found'; + } + i += 'url('.length; + var url = cssText.slice(i, index); + if (url[0] === url[url.length - 1]) { + if (url[0] === '"' || url[0] === "'") { + url = url.slice(1, -1); + } + } + this.href = url; + i = index; + state = 'media'; + } + break; + + case '"': + if (state === 'url') { + index = cssText.indexOf('"', i + 1); + if (!index) { + throw i + ": '\"' not found"; + } + this.href = cssText.slice(i + 1, index); + i = index; + state = 'media'; + } + break; + + case "'": + if (state === 'url') { + index = cssText.indexOf("'", i + 1); + if (!index) { + throw i + ': "\'" not found'; + } + this.href = cssText.slice(i + 1, index); + i = index; + state = 'media'; + } + break; + + case ';': + if (state === 'media') { + if (buffer) { + this.media.mediaText = buffer.trim(); + } + } + break; + + default: + if (state === 'media') { + buffer += character; + } + break; + } + } + } + }); + + + //.CommonJS + CSSImportRule.CSSImportRule = CSSOM.CSSImportRule; + ///CommonJS + return CSSImportRule; + } + + var CSSGroupingRule = {}; + + //.CommonJS + var CSSOM$9 = { + CSSRule: CSSRule.CSSRule + }; + ///CommonJS + + + /** + * @constructor + * @see https://drafts.csswg.org/cssom/#the-cssgroupingrule-interface + */ + CSSOM$9.CSSGroupingRule = function CSSGroupingRule() { + CSSOM$9.CSSRule.call(this); + this.cssRules = []; + }; + + CSSOM$9.CSSGroupingRule.prototype = new CSSOM$9.CSSRule(); + CSSOM$9.CSSGroupingRule.prototype.constructor = CSSOM$9.CSSGroupingRule; + + + /** + * Used to insert a new CSS rule to a list of CSS rules. + * + * @example + * cssGroupingRule.cssText + * -> "body{margin:0;}" + * cssGroupingRule.insertRule("img{border:none;}", 1) + * -> 1 + * cssGroupingRule.cssText + * -> "body{margin:0;}img{border:none;}" + * + * @param {string} rule + * @param {number} [index] + * @see https://www.w3.org/TR/cssom-1/#dom-cssgroupingrule-insertrule + * @return {number} The index within the grouping rule's collection of the newly inserted rule. + */ + CSSOM$9.CSSGroupingRule.prototype.insertRule = function insertRule(rule, index) { + if (index < 0 || index > this.cssRules.length) { + throw new RangeError("INDEX_SIZE_ERR"); + } + var cssRule = CSSOM$9.parse(rule).cssRules[0]; + cssRule.parentRule = this; + this.cssRules.splice(index, 0, cssRule); + return index; + }; + + /** + * Used to delete a rule from the grouping rule. + * + * cssGroupingRule.cssText + * -> "img{border:none;}body{margin:0;}" + * cssGroupingRule.deleteRule(0) + * cssGroupingRule.cssText + * -> "body{margin:0;}" + * + * @param {number} index within the grouping rule's rule list of the rule to remove. + * @see https://www.w3.org/TR/cssom-1/#dom-cssgroupingrule-deleterule + */ + CSSOM$9.CSSGroupingRule.prototype.deleteRule = function deleteRule(index) { + if (index < 0 || index >= this.cssRules.length) { + throw new RangeError("INDEX_SIZE_ERR"); + } + this.cssRules.splice(index, 1)[0].parentRule = null; + }; + + //.CommonJS + CSSGroupingRule.CSSGroupingRule = CSSOM$9.CSSGroupingRule; + + var CSSMediaRule = {}; + + var CSSConditionRule = {}; + + //.CommonJS + var CSSOM$8 = { + CSSRule: CSSRule.CSSRule, + CSSGroupingRule: CSSGroupingRule.CSSGroupingRule + }; + ///CommonJS + + + /** + * @constructor + * @see https://www.w3.org/TR/css-conditional-3/#the-cssconditionrule-interface + */ + CSSOM$8.CSSConditionRule = function CSSConditionRule() { + CSSOM$8.CSSGroupingRule.call(this); + this.cssRules = []; + }; + + CSSOM$8.CSSConditionRule.prototype = new CSSOM$8.CSSGroupingRule(); + CSSOM$8.CSSConditionRule.prototype.constructor = CSSOM$8.CSSConditionRule; + CSSOM$8.CSSConditionRule.prototype.conditionText = ''; + CSSOM$8.CSSConditionRule.prototype.cssText = ''; + + //.CommonJS + CSSConditionRule.CSSConditionRule = CSSOM$8.CSSConditionRule; + + //.CommonJS + var CSSOM$7 = { + CSSRule: CSSRule.CSSRule, + CSSGroupingRule: CSSGroupingRule.CSSGroupingRule, + CSSConditionRule: CSSConditionRule.CSSConditionRule, + MediaList: MediaList.MediaList + }; + ///CommonJS + + + /** + * @constructor + * @see http://dev.w3.org/csswg/cssom/#cssmediarule + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSMediaRule + */ + CSSOM$7.CSSMediaRule = function CSSMediaRule() { + CSSOM$7.CSSConditionRule.call(this); + this.media = new CSSOM$7.MediaList(); + }; + + CSSOM$7.CSSMediaRule.prototype = new CSSOM$7.CSSConditionRule(); + CSSOM$7.CSSMediaRule.prototype.constructor = CSSOM$7.CSSMediaRule; + CSSOM$7.CSSMediaRule.prototype.type = 4; + + // https://opensource.apple.com/source/WebCore/WebCore-7611.1.21.161.3/css/CSSMediaRule.cpp + Object.defineProperties(CSSOM$7.CSSMediaRule.prototype, { + "conditionText": { + get: function() { + return this.media.mediaText; + }, + set: function(value) { + this.media.mediaText = value; + }, + configurable: true, + enumerable: true + }, + "cssText": { + get: function() { + var cssTexts = []; + for (var i=0, length=this.cssRules.length; i < length; i++) { + cssTexts.push(this.cssRules[i].cssText); + } + return "@media " + this.media.mediaText + " {" + cssTexts.join("") + "}"; + }, + configurable: true, + enumerable: true + } + }); + + + //.CommonJS + CSSMediaRule.CSSMediaRule = CSSOM$7.CSSMediaRule; + + var CSSSupportsRule = {}; + + //.CommonJS + var CSSOM$6 = { + CSSRule: CSSRule.CSSRule, + CSSGroupingRule: CSSGroupingRule.CSSGroupingRule, + CSSConditionRule: CSSConditionRule.CSSConditionRule + }; + ///CommonJS + + + /** + * @constructor + * @see https://drafts.csswg.org/css-conditional-3/#the-csssupportsrule-interface + */ + CSSOM$6.CSSSupportsRule = function CSSSupportsRule() { + CSSOM$6.CSSConditionRule.call(this); + }; + + CSSOM$6.CSSSupportsRule.prototype = new CSSOM$6.CSSConditionRule(); + CSSOM$6.CSSSupportsRule.prototype.constructor = CSSOM$6.CSSSupportsRule; + CSSOM$6.CSSSupportsRule.prototype.type = 12; + + Object.defineProperty(CSSOM$6.CSSSupportsRule.prototype, "cssText", { + get: function() { + var cssTexts = []; + + for (var i = 0, length = this.cssRules.length; i < length; i++) { + cssTexts.push(this.cssRules[i].cssText); + } + + return "@supports " + this.conditionText + " {" + cssTexts.join("") + "}"; + } + }); + + //.CommonJS + CSSSupportsRule.CSSSupportsRule = CSSOM$6.CSSSupportsRule; + + var CSSFontFaceRule = {}; + + var hasRequiredCSSFontFaceRule; + + function requireCSSFontFaceRule () { + if (hasRequiredCSSFontFaceRule) return CSSFontFaceRule; + hasRequiredCSSFontFaceRule = 1; + //.CommonJS + var CSSOM = { + CSSStyleDeclaration: requireCSSStyleDeclaration().CSSStyleDeclaration, + CSSRule: CSSRule.CSSRule + }; + ///CommonJS + + + /** + * @constructor + * @see http://dev.w3.org/csswg/cssom/#css-font-face-rule + */ + CSSOM.CSSFontFaceRule = function CSSFontFaceRule() { + CSSOM.CSSRule.call(this); + this.style = new CSSOM.CSSStyleDeclaration(); + this.style.parentRule = this; + }; + + CSSOM.CSSFontFaceRule.prototype = new CSSOM.CSSRule(); + CSSOM.CSSFontFaceRule.prototype.constructor = CSSOM.CSSFontFaceRule; + CSSOM.CSSFontFaceRule.prototype.type = 5; + //FIXME + //CSSOM.CSSFontFaceRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule; + //CSSOM.CSSFontFaceRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule; + + // http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSFontFaceRule.cpp + Object.defineProperty(CSSOM.CSSFontFaceRule.prototype, "cssText", { + get: function() { + return "@font-face {" + this.style.cssText + "}"; + } + }); + + + //.CommonJS + CSSFontFaceRule.CSSFontFaceRule = CSSOM.CSSFontFaceRule; + ///CommonJS + return CSSFontFaceRule; + } + + var CSSHostRule = {}; + + //.CommonJS + var CSSOM$5 = { + CSSRule: CSSRule.CSSRule + }; + ///CommonJS + + + /** + * @constructor + * @see http://www.w3.org/TR/shadow-dom/#host-at-rule + */ + CSSOM$5.CSSHostRule = function CSSHostRule() { + CSSOM$5.CSSRule.call(this); + this.cssRules = []; + }; + + CSSOM$5.CSSHostRule.prototype = new CSSOM$5.CSSRule(); + CSSOM$5.CSSHostRule.prototype.constructor = CSSOM$5.CSSHostRule; + CSSOM$5.CSSHostRule.prototype.type = 1001; + //FIXME + //CSSOM.CSSHostRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule; + //CSSOM.CSSHostRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule; + + Object.defineProperty(CSSOM$5.CSSHostRule.prototype, "cssText", { + get: function() { + var cssTexts = []; + for (var i=0, length=this.cssRules.length; i < length; i++) { + cssTexts.push(this.cssRules[i].cssText); + } + return "@host {" + cssTexts.join("") + "}"; + } + }); + + + //.CommonJS + CSSHostRule.CSSHostRule = CSSOM$5.CSSHostRule; + + var CSSKeyframeRule = {}; + + var hasRequiredCSSKeyframeRule; + + function requireCSSKeyframeRule () { + if (hasRequiredCSSKeyframeRule) return CSSKeyframeRule; + hasRequiredCSSKeyframeRule = 1; + //.CommonJS + var CSSOM = { + CSSRule: CSSRule.CSSRule, + CSSStyleDeclaration: requireCSSStyleDeclaration().CSSStyleDeclaration + }; + ///CommonJS + + + /** + * @constructor + * @see http://www.w3.org/TR/css3-animations/#DOM-CSSKeyframeRule + */ + CSSOM.CSSKeyframeRule = function CSSKeyframeRule() { + CSSOM.CSSRule.call(this); + this.keyText = ''; + this.style = new CSSOM.CSSStyleDeclaration(); + this.style.parentRule = this; + }; + + CSSOM.CSSKeyframeRule.prototype = new CSSOM.CSSRule(); + CSSOM.CSSKeyframeRule.prototype.constructor = CSSOM.CSSKeyframeRule; + CSSOM.CSSKeyframeRule.prototype.type = 8; + //FIXME + //CSSOM.CSSKeyframeRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule; + //CSSOM.CSSKeyframeRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule; + + // http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSKeyframeRule.cpp + Object.defineProperty(CSSOM.CSSKeyframeRule.prototype, "cssText", { + get: function() { + return this.keyText + " {" + this.style.cssText + "} "; + } + }); + + + //.CommonJS + CSSKeyframeRule.CSSKeyframeRule = CSSOM.CSSKeyframeRule; + ///CommonJS + return CSSKeyframeRule; + } + + var CSSKeyframesRule = {}; + + //.CommonJS + var CSSOM$4 = { + CSSRule: CSSRule.CSSRule + }; + ///CommonJS + + + /** + * @constructor + * @see http://www.w3.org/TR/css3-animations/#DOM-CSSKeyframesRule + */ + CSSOM$4.CSSKeyframesRule = function CSSKeyframesRule() { + CSSOM$4.CSSRule.call(this); + this.name = ''; + this.cssRules = []; + }; + + CSSOM$4.CSSKeyframesRule.prototype = new CSSOM$4.CSSRule(); + CSSOM$4.CSSKeyframesRule.prototype.constructor = CSSOM$4.CSSKeyframesRule; + CSSOM$4.CSSKeyframesRule.prototype.type = 7; + //FIXME + //CSSOM.CSSKeyframesRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule; + //CSSOM.CSSKeyframesRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule; + + // http://www.opensource.apple.com/source/WebCore/WebCore-955.66.1/css/WebKitCSSKeyframesRule.cpp + Object.defineProperty(CSSOM$4.CSSKeyframesRule.prototype, "cssText", { + get: function() { + var cssTexts = []; + for (var i=0, length=this.cssRules.length; i < length; i++) { + cssTexts.push(" " + this.cssRules[i].cssText); + } + return "@" + (this._vendorPrefix || '') + "keyframes " + this.name + " { \n" + cssTexts.join("\n") + "\n}"; + } + }); + + + //.CommonJS + CSSKeyframesRule.CSSKeyframesRule = CSSOM$4.CSSKeyframesRule; + + var CSSValueExpression = {}; + + var CSSValue = {}; + + //.CommonJS + var CSSOM$3 = {}; + ///CommonJS + + + /** + * @constructor + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue + * + * TODO: add if needed + */ + CSSOM$3.CSSValue = function CSSValue() { + }; + + CSSOM$3.CSSValue.prototype = { + constructor: CSSOM$3.CSSValue, + + // @see: http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSValue + set cssText(text) { + var name = this._getConstructorName(); + + throw new Error('DOMException: property "cssText" of "' + name + '" is readonly and can not be replaced with "' + text + '"!'); + }, + + get cssText() { + var name = this._getConstructorName(); + + throw new Error('getter "cssText" of "' + name + '" is not implemented!'); + }, + + _getConstructorName: function() { + var s = this.constructor.toString(), + c = s.match(/function\s([^\(]+)/), + name = c[1]; + + return name; + } + }; + + + //.CommonJS + CSSValue.CSSValue = CSSOM$3.CSSValue; + + //.CommonJS + var CSSOM$2 = { + CSSValue: CSSValue.CSSValue + }; + ///CommonJS + + + /** + * @constructor + * @see http://msdn.microsoft.com/en-us/library/ms537634(v=vs.85).aspx + * + */ + CSSOM$2.CSSValueExpression = function CSSValueExpression(token, idx) { + this._token = token; + this._idx = idx; + }; + + CSSOM$2.CSSValueExpression.prototype = new CSSOM$2.CSSValue(); + CSSOM$2.CSSValueExpression.prototype.constructor = CSSOM$2.CSSValueExpression; + + /** + * parse css expression() value + * + * @return {Object} + * - error: + * or + * - idx: + * - expression: + * + * Example: + * + * .selector { + * zoom: expression(documentElement.clientWidth > 1000 ? '1000px' : 'auto'); + * } + */ + CSSOM$2.CSSValueExpression.prototype.parse = function() { + var token = this._token, + idx = this._idx; + + var character = '', + expression = '', + error = '', + info, + paren = []; + + + for (; ; ++idx) { + character = token.charAt(idx); + + // end of token + if (character === '') { + error = 'css expression error: unfinished expression!'; + break; + } + + switch(character) { + case '(': + paren.push(character); + expression += character; + break; + + case ')': + paren.pop(character); + expression += character; + break; + + case '/': + if ((info = this._parseJSComment(token, idx))) { // comment? + if (info.error) { + error = 'css expression error: unfinished comment in expression!'; + } else { + idx = info.idx; + // ignore the comment + } + } else if ((info = this._parseJSRexExp(token, idx))) { // regexp + idx = info.idx; + expression += info.text; + } else { // other + expression += character; + } + break; + + case "'": + case '"': + info = this._parseJSString(token, idx, character); + if (info) { // string + idx = info.idx; + expression += info.text; + } else { + expression += character; + } + break; + + default: + expression += character; + break; + } + + if (error) { + break; + } + + // end of expression + if (paren.length === 0) { + break; + } + } + + var ret; + if (error) { + ret = { + error: error + }; + } else { + ret = { + idx: idx, + expression: expression + }; + } + + return ret; + }; + + + /** + * + * @return {Object|false} + * - idx: + * - text: + * or + * - error: + * or + * false + * + */ + CSSOM$2.CSSValueExpression.prototype._parseJSComment = function(token, idx) { + var nextChar = token.charAt(idx + 1), + text; + + if (nextChar === '/' || nextChar === '*') { + var startIdx = idx, + endIdx, + commentEndChar; + + if (nextChar === '/') { // line comment + commentEndChar = '\n'; + } else if (nextChar === '*') { // block comment + commentEndChar = '*/'; + } + + endIdx = token.indexOf(commentEndChar, startIdx + 1 + 1); + if (endIdx !== -1) { + endIdx = endIdx + commentEndChar.length - 1; + text = token.substring(idx, endIdx + 1); + return { + idx: endIdx, + text: text + }; + } else { + var error = 'css expression error: unfinished comment in expression!'; + return { + error: error + }; + } + } else { + return false; + } + }; + + + /** + * + * @return {Object|false} + * - idx: + * - text: + * or + * false + * + */ + CSSOM$2.CSSValueExpression.prototype._parseJSString = function(token, idx, sep) { + var endIdx = this._findMatchedIdx(token, idx, sep), + text; + + if (endIdx === -1) { + return false; + } else { + text = token.substring(idx, endIdx + sep.length); + + return { + idx: endIdx, + text: text + }; + } + }; + + + /** + * parse regexp in css expression + * + * @return {Object|false} + * - idx: + * - regExp: + * or + * false + */ + + /* + + all legal RegExp + + /a/ + (/a/) + [/a/] + [12, /a/] + + !/a/ + + +/a/ + -/a/ + * /a/ + / /a/ + %/a/ + + ===/a/ + !==/a/ + ==/a/ + !=/a/ + >/a/ + >=/a/ + </a/ + <=/a/ + + &/a/ + |/a/ + ^/a/ + ~/a/ + <</a/ + >>/a/ + >>>/a/ + + &&/a/ + ||/a/ + ?/a/ + =/a/ + ,/a/ + + delete /a/ + in /a/ + instanceof /a/ + new /a/ + typeof /a/ + void /a/ + + */ + CSSOM$2.CSSValueExpression.prototype._parseJSRexExp = function(token, idx) { + var before = token.substring(0, idx).replace(/\s+$/, ""), + legalRegx = [ + /^$/, + /\($/, + /\[$/, + /\!$/, + /\+$/, + /\-$/, + /\*$/, + /\/\s+/, + /\%$/, + /\=$/, + /\>$/, + /<$/, + /\&$/, + /\|$/, + /\^$/, + /\~$/, + /\?$/, + /\,$/, + /delete$/, + /in$/, + /instanceof$/, + /new$/, + /typeof$/, + /void$/ + ]; + + var isLegal = legalRegx.some(function(reg) { + return reg.test(before); + }); + + if (!isLegal) { + return false; + } else { + var sep = '/'; + + // same logic as string + return this._parseJSString(token, idx, sep); + } + }; + + + /** + * + * find next sep(same line) index in `token` + * + * @return {Number} + * + */ + CSSOM$2.CSSValueExpression.prototype._findMatchedIdx = function(token, idx, sep) { + var startIdx = idx, + endIdx; + + var NOT_FOUND = -1; + + while(true) { + endIdx = token.indexOf(sep, startIdx + 1); + + if (endIdx === -1) { // not found + endIdx = NOT_FOUND; + break; + } else { + var text = token.substring(idx + 1, endIdx), + matched = text.match(/\\+$/); + if (!matched || matched[0] % 2 === 0) { // not escaped + break; + } else { + startIdx = endIdx; + } + } + } + + // boundary must be in the same line(js sting or regexp) + var nextNewLineIdx = token.indexOf('\n', idx + 1); + if (nextNewLineIdx < endIdx) { + endIdx = NOT_FOUND; + } + + + return endIdx; + }; + + + + + //.CommonJS + CSSValueExpression.CSSValueExpression = CSSOM$2.CSSValueExpression; + + var CSSDocumentRule = {}; + + var MatcherList = {}; + + //.CommonJS + var CSSOM$1 = {}; + ///CommonJS + + + /** + * @constructor + * @see https://developer.mozilla.org/en/CSS/@-moz-document + */ + CSSOM$1.MatcherList = function MatcherList(){ + this.length = 0; + }; + + CSSOM$1.MatcherList.prototype = { + + constructor: CSSOM$1.MatcherList, + + /** + * @return {string} + */ + get matcherText() { + return Array.prototype.join.call(this, ", "); + }, + + /** + * @param {string} value + */ + set matcherText(value) { + // just a temporary solution, actually it may be wrong by just split the value with ',', because a url can include ','. + var values = value.split(","); + var length = this.length = values.length; + for (var i=0; i<length; i++) { + this[i] = values[i].trim(); + } + }, + + /** + * @param {string} matcher + */ + appendMatcher: function(matcher) { + if (Array.prototype.indexOf.call(this, matcher) === -1) { + this[this.length] = matcher; + this.length++; + } + }, + + /** + * @param {string} matcher + */ + deleteMatcher: function(matcher) { + var index = Array.prototype.indexOf.call(this, matcher); + if (index !== -1) { + Array.prototype.splice.call(this, index, 1); + } + } + + }; + + + //.CommonJS + MatcherList.MatcherList = CSSOM$1.MatcherList; + + //.CommonJS + var CSSOM = { + CSSRule: CSSRule.CSSRule, + MatcherList: MatcherList.MatcherList + }; + ///CommonJS + + + /** + * @constructor + * @see https://developer.mozilla.org/en/CSS/@-moz-document + */ + CSSOM.CSSDocumentRule = function CSSDocumentRule() { + CSSOM.CSSRule.call(this); + this.matcher = new CSSOM.MatcherList(); + this.cssRules = []; + }; + + CSSOM.CSSDocumentRule.prototype = new CSSOM.CSSRule(); + CSSOM.CSSDocumentRule.prototype.constructor = CSSOM.CSSDocumentRule; + CSSOM.CSSDocumentRule.prototype.type = 10; + //FIXME + //CSSOM.CSSDocumentRule.prototype.insertRule = CSSStyleSheet.prototype.insertRule; + //CSSOM.CSSDocumentRule.prototype.deleteRule = CSSStyleSheet.prototype.deleteRule; + + Object.defineProperty(CSSOM.CSSDocumentRule.prototype, "cssText", { + get: function() { + var cssTexts = []; + for (var i=0, length=this.cssRules.length; i < length; i++) { + cssTexts.push(this.cssRules[i].cssText); + } + return "@-moz-document " + this.matcher.matcherText + " {" + cssTexts.join("") + "}"; + } + }); + + + //.CommonJS + CSSDocumentRule.CSSDocumentRule = CSSOM.CSSDocumentRule; + + var hasRequiredParse; + + function requireParse () { + if (hasRequiredParse) return parse$8; + hasRequiredParse = 1; + //.CommonJS + var CSSOM = {}; + ///CommonJS + + + /** + * @param {string} token + */ + CSSOM.parse = function parse(token) { + + var i = 0; + + /** + "before-selector" or + "selector" or + "atRule" or + "atBlock" or + "conditionBlock" or + "before-name" or + "name" or + "before-value" or + "value" + */ + var state = "before-selector"; + + var index; + var buffer = ""; + var valueParenthesisDepth = 0; + + var SIGNIFICANT_WHITESPACE = { + "selector": true, + "value": true, + "value-parenthesis": true, + "atRule": true, + "importRule-begin": true, + "importRule": true, + "atBlock": true, + "conditionBlock": true, + 'documentRule-begin': true + }; + + var styleSheet = new CSSOM.CSSStyleSheet(); + + // @type CSSStyleSheet|CSSMediaRule|CSSSupportsRule|CSSFontFaceRule|CSSKeyframesRule|CSSDocumentRule + var currentScope = styleSheet; + + // @type CSSMediaRule|CSSSupportsRule|CSSKeyframesRule|CSSDocumentRule + var parentRule; + + var ancestorRules = []; + var hasAncestors = false; + var prevScope; + + var name, priority="", styleRule, mediaRule, supportsRule, importRule, fontFaceRule, keyframesRule, documentRule, hostRule; + + var atKeyframesRegExp = /@(-(?:\w+-)+)?keyframes/g; + + var parseError = function(message) { + var lines = token.substring(0, i).split('\n'); + var lineCount = lines.length; + var charCount = lines.pop().length + 1; + var error = new Error(message + ' (line ' + lineCount + ', char ' + charCount + ')'); + error.line = lineCount; + /* jshint sub : true */ + error['char'] = charCount; + error.styleSheet = styleSheet; + throw error; + }; + + for (var character; (character = token.charAt(i)); i++) { + + switch (character) { + + case " ": + case "\t": + case "\r": + case "\n": + case "\f": + if (SIGNIFICANT_WHITESPACE[state]) { + buffer += character; + } + break; + + // String + case '"': + index = i + 1; + do { + index = token.indexOf('"', index) + 1; + if (!index) { + parseError('Unmatched "'); + } + } while (token[index - 2] === '\\'); + buffer += token.slice(i, index); + i = index - 1; + switch (state) { + case 'before-value': + state = 'value'; + break; + case 'importRule-begin': + state = 'importRule'; + break; + } + break; + + case "'": + index = i + 1; + do { + index = token.indexOf("'", index) + 1; + if (!index) { + parseError("Unmatched '"); + } + } while (token[index - 2] === '\\'); + buffer += token.slice(i, index); + i = index - 1; + switch (state) { + case 'before-value': + state = 'value'; + break; + case 'importRule-begin': + state = 'importRule'; + break; + } + break; + + // Comment + case "/": + if (token.charAt(i + 1) === "*") { + i += 2; + index = token.indexOf("*/", i); + if (index === -1) { + parseError("Missing */"); + } else { + i = index + 1; + } + } else { + buffer += character; + } + if (state === "importRule-begin") { + buffer += " "; + state = "importRule"; + } + break; + + // At-rule + case "@": + if (token.indexOf("@-moz-document", i) === i) { + state = "documentRule-begin"; + documentRule = new CSSOM.CSSDocumentRule(); + documentRule.__starts = i; + i += "-moz-document".length; + buffer = ""; + break; + } else if (token.indexOf("@media", i) === i) { + state = "atBlock"; + mediaRule = new CSSOM.CSSMediaRule(); + mediaRule.__starts = i; + i += "media".length; + buffer = ""; + break; + } else if (token.indexOf("@supports", i) === i) { + state = "conditionBlock"; + supportsRule = new CSSOM.CSSSupportsRule(); + supportsRule.__starts = i; + i += "supports".length; + buffer = ""; + break; + } else if (token.indexOf("@host", i) === i) { + state = "hostRule-begin"; + i += "host".length; + hostRule = new CSSOM.CSSHostRule(); + hostRule.__starts = i; + buffer = ""; + break; + } else if (token.indexOf("@import", i) === i) { + state = "importRule-begin"; + i += "import".length; + buffer += "@import"; + break; + } else if (token.indexOf("@font-face", i) === i) { + state = "fontFaceRule-begin"; + i += "font-face".length; + fontFaceRule = new CSSOM.CSSFontFaceRule(); + fontFaceRule.__starts = i; + buffer = ""; + break; + } else { + atKeyframesRegExp.lastIndex = i; + var matchKeyframes = atKeyframesRegExp.exec(token); + if (matchKeyframes && matchKeyframes.index === i) { + state = "keyframesRule-begin"; + keyframesRule = new CSSOM.CSSKeyframesRule(); + keyframesRule.__starts = i; + keyframesRule._vendorPrefix = matchKeyframes[1]; // Will come out as undefined if no prefix was found + i += matchKeyframes[0].length - 1; + buffer = ""; + break; + } else if (state === "selector") { + state = "atRule"; + } + } + buffer += character; + break; + + case "{": + if (state === "selector" || state === "atRule") { + styleRule.selectorText = buffer.trim(); + styleRule.style.__starts = i; + buffer = ""; + state = "before-name"; + } else if (state === "atBlock") { + mediaRule.media.mediaText = buffer.trim(); + + if (parentRule) { + ancestorRules.push(parentRule); + } + + currentScope = parentRule = mediaRule; + mediaRule.parentStyleSheet = styleSheet; + buffer = ""; + state = "before-selector"; + } else if (state === "conditionBlock") { + supportsRule.conditionText = buffer.trim(); + + if (parentRule) { + ancestorRules.push(parentRule); + } + + currentScope = parentRule = supportsRule; + supportsRule.parentStyleSheet = styleSheet; + buffer = ""; + state = "before-selector"; + } else if (state === "hostRule-begin") { + if (parentRule) { + ancestorRules.push(parentRule); + } + + currentScope = parentRule = hostRule; + hostRule.parentStyleSheet = styleSheet; + buffer = ""; + state = "before-selector"; + } else if (state === "fontFaceRule-begin") { + if (parentRule) { + fontFaceRule.parentRule = parentRule; + } + fontFaceRule.parentStyleSheet = styleSheet; + styleRule = fontFaceRule; + buffer = ""; + state = "before-name"; + } else if (state === "keyframesRule-begin") { + keyframesRule.name = buffer.trim(); + if (parentRule) { + ancestorRules.push(parentRule); + keyframesRule.parentRule = parentRule; + } + keyframesRule.parentStyleSheet = styleSheet; + currentScope = parentRule = keyframesRule; + buffer = ""; + state = "keyframeRule-begin"; + } else if (state === "keyframeRule-begin") { + styleRule = new CSSOM.CSSKeyframeRule(); + styleRule.keyText = buffer.trim(); + styleRule.__starts = i; + buffer = ""; + state = "before-name"; + } else if (state === "documentRule-begin") { + // FIXME: what if this '{' is in the url text of the match function? + documentRule.matcher.matcherText = buffer.trim(); + if (parentRule) { + ancestorRules.push(parentRule); + documentRule.parentRule = parentRule; + } + currentScope = parentRule = documentRule; + documentRule.parentStyleSheet = styleSheet; + buffer = ""; + state = "before-selector"; + } + break; + + case ":": + if (state === "name") { + name = buffer.trim(); + buffer = ""; + state = "before-value"; + } else { + buffer += character; + } + break; + + case "(": + if (state === 'value') { + // ie css expression mode + if (buffer.trim() === 'expression') { + var info = (new CSSOM.CSSValueExpression(token, i)).parse(); + + if (info.error) { + parseError(info.error); + } else { + buffer += info.expression; + i = info.idx; + } + } else { + state = 'value-parenthesis'; + //always ensure this is reset to 1 on transition + //from value to value-parenthesis + valueParenthesisDepth = 1; + buffer += character; + } + } else if (state === 'value-parenthesis') { + valueParenthesisDepth++; + buffer += character; + } else { + buffer += character; + } + break; + + case ")": + if (state === 'value-parenthesis') { + valueParenthesisDepth--; + if (valueParenthesisDepth === 0) state = 'value'; + } + buffer += character; + break; + + case "!": + if (state === "value" && token.indexOf("!important", i) === i) { + priority = "important"; + i += "important".length; + } else { + buffer += character; + } + break; + + case ";": + switch (state) { + case "value": + styleRule.style.setProperty(name, buffer.trim(), priority); + priority = ""; + buffer = ""; + state = "before-name"; + break; + case "atRule": + buffer = ""; + state = "before-selector"; + break; + case "importRule": + importRule = new CSSOM.CSSImportRule(); + importRule.parentStyleSheet = importRule.styleSheet.parentStyleSheet = styleSheet; + importRule.cssText = buffer + character; + styleSheet.cssRules.push(importRule); + buffer = ""; + state = "before-selector"; + break; + default: + buffer += character; + break; + } + break; + + case "}": + switch (state) { + case "value": + styleRule.style.setProperty(name, buffer.trim(), priority); + priority = ""; + /* falls through */ + case "before-name": + case "name": + styleRule.__ends = i + 1; + if (parentRule) { + styleRule.parentRule = parentRule; + } + styleRule.parentStyleSheet = styleSheet; + currentScope.cssRules.push(styleRule); + buffer = ""; + if (currentScope.constructor === CSSOM.CSSKeyframesRule) { + state = "keyframeRule-begin"; + } else { + state = "before-selector"; + } + break; + case "keyframeRule-begin": + case "before-selector": + case "selector": + // End of media/supports/document rule. + if (!parentRule) { + parseError("Unexpected }"); + } + + // Handle rules nested in @media or @supports + hasAncestors = ancestorRules.length > 0; + + while (ancestorRules.length > 0) { + parentRule = ancestorRules.pop(); + + if ( + parentRule.constructor.name === "CSSMediaRule" + || parentRule.constructor.name === "CSSSupportsRule" + ) { + prevScope = currentScope; + currentScope = parentRule; + currentScope.cssRules.push(prevScope); + break; + } + + if (ancestorRules.length === 0) { + hasAncestors = false; + } + } + + if (!hasAncestors) { + currentScope.__ends = i + 1; + styleSheet.cssRules.push(currentScope); + currentScope = styleSheet; + parentRule = null; + } + + buffer = ""; + state = "before-selector"; + break; + } + break; + + default: + switch (state) { + case "before-selector": + state = "selector"; + styleRule = new CSSOM.CSSStyleRule(); + styleRule.__starts = i; + break; + case "before-name": + state = "name"; + break; + case "before-value": + state = "value"; + break; + case "importRule-begin": + state = "importRule"; + break; + } + buffer += character; + break; + } + } + + return styleSheet; + }; + + + //.CommonJS + parse$8.parse = CSSOM.parse; + // The following modules cannot be included sooner due to the mutual dependency with parse.js + CSSOM.CSSStyleSheet = requireCSSStyleSheet().CSSStyleSheet; + CSSOM.CSSStyleRule = requireCSSStyleRule().CSSStyleRule; + CSSOM.CSSImportRule = requireCSSImportRule().CSSImportRule; + CSSOM.CSSGroupingRule = CSSGroupingRule.CSSGroupingRule; + CSSOM.CSSMediaRule = CSSMediaRule.CSSMediaRule; + CSSOM.CSSConditionRule = CSSConditionRule.CSSConditionRule; + CSSOM.CSSSupportsRule = CSSSupportsRule.CSSSupportsRule; + CSSOM.CSSFontFaceRule = requireCSSFontFaceRule().CSSFontFaceRule; + CSSOM.CSSHostRule = CSSHostRule.CSSHostRule; + CSSOM.CSSStyleDeclaration = requireCSSStyleDeclaration().CSSStyleDeclaration; + CSSOM.CSSKeyframeRule = requireCSSKeyframeRule().CSSKeyframeRule; + CSSOM.CSSKeyframesRule = CSSKeyframesRule.CSSKeyframesRule; + CSSOM.CSSValueExpression = CSSValueExpression.CSSValueExpression; + CSSOM.CSSDocumentRule = CSSDocumentRule.CSSDocumentRule; + ///CommonJS + return parse$8; + } + + var hasRequiredCSSStyleDeclaration; + + function requireCSSStyleDeclaration () { + if (hasRequiredCSSStyleDeclaration) return CSSStyleDeclaration; + hasRequiredCSSStyleDeclaration = 1; + //.CommonJS + var CSSOM = {}; + ///CommonJS + + + /** + * @constructor + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration + */ + CSSOM.CSSStyleDeclaration = function CSSStyleDeclaration(){ + this.length = 0; + this.parentRule = null; + + // NON-STANDARD + this._importants = {}; + }; + + + CSSOM.CSSStyleDeclaration.prototype = { + + constructor: CSSOM.CSSStyleDeclaration, + + /** + * + * @param {string} name + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-getPropertyValue + * @return {string} the value of the property if it has been explicitly set for this declaration block. + * Returns the empty string if the property has not been set. + */ + getPropertyValue: function(name) { + return this[name] || ""; + }, + + /** + * + * @param {string} name + * @param {string} value + * @param {string} [priority=null] "important" or null + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-setProperty + */ + setProperty: function(name, value, priority) { + if (this[name]) { + // Property already exist. Overwrite it. + var index = Array.prototype.indexOf.call(this, name); + if (index < 0) { + this[this.length] = name; + this.length++; + } + } else { + // New property. + this[this.length] = name; + this.length++; + } + this[name] = value + ""; + this._importants[name] = priority; + }, + + /** + * + * @param {string} name + * @see http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleDeclaration-removeProperty + * @return {string} the value of the property if it has been explicitly set for this declaration block. + * Returns the empty string if the property has not been set or the property name does not correspond to a known CSS property. + */ + removeProperty: function(name) { + if (!(name in this)) { + return ""; + } + var index = Array.prototype.indexOf.call(this, name); + if (index < 0) { + return ""; + } + var prevValue = this[name]; + this[name] = ""; + + // That's what WebKit and Opera do + Array.prototype.splice.call(this, index, 1); + + // That's what Firefox does + //this[index] = "" + + return prevValue; + }, + + getPropertyCSSValue: function() { + //FIXME + }, + + /** + * + * @param {String} name + */ + getPropertyPriority: function(name) { + return this._importants[name] || ""; + }, + + + /** + * element.style.overflow = "auto" + * element.style.getPropertyShorthand("overflow-x") + * -> "overflow" + */ + getPropertyShorthand: function() { + //FIXME + }, + + isPropertyImplicit: function() { + //FIXME + }, + + // Doesn't work in IE < 9 + get cssText(){ + var properties = []; + for (var i=0, length=this.length; i < length; ++i) { + var name = this[i]; + var value = this.getPropertyValue(name); + var priority = this.getPropertyPriority(name); + if (priority) { + priority = " !" + priority; + } + properties[i] = name + ": " + value + priority + ";"; + } + return properties.join(" "); + }, + + set cssText(text){ + var i, name; + for (i = this.length; i--;) { + name = this[i]; + this[name] = ""; + } + Array.prototype.splice.call(this, 0, this.length); + this._importants = {}; + + var dummyRule = CSSOM.parse('#bogus{' + text + '}').cssRules[0].style; + var length = dummyRule.length; + for (i = 0; i < length; ++i) { + name = dummyRule[i]; + this.setProperty(dummyRule[i], dummyRule.getPropertyValue(name), dummyRule.getPropertyPriority(name)); + } + } + }; + + + //.CommonJS + CSSStyleDeclaration.CSSStyleDeclaration = CSSOM.CSSStyleDeclaration; + CSSOM.parse = requireParse().parse; // Cannot be included sooner due to the mutual dependency between parse.js and CSSStyleDeclaration.js + ///CommonJS + return CSSStyleDeclaration; + } + + //.CommonJS + ({ + CSSStyleSheet: requireCSSStyleSheet().CSSStyleSheet, + CSSRule: CSSRule.CSSRule, + CSSStyleRule: requireCSSStyleRule().CSSStyleRule, + CSSGroupingRule: CSSGroupingRule.CSSGroupingRule, + CSSConditionRule: CSSConditionRule.CSSConditionRule, + CSSMediaRule: CSSMediaRule.CSSMediaRule, + CSSSupportsRule: CSSSupportsRule.CSSSupportsRule, + CSSStyleDeclaration: requireCSSStyleDeclaration().CSSStyleDeclaration, + CSSKeyframeRule: requireCSSKeyframeRule().CSSKeyframeRule, + CSSKeyframesRule: CSSKeyframesRule.CSSKeyframesRule + }); + + requireCSSStyleDeclaration().CSSStyleDeclaration; + requireCSSStyleRule().CSSStyleRule; + requireCSSImportRule().CSSImportRule; + requireCSSFontFaceRule().CSSFontFaceRule; + requireCSSStyleSheet().CSSStyleSheet; + requireCSSKeyframeRule().CSSKeyframeRule; + var parse$7 = requireParse().parse; + + const tagName$e = 'style'; + + /** + * @implements globalThis.HTMLStyleElement + */ + class HTMLStyleElement extends TextElement { + constructor(ownerDocument, localName = tagName$e) { + super(ownerDocument, localName); + this[SHEET] = null; + } + + get sheet() { + const sheet = this[SHEET]; + if (sheet !== null) { + return sheet; + } + return this[SHEET] = parse$7(this.textContent); + } + + get innerHTML() { + return super.innerHTML || ''; + } + set innerHTML(value) { + super.textContent = value; + this[SHEET] = null; + } + get innerText() { + return super.innerText || ''; + } + set innerText(value) { + super.textContent = value; + this[SHEET] = null; + } + get textContent() { + return super.textContent || ''; + } + set textContent(value) { + super.textContent = value; + this[SHEET] = null; + } + } + + registerHTMLClass(tagName$e, HTMLStyleElement); + + /** + * @implements globalThis.HTMLTimeElement + */ + class HTMLTimeElement extends HTMLElement { + constructor(ownerDocument, localName = 'time') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLFieldSetElement + */ + class HTMLFieldSetElement extends HTMLElement { + constructor(ownerDocument, localName = 'fieldset') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLEmbedElement + */ + class HTMLEmbedElement extends HTMLElement { + constructor(ownerDocument, localName = 'embed') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLHRElement + */ + class HTMLHRElement extends HTMLElement { + constructor(ownerDocument, localName = 'hr') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLProgressElement + */ + class HTMLProgressElement extends HTMLElement { + constructor(ownerDocument, localName = 'progress') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLParagraphElement + */ + class HTMLParagraphElement extends HTMLElement { + constructor(ownerDocument, localName = 'p') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLTableElement + */ + class HTMLTableElement extends HTMLElement { + constructor(ownerDocument, localName = 'table') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLFrameSetElement + */ + class HTMLFrameSetElement extends HTMLElement { + constructor(ownerDocument, localName = 'frameset') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLLIElement + */ + class HTMLLIElement extends HTMLElement { + constructor(ownerDocument, localName = 'li') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLBaseElement + */ + class HTMLBaseElement extends HTMLElement { + constructor(ownerDocument, localName = 'base') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLDataListElement + */ + class HTMLDataListElement extends HTMLElement { + constructor(ownerDocument, localName = 'datalist') { + super(ownerDocument, localName); + } + } + + const tagName$d = 'input'; + + /** + * @implements globalThis.HTMLInputElement + */ + class HTMLInputElement extends HTMLElement { + constructor(ownerDocument, localName = tagName$d) { + super(ownerDocument, localName); + } + + /* c8 ignore start */ + get autofocus() { return booleanAttribute.get(this, 'autofocus') || -1; } + set autofocus(value) { booleanAttribute.set(this, 'autofocus', value); } + + get disabled() { return booleanAttribute.get(this, 'disabled'); } + set disabled(value) { booleanAttribute.set(this, 'disabled', value); } + + get name() { return this.getAttribute('name'); } + set name(value) { this.setAttribute('name', value); } + + get placeholder() { return this.getAttribute('placeholder'); } + set placeholder(value) { this.setAttribute('placeholder', value); } + + get type() { return this.getAttribute('type'); } + set type(value) { this.setAttribute('type', value); } + + get value() { return stringAttribute.get(this, 'value'); } + set value(value) { stringAttribute.set(this, 'value', value); } + /* c8 ignore stop */ + } + + registerHTMLClass(tagName$d, HTMLInputElement); + + /** + * @implements globalThis.HTMLParamElement + */ + class HTMLParamElement extends HTMLElement { + constructor(ownerDocument, localName = 'param') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLMediaElement + */ + class HTMLMediaElement extends HTMLElement { + constructor(ownerDocument, localName = 'media') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLAudioElement + */ + class HTMLAudioElement extends HTMLElement { + constructor(ownerDocument, localName = 'audio') { + super(ownerDocument, localName); + } + } + + const tagName$c = 'h1'; + + /** + * @implements globalThis.HTMLHeadingElement + */ + class HTMLHeadingElement extends HTMLElement { + constructor(ownerDocument, localName = tagName$c) { + super(ownerDocument, localName); + } + } + + registerHTMLClass([tagName$c, 'h2', 'h3', 'h4', 'h5', 'h6'], HTMLHeadingElement); + + /** + * @implements globalThis.HTMLDirectoryElement + */ + class HTMLDirectoryElement extends HTMLElement { + constructor(ownerDocument, localName = 'dir') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLQuoteElement + */ + class HTMLQuoteElement extends HTMLElement { + constructor(ownerDocument, localName = 'quote') { + super(ownerDocument, localName); + } + } + + var canvas = {exports: {}}; + + var canvasShim; + var hasRequiredCanvasShim; + + function requireCanvasShim () { + if (hasRequiredCanvasShim) return canvasShim; + hasRequiredCanvasShim = 1; + class Canvas { + constructor(width, height) { + this.width = width; + this.height = height; + } + getContext() { + return null; + } + toDataURL() { + return ''; + } + } + + canvasShim = { + createCanvas: (width, height) => new Canvas(width, height), + }; + return canvasShim; + } + + /* c8 ignore start */ + + try { + canvas.exports = require('canvas'); + } catch (fallback) { + canvas.exports = requireCanvasShim(); + } + /* c8 ignore stop */ + + var canvasExports = canvas.exports; + var Canvas = /*@__PURE__*/getDefaultExportFromCjs(canvasExports); + + const {createCanvas} = Canvas; + + const tagName$b = 'canvas'; + + /** + * @implements globalThis.HTMLCanvasElement + */ + class HTMLCanvasElement extends HTMLElement { + constructor(ownerDocument, localName = tagName$b) { + super(ownerDocument, localName); + this[IMAGE] = createCanvas(300, 150); + } + + get width() { + return this[IMAGE].width; + } + + set width(value) { + numericAttribute.set(this, 'width', value); + this[IMAGE].width = value; + } + + get height() { + return this[IMAGE].height; + } + + set height(value) { + numericAttribute.set(this, 'height', value); + this[IMAGE].height = value; + } + + getContext(type) { + return this[IMAGE].getContext(type); + } + + toDataURL(...args) { + return this[IMAGE].toDataURL(...args); + } + } + + registerHTMLClass(tagName$b, HTMLCanvasElement); + + /** + * @implements globalThis.HTMLLegendElement + */ + class HTMLLegendElement extends HTMLElement { + constructor(ownerDocument, localName = 'legend') { + super(ownerDocument, localName); + } + } + + const tagName$a = 'option'; + + /** + * @implements globalThis.HTMLOptionElement + */ + class HTMLOptionElement extends HTMLElement { + constructor(ownerDocument, localName = tagName$a) { + super(ownerDocument, localName); + } + + /* c8 ignore start */ + get value() { return stringAttribute.get(this, 'value'); } + set value(value) { stringAttribute.set(this, 'value', value); } + /* c8 ignore stop */ + + get selected() { return booleanAttribute.get(this, 'selected'); } + set selected(value) { + const option = this.parentElement?.querySelector('option[selected]'); + if (option && option !== this) + option.selected = false; + booleanAttribute.set(this, 'selected', value); + } + } + + registerHTMLClass(tagName$a, HTMLOptionElement); + + /** + * @implements globalThis.HTMLSpanElement + */ + class HTMLSpanElement extends HTMLElement { + constructor(ownerDocument, localName = 'span') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLMeterElement + */ + class HTMLMeterElement extends HTMLElement { + constructor(ownerDocument, localName = 'meter') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLVideoElement + */ + class HTMLVideoElement extends HTMLElement { + constructor(ownerDocument, localName = 'video') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLTableCellElement + */ + class HTMLTableCellElement extends HTMLElement { + constructor(ownerDocument, localName = 'td') { + super(ownerDocument, localName); + } + } + + const tagName$9 = 'title'; + + /** + * @implements globalThis.HTMLTitleElement + */ + class HTMLTitleElement extends TextElement { + constructor(ownerDocument, localName = tagName$9) { + super(ownerDocument, localName); + } + } + + registerHTMLClass(tagName$9, HTMLTitleElement); + + /** + * @implements globalThis.HTMLOutputElement + */ + class HTMLOutputElement extends HTMLElement { + constructor(ownerDocument, localName = 'output') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLTableRowElement + */ + class HTMLTableRowElement extends HTMLElement { + constructor(ownerDocument, localName = 'tr') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLDataElement + */ + class HTMLDataElement extends HTMLElement { + constructor(ownerDocument, localName = 'data') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLMenuElement + */ + class HTMLMenuElement extends HTMLElement { + constructor(ownerDocument, localName = 'menu') { + super(ownerDocument, localName); + } + } + + const tagName$8 = 'select'; + + /** + * @implements globalThis.HTMLSelectElement + */ + class HTMLSelectElement extends HTMLElement { + constructor(ownerDocument, localName = tagName$8) { + super(ownerDocument, localName); + } + + get options() { + let children = new NodeList; + let {firstElementChild} = this; + while (firstElementChild) { + if (firstElementChild.tagName === 'OPTGROUP') + children.push(...firstElementChild.children); + else + children.push(firstElementChild); + firstElementChild = firstElementChild.nextElementSibling; + } + return children; + } + + /* c8 ignore start */ + get disabled() { return booleanAttribute.get(this, 'disabled'); } + set disabled(value) { booleanAttribute.set(this, 'disabled', value); } + + get name() { return this.getAttribute('name'); } + set name(value) { this.setAttribute('name', value); } + /* c8 ignore stop */ + + get value() { return this.querySelector('option[selected]')?.value; } + } + + registerHTMLClass(tagName$8, HTMLSelectElement); + + /** + * @implements globalThis.HTMLBRElement + */ + class HTMLBRElement extends HTMLElement { + constructor(ownerDocument, localName = 'br') { + super(ownerDocument, localName); + } + } + + const tagName$7 = 'button'; + + /** + * @implements globalThis.HTMLButtonElement + */ + class HTMLButtonElement extends HTMLElement { + constructor(ownerDocument, localName = tagName$7) { + super(ownerDocument, localName); + } + + /* c8 ignore start */ + get disabled() { return booleanAttribute.get(this, 'disabled'); } + set disabled(value) { booleanAttribute.set(this, 'disabled', value); } + + get name() { return this.getAttribute('name'); } + set name(value) { this.setAttribute('name', value); } + + get type() { return this.getAttribute('type'); } + set type(value) { this.setAttribute('type', value); } + /* c8 ignore stop */ + } + + registerHTMLClass(tagName$7, HTMLButtonElement); + + /** + * @implements globalThis.HTMLMapElement + */ + class HTMLMapElement extends HTMLElement { + constructor(ownerDocument, localName = 'map') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLOptGroupElement + */ + class HTMLOptGroupElement extends HTMLElement { + constructor(ownerDocument, localName = 'optgroup') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLDListElement + */ + class HTMLDListElement extends HTMLElement { + constructor(ownerDocument, localName = 'dl') { + super(ownerDocument, localName); + } + } + + const tagName$6 = 'textarea'; + + /** + * @implements globalThis.HTMLTextAreaElement + */ + class HTMLTextAreaElement extends TextElement { + constructor(ownerDocument, localName = tagName$6) { + super(ownerDocument, localName); + } + + /* c8 ignore start */ + get disabled() { return booleanAttribute.get(this, 'disabled'); } + set disabled(value) { booleanAttribute.set(this, 'disabled', value); } + + get name() { return this.getAttribute('name'); } + set name(value) { this.setAttribute('name', value); } + + get placeholder() { return this.getAttribute('placeholder'); } + set placeholder(value) { this.setAttribute('placeholder', value); } + + get type() { return this.getAttribute('type'); } + set type(value) { this.setAttribute('type', value); } + + get value() { return this.textContent; } + set value(content) { this.textContent = content; } + /* c8 ignore stop */ + } + + registerHTMLClass(tagName$6, HTMLTextAreaElement); + + /** + * @implements globalThis.HTMLFontElement + */ + class HTMLFontElement extends HTMLElement { + constructor(ownerDocument, localName = 'font') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLDivElement + */ + class HTMLDivElement extends HTMLElement { + constructor(ownerDocument, localName = 'div') { + super(ownerDocument, localName); + } + } + + const tagName$5 = 'link'; + + /** + * @implements globalThis.HTMLLinkElement + */ + class HTMLLinkElement extends HTMLElement { + constructor(ownerDocument, localName = tagName$5) { + super(ownerDocument, localName); + } + + /* c8 ignore start */ // copy paste from img.src, already covered + get disabled() { return booleanAttribute.get(this, 'disabled'); } + set disabled(value) { booleanAttribute.set(this, 'disabled', value); } + + get href() { return stringAttribute.get(this, 'href'); } + set href(value) { stringAttribute.set(this, 'href', value); } + + get hreflang() { return stringAttribute.get(this, 'hreflang'); } + set hreflang(value) { stringAttribute.set(this, 'hreflang', value); } + + get media() { return stringAttribute.get(this, 'media'); } + set media(value) { stringAttribute.set(this, 'media', value); } + + get rel() { return stringAttribute.get(this, 'rel'); } + set rel(value) { stringAttribute.set(this, 'rel', value); } + + get type() { return stringAttribute.get(this, 'type'); } + set type(value) { stringAttribute.set(this, 'type', value); } + /* c8 ignore stop */ + + } + + registerHTMLClass(tagName$5, HTMLLinkElement); + + const tagName$4 = 'slot'; + + /** + * @implements globalThis.HTMLSlotElement + */ + class HTMLSlotElement extends HTMLElement { + constructor(ownerDocument, localName = tagName$4) { + super(ownerDocument, localName); + } + + /* c8 ignore start */ + get name() { return this.getAttribute('name'); } + set name(value) { this.setAttribute('name', value); } + + assign() {} + + assignedNodes(options) { + const isNamedSlot = !!this.name; + const hostChildNodes = this.getRootNode().host?.childNodes ?? []; + let slottables; + + if (isNamedSlot) { + slottables = [...hostChildNodes].filter(node => node.slot === this.name); + } else { + slottables = [...hostChildNodes].filter(node => !node.slot); + } + + if (options?.flatten) { + const result = []; + + // Element and Text nodes are slottables. A slot can be a slottable. + for (let slottable of slottables) { + if (slottable.localName === 'slot') { + result.push(...slottable.assignedNodes({ flatten: true })); + } else { + result.push(slottable); + } + } + + slottables = result; + } + + // If no assigned nodes are found, it returns the slot's fallback content. + return slottables.length ? slottables : [...this.childNodes]; + } + + assignedElements(options) { + const slottables = this.assignedNodes(options).filter(n => n.nodeType === 1); + + // If no assigned elements are found, it returns the slot's fallback content. + return slottables.length ? slottables : [...this.children]; + } + /* c8 ignore stop */ + } + + registerHTMLClass(tagName$4, HTMLSlotElement); + + /** + * @implements globalThis.HTMLFormElement + */ + class HTMLFormElement extends HTMLElement { + constructor(ownerDocument, localName = 'form') { + super(ownerDocument, localName); + } + } + + const tagName$3 = 'img'; + + /** + * @implements globalThis.HTMLImageElement + */ + class HTMLImageElement extends HTMLElement { + constructor(ownerDocument, localName = tagName$3) { + super(ownerDocument, localName); + } + + /* c8 ignore start */ + get alt() { return stringAttribute.get(this, 'alt'); } + set alt(value) { stringAttribute.set(this, 'alt', value); } + + get sizes() { return stringAttribute.get(this, 'sizes'); } + set sizes(value) { stringAttribute.set(this, 'sizes', value); } + + get src() { return stringAttribute.get(this, 'src'); } + set src(value) { stringAttribute.set(this, 'src', value); } + + get srcset() { return stringAttribute.get(this, 'srcset'); } + set srcset(value) { stringAttribute.set(this, 'srcset', value); } + + get title() { return stringAttribute.get(this, 'title'); } + set title(value) { stringAttribute.set(this, 'title', value); } + + get width() { return numericAttribute.get(this, 'width'); } + set width(value) { numericAttribute.set(this, 'width', value); } + + get height() { return numericAttribute.get(this, 'height'); } + set height(value) { numericAttribute.set(this, 'height', value); } + /* c8 ignore stop */ + } + + registerHTMLClass(tagName$3, HTMLImageElement); + + /** + * @implements globalThis.HTMLPreElement + */ + class HTMLPreElement extends HTMLElement { + constructor(ownerDocument, localName = 'pre') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLUListElement + */ + class HTMLUListElement extends HTMLElement { + constructor(ownerDocument, localName = 'ul') { + super(ownerDocument, localName); + } + } + + const tagName$2 = 'meta'; + /** + * @implements globalThis.HTMLMetaElement + */ + class HTMLMetaElement extends HTMLElement { + constructor(ownerDocument, localName =tagName$2) { + super(ownerDocument, localName); + } + + /* c8 ignore start */ + get name() { return stringAttribute.get(this, 'name'); } + set name(value) { stringAttribute.set(this, 'name', value); } + + get httpEquiv() { return stringAttribute.get(this, 'http-equiv'); } + set httpEquiv(value) { stringAttribute.set(this, 'http-equiv', value); } + + get content() { return stringAttribute.get(this, 'content'); } + set content(value) { stringAttribute.set(this, 'content', value); } + + get charset() { return stringAttribute.get(this, 'charset'); } + set charset(value) { stringAttribute.set(this, 'charset', value); } + + get media() { return stringAttribute.get(this, 'media'); } + set media(value) { stringAttribute.set(this, 'media', value); } + /* c8 ignore stop */ + + } + + registerHTMLClass(tagName$2, HTMLMetaElement); + + /** + * @implements globalThis.HTMLPictureElement + */ + class HTMLPictureElement extends HTMLElement { + constructor(ownerDocument, localName = 'picture') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLAreaElement + */ + class HTMLAreaElement extends HTMLElement { + constructor(ownerDocument, localName = 'area') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLOListElement + */ + class HTMLOListElement extends HTMLElement { + constructor(ownerDocument, localName = 'ol') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLTableCaptionElement + */ + class HTMLTableCaptionElement extends HTMLElement { + constructor(ownerDocument, localName = 'caption') { + super(ownerDocument, localName); + } + } + + const tagName$1 = 'a'; + + /** + * @implements globalThis.HTMLAnchorElement + */ + class HTMLAnchorElement extends HTMLElement { + constructor(ownerDocument, localName = tagName$1) { + super(ownerDocument, localName); + } + + /* c8 ignore start */ // copy paste from img.src, already covered + get href() { return encodeURI(decodeURI(stringAttribute.get(this, 'href'))); } + set href(value) { stringAttribute.set(this, 'href', decodeURI(value)); } + + get download() { return encodeURI(decodeURI(stringAttribute.get(this, 'download'))); } + set download(value) { stringAttribute.set(this, 'download', decodeURI(value)); } + + get target() { return stringAttribute.get(this, 'target'); } + set target(value) { stringAttribute.set(this, 'target', value); } + + get type() { return stringAttribute.get(this, 'type'); } + set type(value) { stringAttribute.set(this, 'type', value); } + /* c8 ignore stop */ + + } + + registerHTMLClass(tagName$1, HTMLAnchorElement); + + /** + * @implements globalThis.HTMLLabelElement + */ + class HTMLLabelElement extends HTMLElement { + constructor(ownerDocument, localName = 'label') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLUnknownElement + */ + class HTMLUnknownElement extends HTMLElement { + constructor(ownerDocument, localName = 'unknown') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLModElement + */ + class HTMLModElement extends HTMLElement { + constructor(ownerDocument, localName = 'mod') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLDetailsElement + */ + class HTMLDetailsElement extends HTMLElement { + constructor(ownerDocument, localName = 'details') { + super(ownerDocument, localName); + } + } + + const tagName = 'source'; + + /** + * @implements globalThis.HTMLSourceElement + */ + class HTMLSourceElement extends HTMLElement { + constructor(ownerDocument, localName = tagName) { + super(ownerDocument, localName); + } + + /* c8 ignore start */ + get src() { return stringAttribute.get(this, 'src'); } + set src(value) { stringAttribute.set(this, 'src', value); } + + get srcset() { return stringAttribute.get(this, 'srcset'); } + set srcset(value) { stringAttribute.set(this, 'srcset', value); } + + get sizes() { return stringAttribute.get(this, 'sizes'); } + set sizes(value) { stringAttribute.set(this, 'sizes', value); } + + get type() { return stringAttribute.get(this, 'type'); } + set type(value) { stringAttribute.set(this, 'type', value); } + /* c8 ignore stop */ + } + + registerHTMLClass(tagName, HTMLSourceElement); + + /** + * @implements globalThis.HTMLTrackElement + */ + class HTMLTrackElement extends HTMLElement { + constructor(ownerDocument, localName = 'track') { + super(ownerDocument, localName); + } + } + + /** + * @implements globalThis.HTMLMarqueeElement + */ + class HTMLMarqueeElement extends HTMLElement { + constructor(ownerDocument, localName = 'marquee') { + super(ownerDocument, localName); + } + } + + const HTMLClasses = { + HTMLElement, + HTMLTemplateElement, + HTMLHtmlElement, + HTMLScriptElement, + HTMLFrameElement, + HTMLIFrameElement, + HTMLObjectElement, + HTMLHeadElement, + HTMLBodyElement, + HTMLStyleElement, + HTMLTimeElement, + HTMLFieldSetElement, + HTMLEmbedElement, + HTMLHRElement, + HTMLProgressElement, + HTMLParagraphElement, + HTMLTableElement, + HTMLFrameSetElement, + HTMLLIElement, + HTMLBaseElement, + HTMLDataListElement, + HTMLInputElement, + HTMLParamElement, + HTMLMediaElement, + HTMLAudioElement, + HTMLHeadingElement, + HTMLDirectoryElement, + HTMLQuoteElement, + HTMLCanvasElement, + HTMLLegendElement, + HTMLOptionElement, + HTMLSpanElement, + HTMLMeterElement, + HTMLVideoElement, + HTMLTableCellElement, + HTMLTitleElement, + HTMLOutputElement, + HTMLTableRowElement, + HTMLDataElement, + HTMLMenuElement, + HTMLSelectElement, + HTMLBRElement, + HTMLButtonElement, + HTMLMapElement, + HTMLOptGroupElement, + HTMLDListElement, + HTMLTextAreaElement, + HTMLFontElement, + HTMLDivElement, + HTMLLinkElement, + HTMLSlotElement, + HTMLFormElement, + HTMLImageElement, + HTMLPreElement, + HTMLUListElement, + HTMLMetaElement, + HTMLPictureElement, + HTMLAreaElement, + HTMLOListElement, + HTMLTableCaptionElement, + HTMLAnchorElement, + HTMLLabelElement, + HTMLUnknownElement, + HTMLModElement, + HTMLDetailsElement, + HTMLSourceElement, + HTMLTrackElement, + HTMLMarqueeElement + }; + + // TODO: ensure all these are text only + // /^(?:plaintext|script|style|textarea|title|xmp)$/i + + const voidElements$1 = {test: () => true}; + const Mime = { + 'text/html': { + docType: '<!DOCTYPE html>', + ignoreCase: true, + voidElements: /^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i + }, + 'image/svg+xml': { + docType: '<?xml version="1.0" encoding="utf-8"?>', + ignoreCase: false, + voidElements: voidElements$1 + }, + 'text/xml': { + docType: '<?xml version="1.0" encoding="utf-8"?>', + ignoreCase: false, + voidElements: voidElements$1 + }, + 'application/xml': { + docType: '<?xml version="1.0" encoding="utf-8"?>', + ignoreCase: false, + voidElements: voidElements$1 + }, + 'application/xhtml+xml': { + docType: '<?xml version="1.0" encoding="utf-8"?>', + ignoreCase: false, + voidElements: voidElements$1 + } + }; + + // https://dom.spec.whatwg.org/#interface-customevent + + + /** + * @implements globalThis.CustomEvent + */ + class CustomEvent extends GlobalEvent { + constructor(type, eventInitDict = {}) { + super(type, eventInitDict); + this.detail = eventInitDict.detail; + } + } + + /* c8 ignore stop */ + + // https://dom.spec.whatwg.org/#interface-customevent + + + /** + * @implements globalThis.InputEvent + */ + class InputEvent extends GlobalEvent { + constructor(type, inputEventInit = {}) { + super(type, inputEventInit); + this.inputType = inputEventInit.inputType; + this.data = inputEventInit.data; + this.dataTransfer = inputEventInit.dataTransfer; + this.isComposing = inputEventInit.isComposing || false; + this.ranges = inputEventInit.ranges; + } + } + /* c8 ignore stop */ + + const ImageClass = ownerDocument => + /** + * @implements globalThis.Image + */ + class Image extends HTMLImageElement { + constructor(width, height) { + super(ownerDocument); + switch (arguments.length) { + case 1: + this.height = width; + this.width = width; + break; + case 2: + this.height = height; + this.width = width; + break; + } + } + }; + + // https://dom.spec.whatwg.org/#concept-live-range + + + const deleteContents = ({[START]: start, [END]: end}, fragment = null) => { + setAdjacent(start[PREV], end[NEXT]); + do { + const after = getEnd(start); + const next = after === end ? after : after[NEXT]; + if (fragment) + fragment.insertBefore(start, fragment[END]); + else + start.remove(); + start = next; + } while (start !== end); + }; + + /** + * @implements globalThis.Range + */ + class Range { + constructor() { + this[START] = null; + this[END] = null; + this.commonAncestorContainer = null; + } + + /* TODO: this is more complicated than it looks + setStart(node, offset) { + this[START] = node.childNodes[offset]; + } + + setEnd(node, offset) { + this[END] = getEnd(node.childNodes[offset]); + } + //*/ + + insertNode(newNode) { + this[END].parentNode.insertBefore(newNode, this[START]); + } + + selectNode(node) { + this[START] = node; + this[END] = getEnd(node); + } + + // TODO: SVG elements should then create contextual fragments + // that return SVG nodes + selectNodeContents(node) { + this.selectNode(node); + this.commonAncestorContainer = node; + } + + surroundContents(parentNode) { + parentNode.replaceChildren(this.extractContents()); + } + + setStartBefore(node) { + this[START] = node; + } + + setStartAfter(node) { + this[START] = node.nextSibling; + } + + setEndBefore(node) { + this[END] = getEnd(node.previousSibling); + } + + setEndAfter(node) { + this[END] = getEnd(node); + } + + cloneContents() { + let {[START]: start, [END]: end} = this; + const fragment = start.ownerDocument.createDocumentFragment(); + while (start !== end) { + fragment.insertBefore(start.cloneNode(true), fragment[END]); + start = getEnd(start); + if (start !== end) + start = start[NEXT]; + } + return fragment; + } + + deleteContents() { + deleteContents(this); + } + + extractContents() { + const fragment = this[START].ownerDocument.createDocumentFragment(); + deleteContents(this, fragment); + return fragment; + } + + createContextualFragment(html) { + const { commonAncestorContainer: doc } = this; + const isSVG = 'ownerSVGElement' in doc; + const document = isSVG ? doc.ownerDocument : doc; + const template = document.createElement('template'); + template.innerHTML = html; + let {content} = template; + if (isSVG) { + const childNodes = [...content.childNodes]; + content = document.createDocumentFragment(); + Object.setPrototypeOf(content, SVGElement$1.prototype); + content.ownerSVGElement = document; + for (const child of childNodes) { + Object.setPrototypeOf(child, SVGElement$1.prototype); + child.ownerSVGElement = document; + content.appendChild(child); + } + } + else + this.selectNode(content); + return content; + } + + cloneRange() { + const range = new Range; + range[START] = this[START]; + range[END] = this[END]; + return range; + } + } + + const isOK = ({nodeType}, mask) => { + switch (nodeType) { + case ELEMENT_NODE: + return mask & SHOW_ELEMENT; + case TEXT_NODE: + return mask & SHOW_TEXT; + case COMMENT_NODE: + return mask & SHOW_COMMENT; + case CDATA_SECTION_NODE: + return mask & SHOW_CDATA_SECTION; + } + return 0; + }; + + /** + * @implements globalThis.TreeWalker + */ + class TreeWalker { + constructor(root, whatToShow = SHOW_ALL) { + this.root = root; + this.currentNode = root; + this.whatToShow = whatToShow; + let {[NEXT]: next, [END]: end} = root; + if (root.nodeType === DOCUMENT_NODE) { + const {documentElement} = root; + next = documentElement; + end = documentElement[END]; + } + const nodes = []; + while (next !== end) { + if (isOK(next, whatToShow)) + nodes.push(next); + next = next[NEXT]; + } + this[PRIVATE] = {i: 0, nodes}; + } + + nextNode() { + const $ = this[PRIVATE]; + this.currentNode = $.i < $.nodes.length ? $.nodes[$.i++] : null; + return this.currentNode; + } + } + + const query = (method, ownerDocument, selectors) => { + let {[NEXT]: next, [END]: end} = ownerDocument; + return method.call({ownerDocument, [NEXT]: next, [END]: end}, selectors); + }; + + const globalExports = assign( + {}, + Facades, + HTMLClasses, + { + CustomEvent, + Event: GlobalEvent, + EventTarget: DOMEventTarget, + InputEvent, + NamedNodeMap, + NodeList + } + ); + + const window$1 = new WeakMap; + + /** + * @implements globalThis.Document + */ + let Document$6 = class Document extends NonElementParentNode { + constructor(type) { + super(null, '#document', DOCUMENT_NODE); + this[CUSTOM_ELEMENTS] = {active: false, registry: null}; + this[MUTATION_OBSERVER] = {active: false, class: null}; + this[MIME] = Mime[type]; + /** @type {DocumentType} */ + this[DOCTYPE] = null; + this[DOM_PARSER] = null; + this[GLOBALS] = null; + this[IMAGE] = null; + this[UPGRADE] = null; + } + + /** + * @type {globalThis.Document['defaultView']} + */ + get defaultView() { + if (!window$1.has(this)) + window$1.set(this, new Proxy(globalThis, { + set: (target, name, value) => { + switch (name) { + case 'addEventListener': + case 'removeEventListener': + case 'dispatchEvent': + this[EVENT_TARGET][name] = value; + break; + default: + target[name] = value; + break; + } + return true; + }, + get: (globalThis, name) => { + switch (name) { + case 'addEventListener': + case 'removeEventListener': + case 'dispatchEvent': + if (!this[EVENT_TARGET]) { + const et = this[EVENT_TARGET] = new DOMEventTarget; + et.dispatchEvent = et.dispatchEvent.bind(et); + et.addEventListener = et.addEventListener.bind(et); + et.removeEventListener = et.removeEventListener.bind(et); + } + return this[EVENT_TARGET][name]; + case 'document': + return this; + /* c8 ignore start */ + case 'navigator': + return { + userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36' + }; + /* c8 ignore stop */ + case 'window': + return window$1.get(this); + case 'customElements': + if (!this[CUSTOM_ELEMENTS].registry) + this[CUSTOM_ELEMENTS] = new CustomElementRegistry(this); + return this[CUSTOM_ELEMENTS]; + case 'performance': + return performance_1; + case 'DOMParser': + return this[DOM_PARSER]; + case 'Image': + if (!this[IMAGE]) + this[IMAGE] = ImageClass(this); + return this[IMAGE]; + case 'MutationObserver': + if (!this[MUTATION_OBSERVER].class) + this[MUTATION_OBSERVER] = new MutationObserverClass(this); + return this[MUTATION_OBSERVER].class; + } + return (this[GLOBALS] && this[GLOBALS][name]) || + globalExports[name] || + globalThis[name]; + } + })); + return window$1.get(this); + } + + get doctype() { + const docType = this[DOCTYPE]; + if (docType) + return docType; + const {firstChild} = this; + if (firstChild && firstChild.nodeType === DOCUMENT_TYPE_NODE) + return (this[DOCTYPE] = firstChild); + return null; + } + + set doctype(value) { + if (/^([a-z:]+)(\s+system|\s+public(\s+"([^"]+)")?)?(\s+"([^"]+)")?/i.test(value)) { + const {$1: name, $4: publicId, $6: systemId} = RegExp; + this[DOCTYPE] = new DocumentType$1(this, name, publicId, systemId); + knownSiblings(this, this[DOCTYPE], this[NEXT]); + } + } + + get documentElement() { + return this.firstElementChild; + } + + get isConnected() { return true; } + + /** + * @protected + */ + _getParent() { + return this[EVENT_TARGET]; + } + + createAttribute(name) { return new Attr$1(this, name); } + createCDATASection(data) { return new CDATASection$1(this, data); } + createComment(textContent) { return new Comment$7(this, textContent); } + createDocumentFragment() { return new DocumentFragment$1(this); } + createDocumentType(name, publicId, systemId) { return new DocumentType$1(this, name, publicId, systemId); } + createElement(localName) { return new Element$2(this, localName); } + createRange() { + const range = new Range; + range.commonAncestorContainer = this; + return range; + } + createTextNode(textContent) { return new Text$2(this, textContent); } + createTreeWalker(root, whatToShow = -1) { return new TreeWalker(root, whatToShow); } + createNodeIterator(root, whatToShow = -1) { return this.createTreeWalker(root, whatToShow); } + + createEvent(name) { + const event = create$1(name === 'Event' ? new GlobalEvent('') : new CustomEvent('')); + event.initEvent = event.initCustomEvent = ( + type, + canBubble = false, + cancelable = false, + detail + ) => { + event.bubbles = !!canBubble; + + defineProperties(event, { + type: {value: type}, + canBubble: {value: canBubble}, + cancelable: {value: cancelable}, + detail: {value: detail} + }); + }; + return event; + } + + cloneNode(deep = false) { + const { + constructor, + [CUSTOM_ELEMENTS]: customElements, + [DOCTYPE]: doctype + } = this; + const document = new constructor(); + document[CUSTOM_ELEMENTS] = customElements; + if (deep) { + const end = document[END]; + const {childNodes} = this; + for (let {length} = childNodes, i = 0; i < length; i++) + document.insertBefore(childNodes[i].cloneNode(true), end); + if (doctype) + document[DOCTYPE] = childNodes[0]; + } + return document; + } + + importNode(externalNode) { + // important: keep the signature length as *one* + // or it would behave like old IE or Edge with polyfills + const deep = 1 < arguments.length && !!arguments[1]; + const node = externalNode.cloneNode(deep); + const {[CUSTOM_ELEMENTS]: customElements} = this; + const {active} = customElements; + const upgrade = element => { + const {ownerDocument, nodeType} = element; + element.ownerDocument = this; + if (active && ownerDocument !== this && nodeType === ELEMENT_NODE) + customElements.upgrade(element); + }; + upgrade(node); + if (deep) { + switch (node.nodeType) { + case ELEMENT_NODE: + case DOCUMENT_FRAGMENT_NODE: { + let {[NEXT]: next, [END]: end} = node; + while (next !== end) { + if (next.nodeType === ELEMENT_NODE) + upgrade(next); + next = next[NEXT]; + } + break; + } + } + } + return node; + } + + toString() { return this.childNodes.join(''); } + + querySelector(selectors) { + return query(super.querySelector, this, selectors); + } + + querySelectorAll(selectors) { + return query(super.querySelectorAll, this, selectors); + } + + /* c8 ignore start */ + getElementsByTagNameNS(_, name) { + return this.getElementsByTagName(name); + } + createAttributeNS(_, name) { + return this.createAttribute(name); + } + createElementNS(nsp, localName, options) { + return nsp === SVG_NAMESPACE ? + new SVGElement$1(this, localName, null) : + this.createElement(localName, options); + } + /* c8 ignore stop */ + }; + + setPrototypeOf( + globalExports.Document = function Document() { + illegalConstructor(); + }, + Document$6 + ).prototype = Document$6.prototype; + + const createHTMLElement = (ownerDocument, builtin, localName, options) => { + if (!builtin && htmlClasses.has(localName)) { + const Class = htmlClasses.get(localName); + return new Class(ownerDocument, localName); + } + const {[CUSTOM_ELEMENTS]: {active, registry}} = ownerDocument; + if (active) { + const ce = builtin ? options.is : localName; + if (registry.has(ce)) { + const {Class} = registry.get(ce); + const element = new Class(ownerDocument, localName); + customElements.set(element, {connected: false}); + return element; + } + } + return new HTMLElement(ownerDocument, localName); + }; + + /** + * @implements globalThis.HTMLDocument + */ + class HTMLDocument extends Document$6 { + constructor() { super('text/html'); } + + get all() { + const nodeList = new NodeList; + let {[NEXT]: next, [END]: end} = this; + while (next !== end) { + switch (next.nodeType) { + case ELEMENT_NODE: + nodeList.push(next); + break; + } + next = next[NEXT]; + } + return nodeList; + } + + /** + * @type HTMLHeadElement + */ + get head() { + const {documentElement} = this; + let {firstElementChild} = documentElement; + if (!firstElementChild || firstElementChild.tagName !== 'HEAD') { + firstElementChild = this.createElement('head'); + documentElement.prepend(firstElementChild); + } + return firstElementChild; + } + + /** + * @type HTMLBodyElement + */ + get body() { + const {head} = this; + let {nextElementSibling} = head; + if (!nextElementSibling || nextElementSibling.tagName !== 'BODY') { + nextElementSibling = this.createElement('body'); + head.after(nextElementSibling); + } + return nextElementSibling; + } + + /** + * @type HTMLTitleElement + */ + get title() { + const {head} = this; + return head.getElementsByTagName('title').at(0)?.textContent || ''; + } + + set title(textContent) { + const {head} = this; + let title = head.getElementsByTagName('title').at(0); + if (title) + title.textContent = textContent; + else { + head.insertBefore( + this.createElement('title'), + head.firstChild + ).textContent = textContent; + } + } + + createElement(localName, options) { + const builtin = !!(options && options.is); + const element = createHTMLElement(this, builtin, localName, options); + if (builtin) + element.setAttribute('is', options.is); + return element; + } + } + + /** + * @implements globalThis.Document + */ + class SVGDocument extends Document$6 { + constructor() { super('image/svg+xml'); } + toString() { + return this[MIME].docType + super.toString(); + } + } + + /** + * @implements globalThis.XMLDocument + */ + class XMLDocument extends Document$6 { + constructor() { super('text/xml'); } + toString() { + return this[MIME].docType + super.toString(); + } + } + + /** + * @implements globalThis.DOMParser + */ + class DOMParser { + + /** @typedef {{ "text/html": HTMLDocument, "image/svg+xml": SVGDocument, "text/xml": XMLDocument }} MimeToDoc */ + /** + * @template {keyof MimeToDoc} MIME + * @param {string} markupLanguage + * @param {MIME} mimeType + * @returns {MimeToDoc[MIME]} + */ + parseFromString(markupLanguage, mimeType, globals = null) { + let isHTML = false, document; + if (mimeType === 'text/html') { + isHTML = true; + document = new HTMLDocument; + } + else if (mimeType === 'image/svg+xml') + document = new SVGDocument; + else + document = new XMLDocument; + document[DOM_PARSER] = DOMParser; + if (globals) + document[GLOBALS] = globals; + if (isHTML && markupLanguage === '...') + markupLanguage = '<!doctype html><html><head></head><body></body></html>'; + return markupLanguage ? + parseFromString(document, isHTML, markupLanguage) : + document; + } + } + + function Document$5() { + illegalConstructor(); + } + + setPrototypeOf(Document$5, Document$6).prototype = Document$6.prototype; + + var lib$5 = {}; + + var Parser$3 = {}; + + var Tokenizer = {}; + + var decode = {}; + + var decodeDataHtml = {}; + + // Generated using scripts/write-decode-map.ts + Object.defineProperty(decodeDataHtml, "__esModule", { value: true }); + decodeDataHtml.default = new Uint16Array( + // prettier-ignore + "\u1d41<\xd5\u0131\u028a\u049d\u057b\u05d0\u0675\u06de\u07a2\u07d6\u080f\u0a4a\u0a91\u0da1\u0e6d\u0f09\u0f26\u10ca\u1228\u12e1\u1415\u149d\u14c3\u14df\u1525\0\0\0\0\0\0\u156b\u16cd\u198d\u1c12\u1ddd\u1f7e\u2060\u21b0\u228d\u23c0\u23fb\u2442\u2824\u2912\u2d08\u2e48\u2fce\u3016\u32ba\u3639\u37ac\u38fe\u3a28\u3a71\u3ae0\u3b2e\u0800EMabcfglmnoprstu\\bfms\x7f\x84\x8b\x90\x95\x98\xa6\xb3\xb9\xc8\xcflig\u803b\xc6\u40c6P\u803b&\u4026cute\u803b\xc1\u40c1reve;\u4102\u0100iyx}rc\u803b\xc2\u40c2;\u4410r;\uc000\ud835\udd04rave\u803b\xc0\u40c0pha;\u4391acr;\u4100d;\u6a53\u0100gp\x9d\xa1on;\u4104f;\uc000\ud835\udd38plyFunction;\u6061ing\u803b\xc5\u40c5\u0100cs\xbe\xc3r;\uc000\ud835\udc9cign;\u6254ilde\u803b\xc3\u40c3ml\u803b\xc4\u40c4\u0400aceforsu\xe5\xfb\xfe\u0117\u011c\u0122\u0127\u012a\u0100cr\xea\xf2kslash;\u6216\u0176\xf6\xf8;\u6ae7ed;\u6306y;\u4411\u0180crt\u0105\u010b\u0114ause;\u6235noullis;\u612ca;\u4392r;\uc000\ud835\udd05pf;\uc000\ud835\udd39eve;\u42d8c\xf2\u0113mpeq;\u624e\u0700HOacdefhilorsu\u014d\u0151\u0156\u0180\u019e\u01a2\u01b5\u01b7\u01ba\u01dc\u0215\u0273\u0278\u027ecy;\u4427PY\u803b\xa9\u40a9\u0180cpy\u015d\u0162\u017aute;\u4106\u0100;i\u0167\u0168\u62d2talDifferentialD;\u6145leys;\u612d\u0200aeio\u0189\u018e\u0194\u0198ron;\u410cdil\u803b\xc7\u40c7rc;\u4108nint;\u6230ot;\u410a\u0100dn\u01a7\u01adilla;\u40b8terDot;\u40b7\xf2\u017fi;\u43a7rcle\u0200DMPT\u01c7\u01cb\u01d1\u01d6ot;\u6299inus;\u6296lus;\u6295imes;\u6297o\u0100cs\u01e2\u01f8kwiseContourIntegral;\u6232eCurly\u0100DQ\u0203\u020foubleQuote;\u601duote;\u6019\u0200lnpu\u021e\u0228\u0247\u0255on\u0100;e\u0225\u0226\u6237;\u6a74\u0180git\u022f\u0236\u023aruent;\u6261nt;\u622fourIntegral;\u622e\u0100fr\u024c\u024e;\u6102oduct;\u6210nterClockwiseContourIntegral;\u6233oss;\u6a2fcr;\uc000\ud835\udc9ep\u0100;C\u0284\u0285\u62d3ap;\u624d\u0580DJSZacefios\u02a0\u02ac\u02b0\u02b4\u02b8\u02cb\u02d7\u02e1\u02e6\u0333\u048d\u0100;o\u0179\u02a5trahd;\u6911cy;\u4402cy;\u4405cy;\u440f\u0180grs\u02bf\u02c4\u02c7ger;\u6021r;\u61a1hv;\u6ae4\u0100ay\u02d0\u02d5ron;\u410e;\u4414l\u0100;t\u02dd\u02de\u6207a;\u4394r;\uc000\ud835\udd07\u0100af\u02eb\u0327\u0100cm\u02f0\u0322ritical\u0200ADGT\u0300\u0306\u0316\u031ccute;\u40b4o\u0174\u030b\u030d;\u42d9bleAcute;\u42ddrave;\u4060ilde;\u42dcond;\u62c4ferentialD;\u6146\u0470\u033d\0\0\0\u0342\u0354\0\u0405f;\uc000\ud835\udd3b\u0180;DE\u0348\u0349\u034d\u40a8ot;\u60dcqual;\u6250ble\u0300CDLRUV\u0363\u0372\u0382\u03cf\u03e2\u03f8ontourIntegra\xec\u0239o\u0274\u0379\0\0\u037b\xbb\u0349nArrow;\u61d3\u0100eo\u0387\u03a4ft\u0180ART\u0390\u0396\u03a1rrow;\u61d0ightArrow;\u61d4e\xe5\u02cang\u0100LR\u03ab\u03c4eft\u0100AR\u03b3\u03b9rrow;\u67f8ightArrow;\u67faightArrow;\u67f9ight\u0100AT\u03d8\u03derrow;\u61d2ee;\u62a8p\u0241\u03e9\0\0\u03efrrow;\u61d1ownArrow;\u61d5erticalBar;\u6225n\u0300ABLRTa\u0412\u042a\u0430\u045e\u047f\u037crrow\u0180;BU\u041d\u041e\u0422\u6193ar;\u6913pArrow;\u61f5reve;\u4311eft\u02d2\u043a\0\u0446\0\u0450ightVector;\u6950eeVector;\u695eector\u0100;B\u0459\u045a\u61bdar;\u6956ight\u01d4\u0467\0\u0471eeVector;\u695fector\u0100;B\u047a\u047b\u61c1ar;\u6957ee\u0100;A\u0486\u0487\u62a4rrow;\u61a7\u0100ct\u0492\u0497r;\uc000\ud835\udc9frok;\u4110\u0800NTacdfglmopqstux\u04bd\u04c0\u04c4\u04cb\u04de\u04e2\u04e7\u04ee\u04f5\u0521\u052f\u0536\u0552\u055d\u0560\u0565G;\u414aH\u803b\xd0\u40d0cute\u803b\xc9\u40c9\u0180aiy\u04d2\u04d7\u04dcron;\u411arc\u803b\xca\u40ca;\u442dot;\u4116r;\uc000\ud835\udd08rave\u803b\xc8\u40c8ement;\u6208\u0100ap\u04fa\u04fecr;\u4112ty\u0253\u0506\0\0\u0512mallSquare;\u65fberySmallSquare;\u65ab\u0100gp\u0526\u052aon;\u4118f;\uc000\ud835\udd3csilon;\u4395u\u0100ai\u053c\u0549l\u0100;T\u0542\u0543\u6a75ilde;\u6242librium;\u61cc\u0100ci\u0557\u055ar;\u6130m;\u6a73a;\u4397ml\u803b\xcb\u40cb\u0100ip\u056a\u056fsts;\u6203onentialE;\u6147\u0280cfios\u0585\u0588\u058d\u05b2\u05ccy;\u4424r;\uc000\ud835\udd09lled\u0253\u0597\0\0\u05a3mallSquare;\u65fcerySmallSquare;\u65aa\u0370\u05ba\0\u05bf\0\0\u05c4f;\uc000\ud835\udd3dAll;\u6200riertrf;\u6131c\xf2\u05cb\u0600JTabcdfgorst\u05e8\u05ec\u05ef\u05fa\u0600\u0612\u0616\u061b\u061d\u0623\u066c\u0672cy;\u4403\u803b>\u403emma\u0100;d\u05f7\u05f8\u4393;\u43dcreve;\u411e\u0180eiy\u0607\u060c\u0610dil;\u4122rc;\u411c;\u4413ot;\u4120r;\uc000\ud835\udd0a;\u62d9pf;\uc000\ud835\udd3eeater\u0300EFGLST\u0635\u0644\u064e\u0656\u065b\u0666qual\u0100;L\u063e\u063f\u6265ess;\u62dbullEqual;\u6267reater;\u6aa2ess;\u6277lantEqual;\u6a7eilde;\u6273cr;\uc000\ud835\udca2;\u626b\u0400Aacfiosu\u0685\u068b\u0696\u069b\u069e\u06aa\u06be\u06caRDcy;\u442a\u0100ct\u0690\u0694ek;\u42c7;\u405eirc;\u4124r;\u610clbertSpace;\u610b\u01f0\u06af\0\u06b2f;\u610dizontalLine;\u6500\u0100ct\u06c3\u06c5\xf2\u06a9rok;\u4126mp\u0144\u06d0\u06d8ownHum\xf0\u012fqual;\u624f\u0700EJOacdfgmnostu\u06fa\u06fe\u0703\u0707\u070e\u071a\u071e\u0721\u0728\u0744\u0778\u078b\u078f\u0795cy;\u4415lig;\u4132cy;\u4401cute\u803b\xcd\u40cd\u0100iy\u0713\u0718rc\u803b\xce\u40ce;\u4418ot;\u4130r;\u6111rave\u803b\xcc\u40cc\u0180;ap\u0720\u072f\u073f\u0100cg\u0734\u0737r;\u412ainaryI;\u6148lie\xf3\u03dd\u01f4\u0749\0\u0762\u0100;e\u074d\u074e\u622c\u0100gr\u0753\u0758ral;\u622bsection;\u62c2isible\u0100CT\u076c\u0772omma;\u6063imes;\u6062\u0180gpt\u077f\u0783\u0788on;\u412ef;\uc000\ud835\udd40a;\u4399cr;\u6110ilde;\u4128\u01eb\u079a\0\u079ecy;\u4406l\u803b\xcf\u40cf\u0280cfosu\u07ac\u07b7\u07bc\u07c2\u07d0\u0100iy\u07b1\u07b5rc;\u4134;\u4419r;\uc000\ud835\udd0dpf;\uc000\ud835\udd41\u01e3\u07c7\0\u07ccr;\uc000\ud835\udca5rcy;\u4408kcy;\u4404\u0380HJacfos\u07e4\u07e8\u07ec\u07f1\u07fd\u0802\u0808cy;\u4425cy;\u440cppa;\u439a\u0100ey\u07f6\u07fbdil;\u4136;\u441ar;\uc000\ud835\udd0epf;\uc000\ud835\udd42cr;\uc000\ud835\udca6\u0580JTaceflmost\u0825\u0829\u082c\u0850\u0863\u09b3\u09b8\u09c7\u09cd\u0a37\u0a47cy;\u4409\u803b<\u403c\u0280cmnpr\u0837\u083c\u0841\u0844\u084dute;\u4139bda;\u439bg;\u67ealacetrf;\u6112r;\u619e\u0180aey\u0857\u085c\u0861ron;\u413ddil;\u413b;\u441b\u0100fs\u0868\u0970t\u0500ACDFRTUVar\u087e\u08a9\u08b1\u08e0\u08e6\u08fc\u092f\u095b\u0390\u096a\u0100nr\u0883\u088fgleBracket;\u67e8row\u0180;BR\u0899\u089a\u089e\u6190ar;\u61e4ightArrow;\u61c6eiling;\u6308o\u01f5\u08b7\0\u08c3bleBracket;\u67e6n\u01d4\u08c8\0\u08d2eeVector;\u6961ector\u0100;B\u08db\u08dc\u61c3ar;\u6959loor;\u630aight\u0100AV\u08ef\u08f5rrow;\u6194ector;\u694e\u0100er\u0901\u0917e\u0180;AV\u0909\u090a\u0910\u62a3rrow;\u61a4ector;\u695aiangle\u0180;BE\u0924\u0925\u0929\u62b2ar;\u69cfqual;\u62b4p\u0180DTV\u0937\u0942\u094cownVector;\u6951eeVector;\u6960ector\u0100;B\u0956\u0957\u61bfar;\u6958ector\u0100;B\u0965\u0966\u61bcar;\u6952ight\xe1\u039cs\u0300EFGLST\u097e\u098b\u0995\u099d\u09a2\u09adqualGreater;\u62daullEqual;\u6266reater;\u6276ess;\u6aa1lantEqual;\u6a7dilde;\u6272r;\uc000\ud835\udd0f\u0100;e\u09bd\u09be\u62d8ftarrow;\u61daidot;\u413f\u0180npw\u09d4\u0a16\u0a1bg\u0200LRlr\u09de\u09f7\u0a02\u0a10eft\u0100AR\u09e6\u09ecrrow;\u67f5ightArrow;\u67f7ightArrow;\u67f6eft\u0100ar\u03b3\u0a0aight\xe1\u03bfight\xe1\u03caf;\uc000\ud835\udd43er\u0100LR\u0a22\u0a2ceftArrow;\u6199ightArrow;\u6198\u0180cht\u0a3e\u0a40\u0a42\xf2\u084c;\u61b0rok;\u4141;\u626a\u0400acefiosu\u0a5a\u0a5d\u0a60\u0a77\u0a7c\u0a85\u0a8b\u0a8ep;\u6905y;\u441c\u0100dl\u0a65\u0a6fiumSpace;\u605flintrf;\u6133r;\uc000\ud835\udd10nusPlus;\u6213pf;\uc000\ud835\udd44c\xf2\u0a76;\u439c\u0480Jacefostu\u0aa3\u0aa7\u0aad\u0ac0\u0b14\u0b19\u0d91\u0d97\u0d9ecy;\u440acute;\u4143\u0180aey\u0ab4\u0ab9\u0aberon;\u4147dil;\u4145;\u441d\u0180gsw\u0ac7\u0af0\u0b0eative\u0180MTV\u0ad3\u0adf\u0ae8ediumSpace;\u600bhi\u0100cn\u0ae6\u0ad8\xeb\u0ad9eryThi\xee\u0ad9ted\u0100GL\u0af8\u0b06reaterGreate\xf2\u0673essLes\xf3\u0a48Line;\u400ar;\uc000\ud835\udd11\u0200Bnpt\u0b22\u0b28\u0b37\u0b3areak;\u6060BreakingSpace;\u40a0f;\u6115\u0680;CDEGHLNPRSTV\u0b55\u0b56\u0b6a\u0b7c\u0ba1\u0beb\u0c04\u0c5e\u0c84\u0ca6\u0cd8\u0d61\u0d85\u6aec\u0100ou\u0b5b\u0b64ngruent;\u6262pCap;\u626doubleVerticalBar;\u6226\u0180lqx\u0b83\u0b8a\u0b9bement;\u6209ual\u0100;T\u0b92\u0b93\u6260ilde;\uc000\u2242\u0338ists;\u6204reater\u0380;EFGLST\u0bb6\u0bb7\u0bbd\u0bc9\u0bd3\u0bd8\u0be5\u626fqual;\u6271ullEqual;\uc000\u2267\u0338reater;\uc000\u226b\u0338ess;\u6279lantEqual;\uc000\u2a7e\u0338ilde;\u6275ump\u0144\u0bf2\u0bfdownHump;\uc000\u224e\u0338qual;\uc000\u224f\u0338e\u0100fs\u0c0a\u0c27tTriangle\u0180;BE\u0c1a\u0c1b\u0c21\u62eaar;\uc000\u29cf\u0338qual;\u62ecs\u0300;EGLST\u0c35\u0c36\u0c3c\u0c44\u0c4b\u0c58\u626equal;\u6270reater;\u6278ess;\uc000\u226a\u0338lantEqual;\uc000\u2a7d\u0338ilde;\u6274ested\u0100GL\u0c68\u0c79reaterGreater;\uc000\u2aa2\u0338essLess;\uc000\u2aa1\u0338recedes\u0180;ES\u0c92\u0c93\u0c9b\u6280qual;\uc000\u2aaf\u0338lantEqual;\u62e0\u0100ei\u0cab\u0cb9verseElement;\u620cghtTriangle\u0180;BE\u0ccb\u0ccc\u0cd2\u62ebar;\uc000\u29d0\u0338qual;\u62ed\u0100qu\u0cdd\u0d0cuareSu\u0100bp\u0ce8\u0cf9set\u0100;E\u0cf0\u0cf3\uc000\u228f\u0338qual;\u62e2erset\u0100;E\u0d03\u0d06\uc000\u2290\u0338qual;\u62e3\u0180bcp\u0d13\u0d24\u0d4eset\u0100;E\u0d1b\u0d1e\uc000\u2282\u20d2qual;\u6288ceeds\u0200;EST\u0d32\u0d33\u0d3b\u0d46\u6281qual;\uc000\u2ab0\u0338lantEqual;\u62e1ilde;\uc000\u227f\u0338erset\u0100;E\u0d58\u0d5b\uc000\u2283\u20d2qual;\u6289ilde\u0200;EFT\u0d6e\u0d6f\u0d75\u0d7f\u6241qual;\u6244ullEqual;\u6247ilde;\u6249erticalBar;\u6224cr;\uc000\ud835\udca9ilde\u803b\xd1\u40d1;\u439d\u0700Eacdfgmoprstuv\u0dbd\u0dc2\u0dc9\u0dd5\u0ddb\u0de0\u0de7\u0dfc\u0e02\u0e20\u0e22\u0e32\u0e3f\u0e44lig;\u4152cute\u803b\xd3\u40d3\u0100iy\u0dce\u0dd3rc\u803b\xd4\u40d4;\u441eblac;\u4150r;\uc000\ud835\udd12rave\u803b\xd2\u40d2\u0180aei\u0dee\u0df2\u0df6cr;\u414cga;\u43a9cron;\u439fpf;\uc000\ud835\udd46enCurly\u0100DQ\u0e0e\u0e1aoubleQuote;\u601cuote;\u6018;\u6a54\u0100cl\u0e27\u0e2cr;\uc000\ud835\udcaaash\u803b\xd8\u40d8i\u016c\u0e37\u0e3cde\u803b\xd5\u40d5es;\u6a37ml\u803b\xd6\u40d6er\u0100BP\u0e4b\u0e60\u0100ar\u0e50\u0e53r;\u603eac\u0100ek\u0e5a\u0e5c;\u63deet;\u63b4arenthesis;\u63dc\u0480acfhilors\u0e7f\u0e87\u0e8a\u0e8f\u0e92\u0e94\u0e9d\u0eb0\u0efcrtialD;\u6202y;\u441fr;\uc000\ud835\udd13i;\u43a6;\u43a0usMinus;\u40b1\u0100ip\u0ea2\u0eadncareplan\xe5\u069df;\u6119\u0200;eio\u0eb9\u0eba\u0ee0\u0ee4\u6abbcedes\u0200;EST\u0ec8\u0ec9\u0ecf\u0eda\u627aqual;\u6aaflantEqual;\u627cilde;\u627eme;\u6033\u0100dp\u0ee9\u0eeeuct;\u620fortion\u0100;a\u0225\u0ef9l;\u621d\u0100ci\u0f01\u0f06r;\uc000\ud835\udcab;\u43a8\u0200Ufos\u0f11\u0f16\u0f1b\u0f1fOT\u803b\"\u4022r;\uc000\ud835\udd14pf;\u611acr;\uc000\ud835\udcac\u0600BEacefhiorsu\u0f3e\u0f43\u0f47\u0f60\u0f73\u0fa7\u0faa\u0fad\u1096\u10a9\u10b4\u10bearr;\u6910G\u803b\xae\u40ae\u0180cnr\u0f4e\u0f53\u0f56ute;\u4154g;\u67ebr\u0100;t\u0f5c\u0f5d\u61a0l;\u6916\u0180aey\u0f67\u0f6c\u0f71ron;\u4158dil;\u4156;\u4420\u0100;v\u0f78\u0f79\u611cerse\u0100EU\u0f82\u0f99\u0100lq\u0f87\u0f8eement;\u620builibrium;\u61cbpEquilibrium;\u696fr\xbb\u0f79o;\u43a1ght\u0400ACDFTUVa\u0fc1\u0feb\u0ff3\u1022\u1028\u105b\u1087\u03d8\u0100nr\u0fc6\u0fd2gleBracket;\u67e9row\u0180;BL\u0fdc\u0fdd\u0fe1\u6192ar;\u61e5eftArrow;\u61c4eiling;\u6309o\u01f5\u0ff9\0\u1005bleBracket;\u67e7n\u01d4\u100a\0\u1014eeVector;\u695dector\u0100;B\u101d\u101e\u61c2ar;\u6955loor;\u630b\u0100er\u102d\u1043e\u0180;AV\u1035\u1036\u103c\u62a2rrow;\u61a6ector;\u695biangle\u0180;BE\u1050\u1051\u1055\u62b3ar;\u69d0qual;\u62b5p\u0180DTV\u1063\u106e\u1078ownVector;\u694feeVector;\u695cector\u0100;B\u1082\u1083\u61bear;\u6954ector\u0100;B\u1091\u1092\u61c0ar;\u6953\u0100pu\u109b\u109ef;\u611dndImplies;\u6970ightarrow;\u61db\u0100ch\u10b9\u10bcr;\u611b;\u61b1leDelayed;\u69f4\u0680HOacfhimoqstu\u10e4\u10f1\u10f7\u10fd\u1119\u111e\u1151\u1156\u1161\u1167\u11b5\u11bb\u11bf\u0100Cc\u10e9\u10eeHcy;\u4429y;\u4428FTcy;\u442ccute;\u415a\u0280;aeiy\u1108\u1109\u110e\u1113\u1117\u6abcron;\u4160dil;\u415erc;\u415c;\u4421r;\uc000\ud835\udd16ort\u0200DLRU\u112a\u1134\u113e\u1149ownArrow\xbb\u041eeftArrow\xbb\u089aightArrow\xbb\u0fddpArrow;\u6191gma;\u43a3allCircle;\u6218pf;\uc000\ud835\udd4a\u0272\u116d\0\0\u1170t;\u621aare\u0200;ISU\u117b\u117c\u1189\u11af\u65a1ntersection;\u6293u\u0100bp\u118f\u119eset\u0100;E\u1197\u1198\u628fqual;\u6291erset\u0100;E\u11a8\u11a9\u6290qual;\u6292nion;\u6294cr;\uc000\ud835\udcaear;\u62c6\u0200bcmp\u11c8\u11db\u1209\u120b\u0100;s\u11cd\u11ce\u62d0et\u0100;E\u11cd\u11d5qual;\u6286\u0100ch\u11e0\u1205eeds\u0200;EST\u11ed\u11ee\u11f4\u11ff\u627bqual;\u6ab0lantEqual;\u627dilde;\u627fTh\xe1\u0f8c;\u6211\u0180;es\u1212\u1213\u1223\u62d1rset\u0100;E\u121c\u121d\u6283qual;\u6287et\xbb\u1213\u0580HRSacfhiors\u123e\u1244\u1249\u1255\u125e\u1271\u1276\u129f\u12c2\u12c8\u12d1ORN\u803b\xde\u40deADE;\u6122\u0100Hc\u124e\u1252cy;\u440by;\u4426\u0100bu\u125a\u125c;\u4009;\u43a4\u0180aey\u1265\u126a\u126fron;\u4164dil;\u4162;\u4422r;\uc000\ud835\udd17\u0100ei\u127b\u1289\u01f2\u1280\0\u1287efore;\u6234a;\u4398\u0100cn\u128e\u1298kSpace;\uc000\u205f\u200aSpace;\u6009lde\u0200;EFT\u12ab\u12ac\u12b2\u12bc\u623cqual;\u6243ullEqual;\u6245ilde;\u6248pf;\uc000\ud835\udd4bipleDot;\u60db\u0100ct\u12d6\u12dbr;\uc000\ud835\udcafrok;\u4166\u0ae1\u12f7\u130e\u131a\u1326\0\u132c\u1331\0\0\0\0\0\u1338\u133d\u1377\u1385\0\u13ff\u1404\u140a\u1410\u0100cr\u12fb\u1301ute\u803b\xda\u40dar\u0100;o\u1307\u1308\u619fcir;\u6949r\u01e3\u1313\0\u1316y;\u440eve;\u416c\u0100iy\u131e\u1323rc\u803b\xdb\u40db;\u4423blac;\u4170r;\uc000\ud835\udd18rave\u803b\xd9\u40d9acr;\u416a\u0100di\u1341\u1369er\u0100BP\u1348\u135d\u0100ar\u134d\u1350r;\u405fac\u0100ek\u1357\u1359;\u63dfet;\u63b5arenthesis;\u63ddon\u0100;P\u1370\u1371\u62c3lus;\u628e\u0100gp\u137b\u137fon;\u4172f;\uc000\ud835\udd4c\u0400ADETadps\u1395\u13ae\u13b8\u13c4\u03e8\u13d2\u13d7\u13f3rrow\u0180;BD\u1150\u13a0\u13a4ar;\u6912ownArrow;\u61c5ownArrow;\u6195quilibrium;\u696eee\u0100;A\u13cb\u13cc\u62a5rrow;\u61a5own\xe1\u03f3er\u0100LR\u13de\u13e8eftArrow;\u6196ightArrow;\u6197i\u0100;l\u13f9\u13fa\u43d2on;\u43a5ing;\u416ecr;\uc000\ud835\udcb0ilde;\u4168ml\u803b\xdc\u40dc\u0480Dbcdefosv\u1427\u142c\u1430\u1433\u143e\u1485\u148a\u1490\u1496ash;\u62abar;\u6aeby;\u4412ash\u0100;l\u143b\u143c\u62a9;\u6ae6\u0100er\u1443\u1445;\u62c1\u0180bty\u144c\u1450\u147aar;\u6016\u0100;i\u144f\u1455cal\u0200BLST\u1461\u1465\u146a\u1474ar;\u6223ine;\u407ceparator;\u6758ilde;\u6240ThinSpace;\u600ar;\uc000\ud835\udd19pf;\uc000\ud835\udd4dcr;\uc000\ud835\udcb1dash;\u62aa\u0280cefos\u14a7\u14ac\u14b1\u14b6\u14bcirc;\u4174dge;\u62c0r;\uc000\ud835\udd1apf;\uc000\ud835\udd4ecr;\uc000\ud835\udcb2\u0200fios\u14cb\u14d0\u14d2\u14d8r;\uc000\ud835\udd1b;\u439epf;\uc000\ud835\udd4fcr;\uc000\ud835\udcb3\u0480AIUacfosu\u14f1\u14f5\u14f9\u14fd\u1504\u150f\u1514\u151a\u1520cy;\u442fcy;\u4407cy;\u442ecute\u803b\xdd\u40dd\u0100iy\u1509\u150drc;\u4176;\u442br;\uc000\ud835\udd1cpf;\uc000\ud835\udd50cr;\uc000\ud835\udcb4ml;\u4178\u0400Hacdefos\u1535\u1539\u153f\u154b\u154f\u155d\u1560\u1564cy;\u4416cute;\u4179\u0100ay\u1544\u1549ron;\u417d;\u4417ot;\u417b\u01f2\u1554\0\u155boWidt\xe8\u0ad9a;\u4396r;\u6128pf;\u6124cr;\uc000\ud835\udcb5\u0be1\u1583\u158a\u1590\0\u15b0\u15b6\u15bf\0\0\0\0\u15c6\u15db\u15eb\u165f\u166d\0\u1695\u169b\u16b2\u16b9\0\u16becute\u803b\xe1\u40e1reve;\u4103\u0300;Ediuy\u159c\u159d\u15a1\u15a3\u15a8\u15ad\u623e;\uc000\u223e\u0333;\u623frc\u803b\xe2\u40e2te\u80bb\xb4\u0306;\u4430lig\u803b\xe6\u40e6\u0100;r\xb2\u15ba;\uc000\ud835\udd1erave\u803b\xe0\u40e0\u0100ep\u15ca\u15d6\u0100fp\u15cf\u15d4sym;\u6135\xe8\u15d3ha;\u43b1\u0100ap\u15dfc\u0100cl\u15e4\u15e7r;\u4101g;\u6a3f\u0264\u15f0\0\0\u160a\u0280;adsv\u15fa\u15fb\u15ff\u1601\u1607\u6227nd;\u6a55;\u6a5clope;\u6a58;\u6a5a\u0380;elmrsz\u1618\u1619\u161b\u161e\u163f\u164f\u1659\u6220;\u69a4e\xbb\u1619sd\u0100;a\u1625\u1626\u6221\u0461\u1630\u1632\u1634\u1636\u1638\u163a\u163c\u163e;\u69a8;\u69a9;\u69aa;\u69ab;\u69ac;\u69ad;\u69ae;\u69aft\u0100;v\u1645\u1646\u621fb\u0100;d\u164c\u164d\u62be;\u699d\u0100pt\u1654\u1657h;\u6222\xbb\xb9arr;\u637c\u0100gp\u1663\u1667on;\u4105f;\uc000\ud835\udd52\u0380;Eaeiop\u12c1\u167b\u167d\u1682\u1684\u1687\u168a;\u6a70cir;\u6a6f;\u624ad;\u624bs;\u4027rox\u0100;e\u12c1\u1692\xf1\u1683ing\u803b\xe5\u40e5\u0180cty\u16a1\u16a6\u16a8r;\uc000\ud835\udcb6;\u402amp\u0100;e\u12c1\u16af\xf1\u0288ilde\u803b\xe3\u40e3ml\u803b\xe4\u40e4\u0100ci\u16c2\u16c8onin\xf4\u0272nt;\u6a11\u0800Nabcdefiklnoprsu\u16ed\u16f1\u1730\u173c\u1743\u1748\u1778\u177d\u17e0\u17e6\u1839\u1850\u170d\u193d\u1948\u1970ot;\u6aed\u0100cr\u16f6\u171ek\u0200ceps\u1700\u1705\u170d\u1713ong;\u624cpsilon;\u43f6rime;\u6035im\u0100;e\u171a\u171b\u623dq;\u62cd\u0176\u1722\u1726ee;\u62bded\u0100;g\u172c\u172d\u6305e\xbb\u172drk\u0100;t\u135c\u1737brk;\u63b6\u0100oy\u1701\u1741;\u4431quo;\u601e\u0280cmprt\u1753\u175b\u1761\u1764\u1768aus\u0100;e\u010a\u0109ptyv;\u69b0s\xe9\u170cno\xf5\u0113\u0180ahw\u176f\u1771\u1773;\u43b2;\u6136een;\u626cr;\uc000\ud835\udd1fg\u0380costuvw\u178d\u179d\u17b3\u17c1\u17d5\u17db\u17de\u0180aiu\u1794\u1796\u179a\xf0\u0760rc;\u65efp\xbb\u1371\u0180dpt\u17a4\u17a8\u17adot;\u6a00lus;\u6a01imes;\u6a02\u0271\u17b9\0\0\u17becup;\u6a06ar;\u6605riangle\u0100du\u17cd\u17d2own;\u65bdp;\u65b3plus;\u6a04e\xe5\u1444\xe5\u14adarow;\u690d\u0180ako\u17ed\u1826\u1835\u0100cn\u17f2\u1823k\u0180lst\u17fa\u05ab\u1802ozenge;\u69ebriangle\u0200;dlr\u1812\u1813\u1818\u181d\u65b4own;\u65beeft;\u65c2ight;\u65b8k;\u6423\u01b1\u182b\0\u1833\u01b2\u182f\0\u1831;\u6592;\u65914;\u6593ck;\u6588\u0100eo\u183e\u184d\u0100;q\u1843\u1846\uc000=\u20e5uiv;\uc000\u2261\u20e5t;\u6310\u0200ptwx\u1859\u185e\u1867\u186cf;\uc000\ud835\udd53\u0100;t\u13cb\u1863om\xbb\u13cctie;\u62c8\u0600DHUVbdhmptuv\u1885\u1896\u18aa\u18bb\u18d7\u18db\u18ec\u18ff\u1905\u190a\u1910\u1921\u0200LRlr\u188e\u1890\u1892\u1894;\u6557;\u6554;\u6556;\u6553\u0280;DUdu\u18a1\u18a2\u18a4\u18a6\u18a8\u6550;\u6566;\u6569;\u6564;\u6567\u0200LRlr\u18b3\u18b5\u18b7\u18b9;\u655d;\u655a;\u655c;\u6559\u0380;HLRhlr\u18ca\u18cb\u18cd\u18cf\u18d1\u18d3\u18d5\u6551;\u656c;\u6563;\u6560;\u656b;\u6562;\u655fox;\u69c9\u0200LRlr\u18e4\u18e6\u18e8\u18ea;\u6555;\u6552;\u6510;\u650c\u0280;DUdu\u06bd\u18f7\u18f9\u18fb\u18fd;\u6565;\u6568;\u652c;\u6534inus;\u629flus;\u629eimes;\u62a0\u0200LRlr\u1919\u191b\u191d\u191f;\u655b;\u6558;\u6518;\u6514\u0380;HLRhlr\u1930\u1931\u1933\u1935\u1937\u1939\u193b\u6502;\u656a;\u6561;\u655e;\u653c;\u6524;\u651c\u0100ev\u0123\u1942bar\u803b\xa6\u40a6\u0200ceio\u1951\u1956\u195a\u1960r;\uc000\ud835\udcb7mi;\u604fm\u0100;e\u171a\u171cl\u0180;bh\u1968\u1969\u196b\u405c;\u69c5sub;\u67c8\u016c\u1974\u197el\u0100;e\u1979\u197a\u6022t\xbb\u197ap\u0180;Ee\u012f\u1985\u1987;\u6aae\u0100;q\u06dc\u06db\u0ce1\u19a7\0\u19e8\u1a11\u1a15\u1a32\0\u1a37\u1a50\0\0\u1ab4\0\0\u1ac1\0\0\u1b21\u1b2e\u1b4d\u1b52\0\u1bfd\0\u1c0c\u0180cpr\u19ad\u19b2\u19ddute;\u4107\u0300;abcds\u19bf\u19c0\u19c4\u19ca\u19d5\u19d9\u6229nd;\u6a44rcup;\u6a49\u0100au\u19cf\u19d2p;\u6a4bp;\u6a47ot;\u6a40;\uc000\u2229\ufe00\u0100eo\u19e2\u19e5t;\u6041\xee\u0693\u0200aeiu\u19f0\u19fb\u1a01\u1a05\u01f0\u19f5\0\u19f8s;\u6a4don;\u410ddil\u803b\xe7\u40e7rc;\u4109ps\u0100;s\u1a0c\u1a0d\u6a4cm;\u6a50ot;\u410b\u0180dmn\u1a1b\u1a20\u1a26il\u80bb\xb8\u01adptyv;\u69b2t\u8100\xa2;e\u1a2d\u1a2e\u40a2r\xe4\u01b2r;\uc000\ud835\udd20\u0180cei\u1a3d\u1a40\u1a4dy;\u4447ck\u0100;m\u1a47\u1a48\u6713ark\xbb\u1a48;\u43c7r\u0380;Ecefms\u1a5f\u1a60\u1a62\u1a6b\u1aa4\u1aaa\u1aae\u65cb;\u69c3\u0180;el\u1a69\u1a6a\u1a6d\u42c6q;\u6257e\u0261\u1a74\0\0\u1a88rrow\u0100lr\u1a7c\u1a81eft;\u61baight;\u61bb\u0280RSacd\u1a92\u1a94\u1a96\u1a9a\u1a9f\xbb\u0f47;\u64c8st;\u629birc;\u629aash;\u629dnint;\u6a10id;\u6aefcir;\u69c2ubs\u0100;u\u1abb\u1abc\u6663it\xbb\u1abc\u02ec\u1ac7\u1ad4\u1afa\0\u1b0aon\u0100;e\u1acd\u1ace\u403a\u0100;q\xc7\xc6\u026d\u1ad9\0\0\u1ae2a\u0100;t\u1ade\u1adf\u402c;\u4040\u0180;fl\u1ae8\u1ae9\u1aeb\u6201\xee\u1160e\u0100mx\u1af1\u1af6ent\xbb\u1ae9e\xf3\u024d\u01e7\u1afe\0\u1b07\u0100;d\u12bb\u1b02ot;\u6a6dn\xf4\u0246\u0180fry\u1b10\u1b14\u1b17;\uc000\ud835\udd54o\xe4\u0254\u8100\xa9;s\u0155\u1b1dr;\u6117\u0100ao\u1b25\u1b29rr;\u61b5ss;\u6717\u0100cu\u1b32\u1b37r;\uc000\ud835\udcb8\u0100bp\u1b3c\u1b44\u0100;e\u1b41\u1b42\u6acf;\u6ad1\u0100;e\u1b49\u1b4a\u6ad0;\u6ad2dot;\u62ef\u0380delprvw\u1b60\u1b6c\u1b77\u1b82\u1bac\u1bd4\u1bf9arr\u0100lr\u1b68\u1b6a;\u6938;\u6935\u0270\u1b72\0\0\u1b75r;\u62dec;\u62dfarr\u0100;p\u1b7f\u1b80\u61b6;\u693d\u0300;bcdos\u1b8f\u1b90\u1b96\u1ba1\u1ba5\u1ba8\u622arcap;\u6a48\u0100au\u1b9b\u1b9ep;\u6a46p;\u6a4aot;\u628dr;\u6a45;\uc000\u222a\ufe00\u0200alrv\u1bb5\u1bbf\u1bde\u1be3rr\u0100;m\u1bbc\u1bbd\u61b7;\u693cy\u0180evw\u1bc7\u1bd4\u1bd8q\u0270\u1bce\0\0\u1bd2re\xe3\u1b73u\xe3\u1b75ee;\u62ceedge;\u62cfen\u803b\xa4\u40a4earrow\u0100lr\u1bee\u1bf3eft\xbb\u1b80ight\xbb\u1bbde\xe4\u1bdd\u0100ci\u1c01\u1c07onin\xf4\u01f7nt;\u6231lcty;\u632d\u0980AHabcdefhijlorstuwz\u1c38\u1c3b\u1c3f\u1c5d\u1c69\u1c75\u1c8a\u1c9e\u1cac\u1cb7\u1cfb\u1cff\u1d0d\u1d7b\u1d91\u1dab\u1dbb\u1dc6\u1dcdr\xf2\u0381ar;\u6965\u0200glrs\u1c48\u1c4d\u1c52\u1c54ger;\u6020eth;\u6138\xf2\u1133h\u0100;v\u1c5a\u1c5b\u6010\xbb\u090a\u016b\u1c61\u1c67arow;\u690fa\xe3\u0315\u0100ay\u1c6e\u1c73ron;\u410f;\u4434\u0180;ao\u0332\u1c7c\u1c84\u0100gr\u02bf\u1c81r;\u61catseq;\u6a77\u0180glm\u1c91\u1c94\u1c98\u803b\xb0\u40b0ta;\u43b4ptyv;\u69b1\u0100ir\u1ca3\u1ca8sht;\u697f;\uc000\ud835\udd21ar\u0100lr\u1cb3\u1cb5\xbb\u08dc\xbb\u101e\u0280aegsv\u1cc2\u0378\u1cd6\u1cdc\u1ce0m\u0180;os\u0326\u1cca\u1cd4nd\u0100;s\u0326\u1cd1uit;\u6666amma;\u43ddin;\u62f2\u0180;io\u1ce7\u1ce8\u1cf8\u40f7de\u8100\xf7;o\u1ce7\u1cf0ntimes;\u62c7n\xf8\u1cf7cy;\u4452c\u026f\u1d06\0\0\u1d0arn;\u631eop;\u630d\u0280lptuw\u1d18\u1d1d\u1d22\u1d49\u1d55lar;\u4024f;\uc000\ud835\udd55\u0280;emps\u030b\u1d2d\u1d37\u1d3d\u1d42q\u0100;d\u0352\u1d33ot;\u6251inus;\u6238lus;\u6214quare;\u62a1blebarwedg\xe5\xfan\u0180adh\u112e\u1d5d\u1d67ownarrow\xf3\u1c83arpoon\u0100lr\u1d72\u1d76ef\xf4\u1cb4igh\xf4\u1cb6\u0162\u1d7f\u1d85karo\xf7\u0f42\u026f\u1d8a\0\0\u1d8ern;\u631fop;\u630c\u0180cot\u1d98\u1da3\u1da6\u0100ry\u1d9d\u1da1;\uc000\ud835\udcb9;\u4455l;\u69f6rok;\u4111\u0100dr\u1db0\u1db4ot;\u62f1i\u0100;f\u1dba\u1816\u65bf\u0100ah\u1dc0\u1dc3r\xf2\u0429a\xf2\u0fa6angle;\u69a6\u0100ci\u1dd2\u1dd5y;\u445fgrarr;\u67ff\u0900Dacdefglmnopqrstux\u1e01\u1e09\u1e19\u1e38\u0578\u1e3c\u1e49\u1e61\u1e7e\u1ea5\u1eaf\u1ebd\u1ee1\u1f2a\u1f37\u1f44\u1f4e\u1f5a\u0100Do\u1e06\u1d34o\xf4\u1c89\u0100cs\u1e0e\u1e14ute\u803b\xe9\u40e9ter;\u6a6e\u0200aioy\u1e22\u1e27\u1e31\u1e36ron;\u411br\u0100;c\u1e2d\u1e2e\u6256\u803b\xea\u40ealon;\u6255;\u444dot;\u4117\u0100Dr\u1e41\u1e45ot;\u6252;\uc000\ud835\udd22\u0180;rs\u1e50\u1e51\u1e57\u6a9aave\u803b\xe8\u40e8\u0100;d\u1e5c\u1e5d\u6a96ot;\u6a98\u0200;ils\u1e6a\u1e6b\u1e72\u1e74\u6a99nters;\u63e7;\u6113\u0100;d\u1e79\u1e7a\u6a95ot;\u6a97\u0180aps\u1e85\u1e89\u1e97cr;\u4113ty\u0180;sv\u1e92\u1e93\u1e95\u6205et\xbb\u1e93p\u01001;\u1e9d\u1ea4\u0133\u1ea1\u1ea3;\u6004;\u6005\u6003\u0100gs\u1eaa\u1eac;\u414bp;\u6002\u0100gp\u1eb4\u1eb8on;\u4119f;\uc000\ud835\udd56\u0180als\u1ec4\u1ece\u1ed2r\u0100;s\u1eca\u1ecb\u62d5l;\u69e3us;\u6a71i\u0180;lv\u1eda\u1edb\u1edf\u43b5on\xbb\u1edb;\u43f5\u0200csuv\u1eea\u1ef3\u1f0b\u1f23\u0100io\u1eef\u1e31rc\xbb\u1e2e\u0269\u1ef9\0\0\u1efb\xed\u0548ant\u0100gl\u1f02\u1f06tr\xbb\u1e5dess\xbb\u1e7a\u0180aei\u1f12\u1f16\u1f1als;\u403dst;\u625fv\u0100;D\u0235\u1f20D;\u6a78parsl;\u69e5\u0100Da\u1f2f\u1f33ot;\u6253rr;\u6971\u0180cdi\u1f3e\u1f41\u1ef8r;\u612fo\xf4\u0352\u0100ah\u1f49\u1f4b;\u43b7\u803b\xf0\u40f0\u0100mr\u1f53\u1f57l\u803b\xeb\u40ebo;\u60ac\u0180cip\u1f61\u1f64\u1f67l;\u4021s\xf4\u056e\u0100eo\u1f6c\u1f74ctatio\xee\u0559nential\xe5\u0579\u09e1\u1f92\0\u1f9e\0\u1fa1\u1fa7\0\0\u1fc6\u1fcc\0\u1fd3\0\u1fe6\u1fea\u2000\0\u2008\u205allingdotse\xf1\u1e44y;\u4444male;\u6640\u0180ilr\u1fad\u1fb3\u1fc1lig;\u8000\ufb03\u0269\u1fb9\0\0\u1fbdg;\u8000\ufb00ig;\u8000\ufb04;\uc000\ud835\udd23lig;\u8000\ufb01lig;\uc000fj\u0180alt\u1fd9\u1fdc\u1fe1t;\u666dig;\u8000\ufb02ns;\u65b1of;\u4192\u01f0\u1fee\0\u1ff3f;\uc000\ud835\udd57\u0100ak\u05bf\u1ff7\u0100;v\u1ffc\u1ffd\u62d4;\u6ad9artint;\u6a0d\u0100ao\u200c\u2055\u0100cs\u2011\u2052\u03b1\u201a\u2030\u2038\u2045\u2048\0\u2050\u03b2\u2022\u2025\u2027\u202a\u202c\0\u202e\u803b\xbd\u40bd;\u6153\u803b\xbc\u40bc;\u6155;\u6159;\u615b\u01b3\u2034\0\u2036;\u6154;\u6156\u02b4\u203e\u2041\0\0\u2043\u803b\xbe\u40be;\u6157;\u615c5;\u6158\u01b6\u204c\0\u204e;\u615a;\u615d8;\u615el;\u6044wn;\u6322cr;\uc000\ud835\udcbb\u0880Eabcdefgijlnorstv\u2082\u2089\u209f\u20a5\u20b0\u20b4\u20f0\u20f5\u20fa\u20ff\u2103\u2112\u2138\u0317\u213e\u2152\u219e\u0100;l\u064d\u2087;\u6a8c\u0180cmp\u2090\u2095\u209dute;\u41f5ma\u0100;d\u209c\u1cda\u43b3;\u6a86reve;\u411f\u0100iy\u20aa\u20aerc;\u411d;\u4433ot;\u4121\u0200;lqs\u063e\u0642\u20bd\u20c9\u0180;qs\u063e\u064c\u20c4lan\xf4\u0665\u0200;cdl\u0665\u20d2\u20d5\u20e5c;\u6aa9ot\u0100;o\u20dc\u20dd\u6a80\u0100;l\u20e2\u20e3\u6a82;\u6a84\u0100;e\u20ea\u20ed\uc000\u22db\ufe00s;\u6a94r;\uc000\ud835\udd24\u0100;g\u0673\u061bmel;\u6137cy;\u4453\u0200;Eaj\u065a\u210c\u210e\u2110;\u6a92;\u6aa5;\u6aa4\u0200Eaes\u211b\u211d\u2129\u2134;\u6269p\u0100;p\u2123\u2124\u6a8arox\xbb\u2124\u0100;q\u212e\u212f\u6a88\u0100;q\u212e\u211bim;\u62e7pf;\uc000\ud835\udd58\u0100ci\u2143\u2146r;\u610am\u0180;el\u066b\u214e\u2150;\u6a8e;\u6a90\u8300>;cdlqr\u05ee\u2160\u216a\u216e\u2173\u2179\u0100ci\u2165\u2167;\u6aa7r;\u6a7aot;\u62d7Par;\u6995uest;\u6a7c\u0280adels\u2184\u216a\u2190\u0656\u219b\u01f0\u2189\0\u218epro\xf8\u209er;\u6978q\u0100lq\u063f\u2196les\xf3\u2088i\xed\u066b\u0100en\u21a3\u21adrtneqq;\uc000\u2269\ufe00\xc5\u21aa\u0500Aabcefkosy\u21c4\u21c7\u21f1\u21f5\u21fa\u2218\u221d\u222f\u2268\u227dr\xf2\u03a0\u0200ilmr\u21d0\u21d4\u21d7\u21dbrs\xf0\u1484f\xbb\u2024il\xf4\u06a9\u0100dr\u21e0\u21e4cy;\u444a\u0180;cw\u08f4\u21eb\u21efir;\u6948;\u61adar;\u610firc;\u4125\u0180alr\u2201\u220e\u2213rts\u0100;u\u2209\u220a\u6665it\xbb\u220alip;\u6026con;\u62b9r;\uc000\ud835\udd25s\u0100ew\u2223\u2229arow;\u6925arow;\u6926\u0280amopr\u223a\u223e\u2243\u225e\u2263rr;\u61fftht;\u623bk\u0100lr\u2249\u2253eftarrow;\u61a9ightarrow;\u61aaf;\uc000\ud835\udd59bar;\u6015\u0180clt\u226f\u2274\u2278r;\uc000\ud835\udcbdas\xe8\u21f4rok;\u4127\u0100bp\u2282\u2287ull;\u6043hen\xbb\u1c5b\u0ae1\u22a3\0\u22aa\0\u22b8\u22c5\u22ce\0\u22d5\u22f3\0\0\u22f8\u2322\u2367\u2362\u237f\0\u2386\u23aa\u23b4cute\u803b\xed\u40ed\u0180;iy\u0771\u22b0\u22b5rc\u803b\xee\u40ee;\u4438\u0100cx\u22bc\u22bfy;\u4435cl\u803b\xa1\u40a1\u0100fr\u039f\u22c9;\uc000\ud835\udd26rave\u803b\xec\u40ec\u0200;ino\u073e\u22dd\u22e9\u22ee\u0100in\u22e2\u22e6nt;\u6a0ct;\u622dfin;\u69dcta;\u6129lig;\u4133\u0180aop\u22fe\u231a\u231d\u0180cgt\u2305\u2308\u2317r;\u412b\u0180elp\u071f\u230f\u2313in\xe5\u078ear\xf4\u0720h;\u4131f;\u62b7ed;\u41b5\u0280;cfot\u04f4\u232c\u2331\u233d\u2341are;\u6105in\u0100;t\u2338\u2339\u621eie;\u69dddo\xf4\u2319\u0280;celp\u0757\u234c\u2350\u235b\u2361al;\u62ba\u0100gr\u2355\u2359er\xf3\u1563\xe3\u234darhk;\u6a17rod;\u6a3c\u0200cgpt\u236f\u2372\u2376\u237by;\u4451on;\u412ff;\uc000\ud835\udd5aa;\u43b9uest\u803b\xbf\u40bf\u0100ci\u238a\u238fr;\uc000\ud835\udcben\u0280;Edsv\u04f4\u239b\u239d\u23a1\u04f3;\u62f9ot;\u62f5\u0100;v\u23a6\u23a7\u62f4;\u62f3\u0100;i\u0777\u23aelde;\u4129\u01eb\u23b8\0\u23bccy;\u4456l\u803b\xef\u40ef\u0300cfmosu\u23cc\u23d7\u23dc\u23e1\u23e7\u23f5\u0100iy\u23d1\u23d5rc;\u4135;\u4439r;\uc000\ud835\udd27ath;\u4237pf;\uc000\ud835\udd5b\u01e3\u23ec\0\u23f1r;\uc000\ud835\udcbfrcy;\u4458kcy;\u4454\u0400acfghjos\u240b\u2416\u2422\u2427\u242d\u2431\u2435\u243bppa\u0100;v\u2413\u2414\u43ba;\u43f0\u0100ey\u241b\u2420dil;\u4137;\u443ar;\uc000\ud835\udd28reen;\u4138cy;\u4445cy;\u445cpf;\uc000\ud835\udd5ccr;\uc000\ud835\udcc0\u0b80ABEHabcdefghjlmnoprstuv\u2470\u2481\u2486\u248d\u2491\u250e\u253d\u255a\u2580\u264e\u265e\u2665\u2679\u267d\u269a\u26b2\u26d8\u275d\u2768\u278b\u27c0\u2801\u2812\u0180art\u2477\u247a\u247cr\xf2\u09c6\xf2\u0395ail;\u691barr;\u690e\u0100;g\u0994\u248b;\u6a8bar;\u6962\u0963\u24a5\0\u24aa\0\u24b1\0\0\0\0\0\u24b5\u24ba\0\u24c6\u24c8\u24cd\0\u24f9ute;\u413amptyv;\u69b4ra\xee\u084cbda;\u43bbg\u0180;dl\u088e\u24c1\u24c3;\u6991\xe5\u088e;\u6a85uo\u803b\xab\u40abr\u0400;bfhlpst\u0899\u24de\u24e6\u24e9\u24eb\u24ee\u24f1\u24f5\u0100;f\u089d\u24e3s;\u691fs;\u691d\xeb\u2252p;\u61abl;\u6939im;\u6973l;\u61a2\u0180;ae\u24ff\u2500\u2504\u6aabil;\u6919\u0100;s\u2509\u250a\u6aad;\uc000\u2aad\ufe00\u0180abr\u2515\u2519\u251drr;\u690crk;\u6772\u0100ak\u2522\u252cc\u0100ek\u2528\u252a;\u407b;\u405b\u0100es\u2531\u2533;\u698bl\u0100du\u2539\u253b;\u698f;\u698d\u0200aeuy\u2546\u254b\u2556\u2558ron;\u413e\u0100di\u2550\u2554il;\u413c\xec\u08b0\xe2\u2529;\u443b\u0200cqrs\u2563\u2566\u256d\u257da;\u6936uo\u0100;r\u0e19\u1746\u0100du\u2572\u2577har;\u6967shar;\u694bh;\u61b2\u0280;fgqs\u258b\u258c\u0989\u25f3\u25ff\u6264t\u0280ahlrt\u2598\u25a4\u25b7\u25c2\u25e8rrow\u0100;t\u0899\u25a1a\xe9\u24f6arpoon\u0100du\u25af\u25b4own\xbb\u045ap\xbb\u0966eftarrows;\u61c7ight\u0180ahs\u25cd\u25d6\u25derrow\u0100;s\u08f4\u08a7arpoon\xf3\u0f98quigarro\xf7\u21f0hreetimes;\u62cb\u0180;qs\u258b\u0993\u25falan\xf4\u09ac\u0280;cdgs\u09ac\u260a\u260d\u261d\u2628c;\u6aa8ot\u0100;o\u2614\u2615\u6a7f\u0100;r\u261a\u261b\u6a81;\u6a83\u0100;e\u2622\u2625\uc000\u22da\ufe00s;\u6a93\u0280adegs\u2633\u2639\u263d\u2649\u264bppro\xf8\u24c6ot;\u62d6q\u0100gq\u2643\u2645\xf4\u0989gt\xf2\u248c\xf4\u099bi\xed\u09b2\u0180ilr\u2655\u08e1\u265asht;\u697c;\uc000\ud835\udd29\u0100;E\u099c\u2663;\u6a91\u0161\u2669\u2676r\u0100du\u25b2\u266e\u0100;l\u0965\u2673;\u696alk;\u6584cy;\u4459\u0280;acht\u0a48\u2688\u268b\u2691\u2696r\xf2\u25c1orne\xf2\u1d08ard;\u696bri;\u65fa\u0100io\u269f\u26a4dot;\u4140ust\u0100;a\u26ac\u26ad\u63b0che\xbb\u26ad\u0200Eaes\u26bb\u26bd\u26c9\u26d4;\u6268p\u0100;p\u26c3\u26c4\u6a89rox\xbb\u26c4\u0100;q\u26ce\u26cf\u6a87\u0100;q\u26ce\u26bbim;\u62e6\u0400abnoptwz\u26e9\u26f4\u26f7\u271a\u272f\u2741\u2747\u2750\u0100nr\u26ee\u26f1g;\u67ecr;\u61fdr\xeb\u08c1g\u0180lmr\u26ff\u270d\u2714eft\u0100ar\u09e6\u2707ight\xe1\u09f2apsto;\u67fcight\xe1\u09fdparrow\u0100lr\u2725\u2729ef\xf4\u24edight;\u61ac\u0180afl\u2736\u2739\u273dr;\u6985;\uc000\ud835\udd5dus;\u6a2dimes;\u6a34\u0161\u274b\u274fst;\u6217\xe1\u134e\u0180;ef\u2757\u2758\u1800\u65cange\xbb\u2758ar\u0100;l\u2764\u2765\u4028t;\u6993\u0280achmt\u2773\u2776\u277c\u2785\u2787r\xf2\u08a8orne\xf2\u1d8car\u0100;d\u0f98\u2783;\u696d;\u600eri;\u62bf\u0300achiqt\u2798\u279d\u0a40\u27a2\u27ae\u27bbquo;\u6039r;\uc000\ud835\udcc1m\u0180;eg\u09b2\u27aa\u27ac;\u6a8d;\u6a8f\u0100bu\u252a\u27b3o\u0100;r\u0e1f\u27b9;\u601arok;\u4142\u8400<;cdhilqr\u082b\u27d2\u2639\u27dc\u27e0\u27e5\u27ea\u27f0\u0100ci\u27d7\u27d9;\u6aa6r;\u6a79re\xe5\u25f2mes;\u62c9arr;\u6976uest;\u6a7b\u0100Pi\u27f5\u27f9ar;\u6996\u0180;ef\u2800\u092d\u181b\u65c3r\u0100du\u2807\u280dshar;\u694ahar;\u6966\u0100en\u2817\u2821rtneqq;\uc000\u2268\ufe00\xc5\u281e\u0700Dacdefhilnopsu\u2840\u2845\u2882\u288e\u2893\u28a0\u28a5\u28a8\u28da\u28e2\u28e4\u0a83\u28f3\u2902Dot;\u623a\u0200clpr\u284e\u2852\u2863\u287dr\u803b\xaf\u40af\u0100et\u2857\u2859;\u6642\u0100;e\u285e\u285f\u6720se\xbb\u285f\u0100;s\u103b\u2868to\u0200;dlu\u103b\u2873\u2877\u287bow\xee\u048cef\xf4\u090f\xf0\u13d1ker;\u65ae\u0100oy\u2887\u288cmma;\u6a29;\u443cash;\u6014asuredangle\xbb\u1626r;\uc000\ud835\udd2ao;\u6127\u0180cdn\u28af\u28b4\u28c9ro\u803b\xb5\u40b5\u0200;acd\u1464\u28bd\u28c0\u28c4s\xf4\u16a7ir;\u6af0ot\u80bb\xb7\u01b5us\u0180;bd\u28d2\u1903\u28d3\u6212\u0100;u\u1d3c\u28d8;\u6a2a\u0163\u28de\u28e1p;\u6adb\xf2\u2212\xf0\u0a81\u0100dp\u28e9\u28eeels;\u62a7f;\uc000\ud835\udd5e\u0100ct\u28f8\u28fdr;\uc000\ud835\udcc2pos\xbb\u159d\u0180;lm\u2909\u290a\u290d\u43bctimap;\u62b8\u0c00GLRVabcdefghijlmoprstuvw\u2942\u2953\u297e\u2989\u2998\u29da\u29e9\u2a15\u2a1a\u2a58\u2a5d\u2a83\u2a95\u2aa4\u2aa8\u2b04\u2b07\u2b44\u2b7f\u2bae\u2c34\u2c67\u2c7c\u2ce9\u0100gt\u2947\u294b;\uc000\u22d9\u0338\u0100;v\u2950\u0bcf\uc000\u226b\u20d2\u0180elt\u295a\u2972\u2976ft\u0100ar\u2961\u2967rrow;\u61cdightarrow;\u61ce;\uc000\u22d8\u0338\u0100;v\u297b\u0c47\uc000\u226a\u20d2ightarrow;\u61cf\u0100Dd\u298e\u2993ash;\u62afash;\u62ae\u0280bcnpt\u29a3\u29a7\u29ac\u29b1\u29ccla\xbb\u02deute;\u4144g;\uc000\u2220\u20d2\u0280;Eiop\u0d84\u29bc\u29c0\u29c5\u29c8;\uc000\u2a70\u0338d;\uc000\u224b\u0338s;\u4149ro\xf8\u0d84ur\u0100;a\u29d3\u29d4\u666el\u0100;s\u29d3\u0b38\u01f3\u29df\0\u29e3p\u80bb\xa0\u0b37mp\u0100;e\u0bf9\u0c00\u0280aeouy\u29f4\u29fe\u2a03\u2a10\u2a13\u01f0\u29f9\0\u29fb;\u6a43on;\u4148dil;\u4146ng\u0100;d\u0d7e\u2a0aot;\uc000\u2a6d\u0338p;\u6a42;\u443dash;\u6013\u0380;Aadqsx\u0b92\u2a29\u2a2d\u2a3b\u2a41\u2a45\u2a50rr;\u61d7r\u0100hr\u2a33\u2a36k;\u6924\u0100;o\u13f2\u13f0ot;\uc000\u2250\u0338ui\xf6\u0b63\u0100ei\u2a4a\u2a4ear;\u6928\xed\u0b98ist\u0100;s\u0ba0\u0b9fr;\uc000\ud835\udd2b\u0200Eest\u0bc5\u2a66\u2a79\u2a7c\u0180;qs\u0bbc\u2a6d\u0be1\u0180;qs\u0bbc\u0bc5\u2a74lan\xf4\u0be2i\xed\u0bea\u0100;r\u0bb6\u2a81\xbb\u0bb7\u0180Aap\u2a8a\u2a8d\u2a91r\xf2\u2971rr;\u61aear;\u6af2\u0180;sv\u0f8d\u2a9c\u0f8c\u0100;d\u2aa1\u2aa2\u62fc;\u62facy;\u445a\u0380AEadest\u2ab7\u2aba\u2abe\u2ac2\u2ac5\u2af6\u2af9r\xf2\u2966;\uc000\u2266\u0338rr;\u619ar;\u6025\u0200;fqs\u0c3b\u2ace\u2ae3\u2aeft\u0100ar\u2ad4\u2ad9rro\xf7\u2ac1ightarro\xf7\u2a90\u0180;qs\u0c3b\u2aba\u2aealan\xf4\u0c55\u0100;s\u0c55\u2af4\xbb\u0c36i\xed\u0c5d\u0100;r\u0c35\u2afei\u0100;e\u0c1a\u0c25i\xe4\u0d90\u0100pt\u2b0c\u2b11f;\uc000\ud835\udd5f\u8180\xac;in\u2b19\u2b1a\u2b36\u40acn\u0200;Edv\u0b89\u2b24\u2b28\u2b2e;\uc000\u22f9\u0338ot;\uc000\u22f5\u0338\u01e1\u0b89\u2b33\u2b35;\u62f7;\u62f6i\u0100;v\u0cb8\u2b3c\u01e1\u0cb8\u2b41\u2b43;\u62fe;\u62fd\u0180aor\u2b4b\u2b63\u2b69r\u0200;ast\u0b7b\u2b55\u2b5a\u2b5flle\xec\u0b7bl;\uc000\u2afd\u20e5;\uc000\u2202\u0338lint;\u6a14\u0180;ce\u0c92\u2b70\u2b73u\xe5\u0ca5\u0100;c\u0c98\u2b78\u0100;e\u0c92\u2b7d\xf1\u0c98\u0200Aait\u2b88\u2b8b\u2b9d\u2ba7r\xf2\u2988rr\u0180;cw\u2b94\u2b95\u2b99\u619b;\uc000\u2933\u0338;\uc000\u219d\u0338ghtarrow\xbb\u2b95ri\u0100;e\u0ccb\u0cd6\u0380chimpqu\u2bbd\u2bcd\u2bd9\u2b04\u0b78\u2be4\u2bef\u0200;cer\u0d32\u2bc6\u0d37\u2bc9u\xe5\u0d45;\uc000\ud835\udcc3ort\u026d\u2b05\0\0\u2bd6ar\xe1\u2b56m\u0100;e\u0d6e\u2bdf\u0100;q\u0d74\u0d73su\u0100bp\u2beb\u2bed\xe5\u0cf8\xe5\u0d0b\u0180bcp\u2bf6\u2c11\u2c19\u0200;Ees\u2bff\u2c00\u0d22\u2c04\u6284;\uc000\u2ac5\u0338et\u0100;e\u0d1b\u2c0bq\u0100;q\u0d23\u2c00c\u0100;e\u0d32\u2c17\xf1\u0d38\u0200;Ees\u2c22\u2c23\u0d5f\u2c27\u6285;\uc000\u2ac6\u0338et\u0100;e\u0d58\u2c2eq\u0100;q\u0d60\u2c23\u0200gilr\u2c3d\u2c3f\u2c45\u2c47\xec\u0bd7lde\u803b\xf1\u40f1\xe7\u0c43iangle\u0100lr\u2c52\u2c5ceft\u0100;e\u0c1a\u2c5a\xf1\u0c26ight\u0100;e\u0ccb\u2c65\xf1\u0cd7\u0100;m\u2c6c\u2c6d\u43bd\u0180;es\u2c74\u2c75\u2c79\u4023ro;\u6116p;\u6007\u0480DHadgilrs\u2c8f\u2c94\u2c99\u2c9e\u2ca3\u2cb0\u2cb6\u2cd3\u2ce3ash;\u62adarr;\u6904p;\uc000\u224d\u20d2ash;\u62ac\u0100et\u2ca8\u2cac;\uc000\u2265\u20d2;\uc000>\u20d2nfin;\u69de\u0180Aet\u2cbd\u2cc1\u2cc5rr;\u6902;\uc000\u2264\u20d2\u0100;r\u2cca\u2ccd\uc000<\u20d2ie;\uc000\u22b4\u20d2\u0100At\u2cd8\u2cdcrr;\u6903rie;\uc000\u22b5\u20d2im;\uc000\u223c\u20d2\u0180Aan\u2cf0\u2cf4\u2d02rr;\u61d6r\u0100hr\u2cfa\u2cfdk;\u6923\u0100;o\u13e7\u13e5ear;\u6927\u1253\u1a95\0\0\0\0\0\0\0\0\0\0\0\0\0\u2d2d\0\u2d38\u2d48\u2d60\u2d65\u2d72\u2d84\u1b07\0\0\u2d8d\u2dab\0\u2dc8\u2dce\0\u2ddc\u2e19\u2e2b\u2e3e\u2e43\u0100cs\u2d31\u1a97ute\u803b\xf3\u40f3\u0100iy\u2d3c\u2d45r\u0100;c\u1a9e\u2d42\u803b\xf4\u40f4;\u443e\u0280abios\u1aa0\u2d52\u2d57\u01c8\u2d5alac;\u4151v;\u6a38old;\u69bclig;\u4153\u0100cr\u2d69\u2d6dir;\u69bf;\uc000\ud835\udd2c\u036f\u2d79\0\0\u2d7c\0\u2d82n;\u42dbave\u803b\xf2\u40f2;\u69c1\u0100bm\u2d88\u0df4ar;\u69b5\u0200acit\u2d95\u2d98\u2da5\u2da8r\xf2\u1a80\u0100ir\u2d9d\u2da0r;\u69beoss;\u69bbn\xe5\u0e52;\u69c0\u0180aei\u2db1\u2db5\u2db9cr;\u414dga;\u43c9\u0180cdn\u2dc0\u2dc5\u01cdron;\u43bf;\u69b6pf;\uc000\ud835\udd60\u0180ael\u2dd4\u2dd7\u01d2r;\u69b7rp;\u69b9\u0380;adiosv\u2dea\u2deb\u2dee\u2e08\u2e0d\u2e10\u2e16\u6228r\xf2\u1a86\u0200;efm\u2df7\u2df8\u2e02\u2e05\u6a5dr\u0100;o\u2dfe\u2dff\u6134f\xbb\u2dff\u803b\xaa\u40aa\u803b\xba\u40bagof;\u62b6r;\u6a56lope;\u6a57;\u6a5b\u0180clo\u2e1f\u2e21\u2e27\xf2\u2e01ash\u803b\xf8\u40f8l;\u6298i\u016c\u2e2f\u2e34de\u803b\xf5\u40f5es\u0100;a\u01db\u2e3as;\u6a36ml\u803b\xf6\u40f6bar;\u633d\u0ae1\u2e5e\0\u2e7d\0\u2e80\u2e9d\0\u2ea2\u2eb9\0\0\u2ecb\u0e9c\0\u2f13\0\0\u2f2b\u2fbc\0\u2fc8r\u0200;ast\u0403\u2e67\u2e72\u0e85\u8100\xb6;l\u2e6d\u2e6e\u40b6le\xec\u0403\u0269\u2e78\0\0\u2e7bm;\u6af3;\u6afdy;\u443fr\u0280cimpt\u2e8b\u2e8f\u2e93\u1865\u2e97nt;\u4025od;\u402eil;\u6030enk;\u6031r;\uc000\ud835\udd2d\u0180imo\u2ea8\u2eb0\u2eb4\u0100;v\u2ead\u2eae\u43c6;\u43d5ma\xf4\u0a76ne;\u660e\u0180;tv\u2ebf\u2ec0\u2ec8\u43c0chfork\xbb\u1ffd;\u43d6\u0100au\u2ecf\u2edfn\u0100ck\u2ed5\u2eddk\u0100;h\u21f4\u2edb;\u610e\xf6\u21f4s\u0480;abcdemst\u2ef3\u2ef4\u1908\u2ef9\u2efd\u2f04\u2f06\u2f0a\u2f0e\u402bcir;\u6a23ir;\u6a22\u0100ou\u1d40\u2f02;\u6a25;\u6a72n\u80bb\xb1\u0e9dim;\u6a26wo;\u6a27\u0180ipu\u2f19\u2f20\u2f25ntint;\u6a15f;\uc000\ud835\udd61nd\u803b\xa3\u40a3\u0500;Eaceinosu\u0ec8\u2f3f\u2f41\u2f44\u2f47\u2f81\u2f89\u2f92\u2f7e\u2fb6;\u6ab3p;\u6ab7u\xe5\u0ed9\u0100;c\u0ece\u2f4c\u0300;acens\u0ec8\u2f59\u2f5f\u2f66\u2f68\u2f7eppro\xf8\u2f43urlye\xf1\u0ed9\xf1\u0ece\u0180aes\u2f6f\u2f76\u2f7approx;\u6ab9qq;\u6ab5im;\u62e8i\xed\u0edfme\u0100;s\u2f88\u0eae\u6032\u0180Eas\u2f78\u2f90\u2f7a\xf0\u2f75\u0180dfp\u0eec\u2f99\u2faf\u0180als\u2fa0\u2fa5\u2faalar;\u632eine;\u6312urf;\u6313\u0100;t\u0efb\u2fb4\xef\u0efbrel;\u62b0\u0100ci\u2fc0\u2fc5r;\uc000\ud835\udcc5;\u43c8ncsp;\u6008\u0300fiopsu\u2fda\u22e2\u2fdf\u2fe5\u2feb\u2ff1r;\uc000\ud835\udd2epf;\uc000\ud835\udd62rime;\u6057cr;\uc000\ud835\udcc6\u0180aeo\u2ff8\u3009\u3013t\u0100ei\u2ffe\u3005rnion\xf3\u06b0nt;\u6a16st\u0100;e\u3010\u3011\u403f\xf1\u1f19\xf4\u0f14\u0a80ABHabcdefhilmnoprstux\u3040\u3051\u3055\u3059\u30e0\u310e\u312b\u3147\u3162\u3172\u318e\u3206\u3215\u3224\u3229\u3258\u326e\u3272\u3290\u32b0\u32b7\u0180art\u3047\u304a\u304cr\xf2\u10b3\xf2\u03ddail;\u691car\xf2\u1c65ar;\u6964\u0380cdenqrt\u3068\u3075\u3078\u307f\u308f\u3094\u30cc\u0100eu\u306d\u3071;\uc000\u223d\u0331te;\u4155i\xe3\u116emptyv;\u69b3g\u0200;del\u0fd1\u3089\u308b\u308d;\u6992;\u69a5\xe5\u0fd1uo\u803b\xbb\u40bbr\u0580;abcfhlpstw\u0fdc\u30ac\u30af\u30b7\u30b9\u30bc\u30be\u30c0\u30c3\u30c7\u30cap;\u6975\u0100;f\u0fe0\u30b4s;\u6920;\u6933s;\u691e\xeb\u225d\xf0\u272el;\u6945im;\u6974l;\u61a3;\u619d\u0100ai\u30d1\u30d5il;\u691ao\u0100;n\u30db\u30dc\u6236al\xf3\u0f1e\u0180abr\u30e7\u30ea\u30eer\xf2\u17e5rk;\u6773\u0100ak\u30f3\u30fdc\u0100ek\u30f9\u30fb;\u407d;\u405d\u0100es\u3102\u3104;\u698cl\u0100du\u310a\u310c;\u698e;\u6990\u0200aeuy\u3117\u311c\u3127\u3129ron;\u4159\u0100di\u3121\u3125il;\u4157\xec\u0ff2\xe2\u30fa;\u4440\u0200clqs\u3134\u3137\u313d\u3144a;\u6937dhar;\u6969uo\u0100;r\u020e\u020dh;\u61b3\u0180acg\u314e\u315f\u0f44l\u0200;ips\u0f78\u3158\u315b\u109cn\xe5\u10bbar\xf4\u0fa9t;\u65ad\u0180ilr\u3169\u1023\u316esht;\u697d;\uc000\ud835\udd2f\u0100ao\u3177\u3186r\u0100du\u317d\u317f\xbb\u047b\u0100;l\u1091\u3184;\u696c\u0100;v\u318b\u318c\u43c1;\u43f1\u0180gns\u3195\u31f9\u31fcht\u0300ahlrst\u31a4\u31b0\u31c2\u31d8\u31e4\u31eerrow\u0100;t\u0fdc\u31ada\xe9\u30c8arpoon\u0100du\u31bb\u31bfow\xee\u317ep\xbb\u1092eft\u0100ah\u31ca\u31d0rrow\xf3\u0feaarpoon\xf3\u0551ightarrows;\u61c9quigarro\xf7\u30cbhreetimes;\u62ccg;\u42daingdotse\xf1\u1f32\u0180ahm\u320d\u3210\u3213r\xf2\u0feaa\xf2\u0551;\u600foust\u0100;a\u321e\u321f\u63b1che\xbb\u321fmid;\u6aee\u0200abpt\u3232\u323d\u3240\u3252\u0100nr\u3237\u323ag;\u67edr;\u61fer\xeb\u1003\u0180afl\u3247\u324a\u324er;\u6986;\uc000\ud835\udd63us;\u6a2eimes;\u6a35\u0100ap\u325d\u3267r\u0100;g\u3263\u3264\u4029t;\u6994olint;\u6a12ar\xf2\u31e3\u0200achq\u327b\u3280\u10bc\u3285quo;\u603ar;\uc000\ud835\udcc7\u0100bu\u30fb\u328ao\u0100;r\u0214\u0213\u0180hir\u3297\u329b\u32a0re\xe5\u31f8mes;\u62cai\u0200;efl\u32aa\u1059\u1821\u32ab\u65b9tri;\u69celuhar;\u6968;\u611e\u0d61\u32d5\u32db\u32df\u332c\u3338\u3371\0\u337a\u33a4\0\0\u33ec\u33f0\0\u3428\u3448\u345a\u34ad\u34b1\u34ca\u34f1\0\u3616\0\0\u3633cute;\u415bqu\xef\u27ba\u0500;Eaceinpsy\u11ed\u32f3\u32f5\u32ff\u3302\u330b\u330f\u331f\u3326\u3329;\u6ab4\u01f0\u32fa\0\u32fc;\u6ab8on;\u4161u\xe5\u11fe\u0100;d\u11f3\u3307il;\u415frc;\u415d\u0180Eas\u3316\u3318\u331b;\u6ab6p;\u6abaim;\u62e9olint;\u6a13i\xed\u1204;\u4441ot\u0180;be\u3334\u1d47\u3335\u62c5;\u6a66\u0380Aacmstx\u3346\u334a\u3357\u335b\u335e\u3363\u336drr;\u61d8r\u0100hr\u3350\u3352\xeb\u2228\u0100;o\u0a36\u0a34t\u803b\xa7\u40a7i;\u403bwar;\u6929m\u0100in\u3369\xf0nu\xf3\xf1t;\u6736r\u0100;o\u3376\u2055\uc000\ud835\udd30\u0200acoy\u3382\u3386\u3391\u33a0rp;\u666f\u0100hy\u338b\u338fcy;\u4449;\u4448rt\u026d\u3399\0\0\u339ci\xe4\u1464ara\xec\u2e6f\u803b\xad\u40ad\u0100gm\u33a8\u33b4ma\u0180;fv\u33b1\u33b2\u33b2\u43c3;\u43c2\u0400;deglnpr\u12ab\u33c5\u33c9\u33ce\u33d6\u33de\u33e1\u33e6ot;\u6a6a\u0100;q\u12b1\u12b0\u0100;E\u33d3\u33d4\u6a9e;\u6aa0\u0100;E\u33db\u33dc\u6a9d;\u6a9fe;\u6246lus;\u6a24arr;\u6972ar\xf2\u113d\u0200aeit\u33f8\u3408\u340f\u3417\u0100ls\u33fd\u3404lsetm\xe9\u336ahp;\u6a33parsl;\u69e4\u0100dl\u1463\u3414e;\u6323\u0100;e\u341c\u341d\u6aaa\u0100;s\u3422\u3423\u6aac;\uc000\u2aac\ufe00\u0180flp\u342e\u3433\u3442tcy;\u444c\u0100;b\u3438\u3439\u402f\u0100;a\u343e\u343f\u69c4r;\u633ff;\uc000\ud835\udd64a\u0100dr\u344d\u0402es\u0100;u\u3454\u3455\u6660it\xbb\u3455\u0180csu\u3460\u3479\u349f\u0100au\u3465\u346fp\u0100;s\u1188\u346b;\uc000\u2293\ufe00p\u0100;s\u11b4\u3475;\uc000\u2294\ufe00u\u0100bp\u347f\u348f\u0180;es\u1197\u119c\u3486et\u0100;e\u1197\u348d\xf1\u119d\u0180;es\u11a8\u11ad\u3496et\u0100;e\u11a8\u349d\xf1\u11ae\u0180;af\u117b\u34a6\u05b0r\u0165\u34ab\u05b1\xbb\u117car\xf2\u1148\u0200cemt\u34b9\u34be\u34c2\u34c5r;\uc000\ud835\udcc8tm\xee\xf1i\xec\u3415ar\xe6\u11be\u0100ar\u34ce\u34d5r\u0100;f\u34d4\u17bf\u6606\u0100an\u34da\u34edight\u0100ep\u34e3\u34eapsilo\xee\u1ee0h\xe9\u2eafs\xbb\u2852\u0280bcmnp\u34fb\u355e\u1209\u358b\u358e\u0480;Edemnprs\u350e\u350f\u3511\u3515\u351e\u3523\u352c\u3531\u3536\u6282;\u6ac5ot;\u6abd\u0100;d\u11da\u351aot;\u6ac3ult;\u6ac1\u0100Ee\u3528\u352a;\u6acb;\u628alus;\u6abfarr;\u6979\u0180eiu\u353d\u3552\u3555t\u0180;en\u350e\u3545\u354bq\u0100;q\u11da\u350feq\u0100;q\u352b\u3528m;\u6ac7\u0100bp\u355a\u355c;\u6ad5;\u6ad3c\u0300;acens\u11ed\u356c\u3572\u3579\u357b\u3326ppro\xf8\u32faurlye\xf1\u11fe\xf1\u11f3\u0180aes\u3582\u3588\u331bppro\xf8\u331aq\xf1\u3317g;\u666a\u0680123;Edehlmnps\u35a9\u35ac\u35af\u121c\u35b2\u35b4\u35c0\u35c9\u35d5\u35da\u35df\u35e8\u35ed\u803b\xb9\u40b9\u803b\xb2\u40b2\u803b\xb3\u40b3;\u6ac6\u0100os\u35b9\u35bct;\u6abeub;\u6ad8\u0100;d\u1222\u35c5ot;\u6ac4s\u0100ou\u35cf\u35d2l;\u67c9b;\u6ad7arr;\u697bult;\u6ac2\u0100Ee\u35e4\u35e6;\u6acc;\u628blus;\u6ac0\u0180eiu\u35f4\u3609\u360ct\u0180;en\u121c\u35fc\u3602q\u0100;q\u1222\u35b2eq\u0100;q\u35e7\u35e4m;\u6ac8\u0100bp\u3611\u3613;\u6ad4;\u6ad6\u0180Aan\u361c\u3620\u362drr;\u61d9r\u0100hr\u3626\u3628\xeb\u222e\u0100;o\u0a2b\u0a29war;\u692alig\u803b\xdf\u40df\u0be1\u3651\u365d\u3660\u12ce\u3673\u3679\0\u367e\u36c2\0\0\0\0\0\u36db\u3703\0\u3709\u376c\0\0\0\u3787\u0272\u3656\0\0\u365bget;\u6316;\u43c4r\xeb\u0e5f\u0180aey\u3666\u366b\u3670ron;\u4165dil;\u4163;\u4442lrec;\u6315r;\uc000\ud835\udd31\u0200eiko\u3686\u369d\u36b5\u36bc\u01f2\u368b\0\u3691e\u01004f\u1284\u1281a\u0180;sv\u3698\u3699\u369b\u43b8ym;\u43d1\u0100cn\u36a2\u36b2k\u0100as\u36a8\u36aeppro\xf8\u12c1im\xbb\u12acs\xf0\u129e\u0100as\u36ba\u36ae\xf0\u12c1rn\u803b\xfe\u40fe\u01ec\u031f\u36c6\u22e7es\u8180\xd7;bd\u36cf\u36d0\u36d8\u40d7\u0100;a\u190f\u36d5r;\u6a31;\u6a30\u0180eps\u36e1\u36e3\u3700\xe1\u2a4d\u0200;bcf\u0486\u36ec\u36f0\u36f4ot;\u6336ir;\u6af1\u0100;o\u36f9\u36fc\uc000\ud835\udd65rk;\u6ada\xe1\u3362rime;\u6034\u0180aip\u370f\u3712\u3764d\xe5\u1248\u0380adempst\u3721\u374d\u3740\u3751\u3757\u375c\u375fngle\u0280;dlqr\u3730\u3731\u3736\u3740\u3742\u65b5own\xbb\u1dbbeft\u0100;e\u2800\u373e\xf1\u092e;\u625cight\u0100;e\u32aa\u374b\xf1\u105aot;\u65ecinus;\u6a3alus;\u6a39b;\u69cdime;\u6a3bezium;\u63e2\u0180cht\u3772\u377d\u3781\u0100ry\u3777\u377b;\uc000\ud835\udcc9;\u4446cy;\u445brok;\u4167\u0100io\u378b\u378ex\xf4\u1777head\u0100lr\u3797\u37a0eftarro\xf7\u084fightarrow\xbb\u0f5d\u0900AHabcdfghlmoprstuw\u37d0\u37d3\u37d7\u37e4\u37f0\u37fc\u380e\u381c\u3823\u3834\u3851\u385d\u386b\u38a9\u38cc\u38d2\u38ea\u38f6r\xf2\u03edar;\u6963\u0100cr\u37dc\u37e2ute\u803b\xfa\u40fa\xf2\u1150r\u01e3\u37ea\0\u37edy;\u445eve;\u416d\u0100iy\u37f5\u37farc\u803b\xfb\u40fb;\u4443\u0180abh\u3803\u3806\u380br\xf2\u13adlac;\u4171a\xf2\u13c3\u0100ir\u3813\u3818sht;\u697e;\uc000\ud835\udd32rave\u803b\xf9\u40f9\u0161\u3827\u3831r\u0100lr\u382c\u382e\xbb\u0957\xbb\u1083lk;\u6580\u0100ct\u3839\u384d\u026f\u383f\0\0\u384arn\u0100;e\u3845\u3846\u631cr\xbb\u3846op;\u630fri;\u65f8\u0100al\u3856\u385acr;\u416b\u80bb\xa8\u0349\u0100gp\u3862\u3866on;\u4173f;\uc000\ud835\udd66\u0300adhlsu\u114b\u3878\u387d\u1372\u3891\u38a0own\xe1\u13b3arpoon\u0100lr\u3888\u388cef\xf4\u382digh\xf4\u382fi\u0180;hl\u3899\u389a\u389c\u43c5\xbb\u13faon\xbb\u389aparrows;\u61c8\u0180cit\u38b0\u38c4\u38c8\u026f\u38b6\0\0\u38c1rn\u0100;e\u38bc\u38bd\u631dr\xbb\u38bdop;\u630eng;\u416fri;\u65f9cr;\uc000\ud835\udcca\u0180dir\u38d9\u38dd\u38e2ot;\u62f0lde;\u4169i\u0100;f\u3730\u38e8\xbb\u1813\u0100am\u38ef\u38f2r\xf2\u38a8l\u803b\xfc\u40fcangle;\u69a7\u0780ABDacdeflnoprsz\u391c\u391f\u3929\u392d\u39b5\u39b8\u39bd\u39df\u39e4\u39e8\u39f3\u39f9\u39fd\u3a01\u3a20r\xf2\u03f7ar\u0100;v\u3926\u3927\u6ae8;\u6ae9as\xe8\u03e1\u0100nr\u3932\u3937grt;\u699c\u0380eknprst\u34e3\u3946\u394b\u3952\u395d\u3964\u3996app\xe1\u2415othin\xe7\u1e96\u0180hir\u34eb\u2ec8\u3959op\xf4\u2fb5\u0100;h\u13b7\u3962\xef\u318d\u0100iu\u3969\u396dgm\xe1\u33b3\u0100bp\u3972\u3984setneq\u0100;q\u397d\u3980\uc000\u228a\ufe00;\uc000\u2acb\ufe00setneq\u0100;q\u398f\u3992\uc000\u228b\ufe00;\uc000\u2acc\ufe00\u0100hr\u399b\u399fet\xe1\u369ciangle\u0100lr\u39aa\u39afeft\xbb\u0925ight\xbb\u1051y;\u4432ash\xbb\u1036\u0180elr\u39c4\u39d2\u39d7\u0180;be\u2dea\u39cb\u39cfar;\u62bbq;\u625alip;\u62ee\u0100bt\u39dc\u1468a\xf2\u1469r;\uc000\ud835\udd33tr\xe9\u39aesu\u0100bp\u39ef\u39f1\xbb\u0d1c\xbb\u0d59pf;\uc000\ud835\udd67ro\xf0\u0efbtr\xe9\u39b4\u0100cu\u3a06\u3a0br;\uc000\ud835\udccb\u0100bp\u3a10\u3a18n\u0100Ee\u3980\u3a16\xbb\u397en\u0100Ee\u3992\u3a1e\xbb\u3990igzag;\u699a\u0380cefoprs\u3a36\u3a3b\u3a56\u3a5b\u3a54\u3a61\u3a6airc;\u4175\u0100di\u3a40\u3a51\u0100bg\u3a45\u3a49ar;\u6a5fe\u0100;q\u15fa\u3a4f;\u6259erp;\u6118r;\uc000\ud835\udd34pf;\uc000\ud835\udd68\u0100;e\u1479\u3a66at\xe8\u1479cr;\uc000\ud835\udccc\u0ae3\u178e\u3a87\0\u3a8b\0\u3a90\u3a9b\0\0\u3a9d\u3aa8\u3aab\u3aaf\0\0\u3ac3\u3ace\0\u3ad8\u17dc\u17dftr\xe9\u17d1r;\uc000\ud835\udd35\u0100Aa\u3a94\u3a97r\xf2\u03c3r\xf2\u09f6;\u43be\u0100Aa\u3aa1\u3aa4r\xf2\u03b8r\xf2\u09eba\xf0\u2713is;\u62fb\u0180dpt\u17a4\u3ab5\u3abe\u0100fl\u3aba\u17a9;\uc000\ud835\udd69im\xe5\u17b2\u0100Aa\u3ac7\u3acar\xf2\u03cer\xf2\u0a01\u0100cq\u3ad2\u17b8r;\uc000\ud835\udccd\u0100pt\u17d6\u3adcr\xe9\u17d4\u0400acefiosu\u3af0\u3afd\u3b08\u3b0c\u3b11\u3b15\u3b1b\u3b21c\u0100uy\u3af6\u3afbte\u803b\xfd\u40fd;\u444f\u0100iy\u3b02\u3b06rc;\u4177;\u444bn\u803b\xa5\u40a5r;\uc000\ud835\udd36cy;\u4457pf;\uc000\ud835\udd6acr;\uc000\ud835\udcce\u0100cm\u3b26\u3b29y;\u444el\u803b\xff\u40ff\u0500acdefhiosw\u3b42\u3b48\u3b54\u3b58\u3b64\u3b69\u3b6d\u3b74\u3b7a\u3b80cute;\u417a\u0100ay\u3b4d\u3b52ron;\u417e;\u4437ot;\u417c\u0100et\u3b5d\u3b61tr\xe6\u155fa;\u43b6r;\uc000\ud835\udd37cy;\u4436grarr;\u61ddpf;\uc000\ud835\udd6bcr;\uc000\ud835\udccf\u0100jn\u3b85\u3b87;\u600dj;\u600c" + .split("") + .map(function (c) { return c.charCodeAt(0); })); + + var decodeDataXml = {}; + + // Generated using scripts/write-decode-map.ts + Object.defineProperty(decodeDataXml, "__esModule", { value: true }); + decodeDataXml.default = new Uint16Array( + // prettier-ignore + "\u0200aglq\t\x15\x18\x1b\u026d\x0f\0\0\x12p;\u4026os;\u4027t;\u403et;\u403cuot;\u4022" + .split("") + .map(function (c) { return c.charCodeAt(0); })); + + var decode_codepoint = {}; + + (function (exports) { + // Adapted from https://github.com/mathiasbynens/he/blob/36afe179392226cf1b6ccdb16ebbb7a5a844d93a/src/he.js#L106-L134 + var _a; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.replaceCodePoint = exports.fromCodePoint = void 0; + var decodeMap = new Map([ + [0, 65533], + // C1 Unicode control character reference replacements + [128, 8364], + [130, 8218], + [131, 402], + [132, 8222], + [133, 8230], + [134, 8224], + [135, 8225], + [136, 710], + [137, 8240], + [138, 352], + [139, 8249], + [140, 338], + [142, 381], + [145, 8216], + [146, 8217], + [147, 8220], + [148, 8221], + [149, 8226], + [150, 8211], + [151, 8212], + [152, 732], + [153, 8482], + [154, 353], + [155, 8250], + [156, 339], + [158, 382], + [159, 376], + ]); + /** + * Polyfill for `String.fromCodePoint`. It is used to create a string from a Unicode code point. + */ + exports.fromCodePoint = + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, node/no-unsupported-features/es-builtins + (_a = String.fromCodePoint) !== null && _a !== void 0 ? _a : function (codePoint) { + var output = ""; + if (codePoint > 0xffff) { + codePoint -= 0x10000; + output += String.fromCharCode(((codePoint >>> 10) & 0x3ff) | 0xd800); + codePoint = 0xdc00 | (codePoint & 0x3ff); + } + output += String.fromCharCode(codePoint); + return output; + }; + /** + * Replace the given code point with a replacement character if it is a + * surrogate or is outside the valid range. Otherwise return the code + * point unchanged. + */ + function replaceCodePoint(codePoint) { + var _a; + if ((codePoint >= 0xd800 && codePoint <= 0xdfff) || codePoint > 0x10ffff) { + return 0xfffd; + } + return (_a = decodeMap.get(codePoint)) !== null && _a !== void 0 ? _a : codePoint; + } + exports.replaceCodePoint = replaceCodePoint; + /** + * Replace the code point if relevant, then convert it to a string. + * + * @deprecated Use `fromCodePoint(replaceCodePoint(codePoint))` instead. + * @param codePoint The code point to decode. + * @returns The decoded code point. + */ + function decodeCodePoint(codePoint) { + return (0, exports.fromCodePoint)(replaceCodePoint(codePoint)); + } + exports.default = decodeCodePoint; + + } (decode_codepoint)); + + (function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __setModuleDefault = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + }) : function(o, v) { + o["default"] = v; + }); + var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; + }; + var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.decodeXML = exports.decodeHTMLStrict = exports.decodeHTMLAttribute = exports.decodeHTML = exports.determineBranch = exports.EntityDecoder = exports.DecodingMode = exports.BinTrieFlags = exports.fromCodePoint = exports.replaceCodePoint = exports.decodeCodePoint = exports.xmlDecodeTree = exports.htmlDecodeTree = void 0; + var decode_data_html_js_1 = __importDefault(decodeDataHtml); + exports.htmlDecodeTree = decode_data_html_js_1.default; + var decode_data_xml_js_1 = __importDefault(decodeDataXml); + exports.xmlDecodeTree = decode_data_xml_js_1.default; + var decode_codepoint_js_1 = __importStar(decode_codepoint); + exports.decodeCodePoint = decode_codepoint_js_1.default; + var decode_codepoint_js_2 = decode_codepoint; + Object.defineProperty(exports, "replaceCodePoint", { enumerable: true, get: function () { return decode_codepoint_js_2.replaceCodePoint; } }); + Object.defineProperty(exports, "fromCodePoint", { enumerable: true, get: function () { return decode_codepoint_js_2.fromCodePoint; } }); + var CharCodes; + (function (CharCodes) { + CharCodes[CharCodes["NUM"] = 35] = "NUM"; + CharCodes[CharCodes["SEMI"] = 59] = "SEMI"; + CharCodes[CharCodes["EQUALS"] = 61] = "EQUALS"; + CharCodes[CharCodes["ZERO"] = 48] = "ZERO"; + CharCodes[CharCodes["NINE"] = 57] = "NINE"; + CharCodes[CharCodes["LOWER_A"] = 97] = "LOWER_A"; + CharCodes[CharCodes["LOWER_F"] = 102] = "LOWER_F"; + CharCodes[CharCodes["LOWER_X"] = 120] = "LOWER_X"; + CharCodes[CharCodes["LOWER_Z"] = 122] = "LOWER_Z"; + CharCodes[CharCodes["UPPER_A"] = 65] = "UPPER_A"; + CharCodes[CharCodes["UPPER_F"] = 70] = "UPPER_F"; + CharCodes[CharCodes["UPPER_Z"] = 90] = "UPPER_Z"; + })(CharCodes || (CharCodes = {})); + /** Bit that needs to be set to convert an upper case ASCII character to lower case */ + var TO_LOWER_BIT = 32; + var BinTrieFlags; + (function (BinTrieFlags) { + BinTrieFlags[BinTrieFlags["VALUE_LENGTH"] = 49152] = "VALUE_LENGTH"; + BinTrieFlags[BinTrieFlags["BRANCH_LENGTH"] = 16256] = "BRANCH_LENGTH"; + BinTrieFlags[BinTrieFlags["JUMP_TABLE"] = 127] = "JUMP_TABLE"; + })(BinTrieFlags = exports.BinTrieFlags || (exports.BinTrieFlags = {})); + function isNumber(code) { + return code >= CharCodes.ZERO && code <= CharCodes.NINE; + } + function isHexadecimalCharacter(code) { + return ((code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_F) || + (code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_F)); + } + function isAsciiAlphaNumeric(code) { + return ((code >= CharCodes.UPPER_A && code <= CharCodes.UPPER_Z) || + (code >= CharCodes.LOWER_A && code <= CharCodes.LOWER_Z) || + isNumber(code)); + } + /** + * Checks if the given character is a valid end character for an entity in an attribute. + * + * Attribute values that aren't terminated properly aren't parsed, and shouldn't lead to a parser error. + * See the example in https://html.spec.whatwg.org/multipage/parsing.html#named-character-reference-state + */ + function isEntityInAttributeInvalidEnd(code) { + return code === CharCodes.EQUALS || isAsciiAlphaNumeric(code); + } + var EntityDecoderState; + (function (EntityDecoderState) { + EntityDecoderState[EntityDecoderState["EntityStart"] = 0] = "EntityStart"; + EntityDecoderState[EntityDecoderState["NumericStart"] = 1] = "NumericStart"; + EntityDecoderState[EntityDecoderState["NumericDecimal"] = 2] = "NumericDecimal"; + EntityDecoderState[EntityDecoderState["NumericHex"] = 3] = "NumericHex"; + EntityDecoderState[EntityDecoderState["NamedEntity"] = 4] = "NamedEntity"; + })(EntityDecoderState || (EntityDecoderState = {})); + var DecodingMode; + (function (DecodingMode) { + /** Entities in text nodes that can end with any character. */ + DecodingMode[DecodingMode["Legacy"] = 0] = "Legacy"; + /** Only allow entities terminated with a semicolon. */ + DecodingMode[DecodingMode["Strict"] = 1] = "Strict"; + /** Entities in attributes have limitations on ending characters. */ + DecodingMode[DecodingMode["Attribute"] = 2] = "Attribute"; + })(DecodingMode = exports.DecodingMode || (exports.DecodingMode = {})); + /** + * Token decoder with support of writing partial entities. + */ + var EntityDecoder = /** @class */ (function () { + function EntityDecoder( + /** The tree used to decode entities. */ + decodeTree, + /** + * The function that is called when a codepoint is decoded. + * + * For multi-byte named entities, this will be called multiple times, + * with the second codepoint, and the same `consumed` value. + * + * @param codepoint The decoded codepoint. + * @param consumed The number of bytes consumed by the decoder. + */ + emitCodePoint, + /** An object that is used to produce errors. */ + errors) { + this.decodeTree = decodeTree; + this.emitCodePoint = emitCodePoint; + this.errors = errors; + /** The current state of the decoder. */ + this.state = EntityDecoderState.EntityStart; + /** Characters that were consumed while parsing an entity. */ + this.consumed = 1; + /** + * The result of the entity. + * + * Either the result index of a numeric entity, or the codepoint of a + * numeric entity. + */ + this.result = 0; + /** The current index in the decode tree. */ + this.treeIndex = 0; + /** The number of characters that were consumed in excess. */ + this.excess = 1; + /** The mode in which the decoder is operating. */ + this.decodeMode = DecodingMode.Strict; + } + /** Resets the instance to make it reusable. */ + EntityDecoder.prototype.startEntity = function (decodeMode) { + this.decodeMode = decodeMode; + this.state = EntityDecoderState.EntityStart; + this.result = 0; + this.treeIndex = 0; + this.excess = 1; + this.consumed = 1; + }; + /** + * Write an entity to the decoder. This can be called multiple times with partial entities. + * If the entity is incomplete, the decoder will return -1. + * + * Mirrors the implementation of `getDecoder`, but with the ability to stop decoding if the + * entity is incomplete, and resume when the next string is written. + * + * @param string The string containing the entity (or a continuation of the entity). + * @param offset The offset at which the entity begins. Should be 0 if this is not the first call. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + EntityDecoder.prototype.write = function (str, offset) { + switch (this.state) { + case EntityDecoderState.EntityStart: { + if (str.charCodeAt(offset) === CharCodes.NUM) { + this.state = EntityDecoderState.NumericStart; + this.consumed += 1; + return this.stateNumericStart(str, offset + 1); + } + this.state = EntityDecoderState.NamedEntity; + return this.stateNamedEntity(str, offset); + } + case EntityDecoderState.NumericStart: { + return this.stateNumericStart(str, offset); + } + case EntityDecoderState.NumericDecimal: { + return this.stateNumericDecimal(str, offset); + } + case EntityDecoderState.NumericHex: { + return this.stateNumericHex(str, offset); + } + case EntityDecoderState.NamedEntity: { + return this.stateNamedEntity(str, offset); + } + } + }; + /** + * Switches between the numeric decimal and hexadecimal states. + * + * Equivalent to the `Numeric character reference state` in the HTML spec. + * + * @param str The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + EntityDecoder.prototype.stateNumericStart = function (str, offset) { + if (offset >= str.length) { + return -1; + } + if ((str.charCodeAt(offset) | TO_LOWER_BIT) === CharCodes.LOWER_X) { + this.state = EntityDecoderState.NumericHex; + this.consumed += 1; + return this.stateNumericHex(str, offset + 1); + } + this.state = EntityDecoderState.NumericDecimal; + return this.stateNumericDecimal(str, offset); + }; + EntityDecoder.prototype.addToNumericResult = function (str, start, end, base) { + if (start !== end) { + var digitCount = end - start; + this.result = + this.result * Math.pow(base, digitCount) + + parseInt(str.substr(start, digitCount), base); + this.consumed += digitCount; + } + }; + /** + * Parses a hexadecimal numeric entity. + * + * Equivalent to the `Hexademical character reference state` in the HTML spec. + * + * @param str The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + EntityDecoder.prototype.stateNumericHex = function (str, offset) { + var startIdx = offset; + while (offset < str.length) { + var char = str.charCodeAt(offset); + if (isNumber(char) || isHexadecimalCharacter(char)) { + offset += 1; + } + else { + this.addToNumericResult(str, startIdx, offset, 16); + return this.emitNumericEntity(char, 3); + } + } + this.addToNumericResult(str, startIdx, offset, 16); + return -1; + }; + /** + * Parses a decimal numeric entity. + * + * Equivalent to the `Decimal character reference state` in the HTML spec. + * + * @param str The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + EntityDecoder.prototype.stateNumericDecimal = function (str, offset) { + var startIdx = offset; + while (offset < str.length) { + var char = str.charCodeAt(offset); + if (isNumber(char)) { + offset += 1; + } + else { + this.addToNumericResult(str, startIdx, offset, 10); + return this.emitNumericEntity(char, 2); + } + } + this.addToNumericResult(str, startIdx, offset, 10); + return -1; + }; + /** + * Validate and emit a numeric entity. + * + * Implements the logic from the `Hexademical character reference start + * state` and `Numeric character reference end state` in the HTML spec. + * + * @param lastCp The last code point of the entity. Used to see if the + * entity was terminated with a semicolon. + * @param expectedLength The minimum number of characters that should be + * consumed. Used to validate that at least one digit + * was consumed. + * @returns The number of characters that were consumed. + */ + EntityDecoder.prototype.emitNumericEntity = function (lastCp, expectedLength) { + var _a; + // Ensure we consumed at least one digit. + if (this.consumed <= expectedLength) { + (_a = this.errors) === null || _a === void 0 ? void 0 : _a.absenceOfDigitsInNumericCharacterReference(this.consumed); + return 0; + } + // Figure out if this is a legit end of the entity + if (lastCp === CharCodes.SEMI) { + this.consumed += 1; + } + else if (this.decodeMode === DecodingMode.Strict) { + return 0; + } + this.emitCodePoint((0, decode_codepoint_js_1.replaceCodePoint)(this.result), this.consumed); + if (this.errors) { + if (lastCp !== CharCodes.SEMI) { + this.errors.missingSemicolonAfterCharacterReference(); + } + this.errors.validateNumericCharacterReference(this.result); + } + return this.consumed; + }; + /** + * Parses a named entity. + * + * Equivalent to the `Named character reference state` in the HTML spec. + * + * @param str The string containing the entity (or a continuation of the entity). + * @param offset The current offset. + * @returns The number of characters that were consumed, or -1 if the entity is incomplete. + */ + EntityDecoder.prototype.stateNamedEntity = function (str, offset) { + var decodeTree = this.decodeTree; + var current = decodeTree[this.treeIndex]; + // The mask is the number of bytes of the value, including the current byte. + var valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; + for (; offset < str.length; offset++, this.excess++) { + var char = str.charCodeAt(offset); + this.treeIndex = determineBranch(decodeTree, current, this.treeIndex + Math.max(1, valueLength), char); + if (this.treeIndex < 0) { + return this.result === 0 || + // If we are parsing an attribute + (this.decodeMode === DecodingMode.Attribute && + // We shouldn't have consumed any characters after the entity, + (valueLength === 0 || + // And there should be no invalid characters. + isEntityInAttributeInvalidEnd(char))) + ? 0 + : this.emitNotTerminatedNamedEntity(); + } + current = decodeTree[this.treeIndex]; + valueLength = (current & BinTrieFlags.VALUE_LENGTH) >> 14; + // If the branch is a value, store it and continue + if (valueLength !== 0) { + // If the entity is terminated by a semicolon, we are done. + if (char === CharCodes.SEMI) { + return this.emitNamedEntityData(this.treeIndex, valueLength, this.consumed + this.excess); + } + // If we encounter a non-terminated (legacy) entity while parsing strictly, then ignore it. + if (this.decodeMode !== DecodingMode.Strict) { + this.result = this.treeIndex; + this.consumed += this.excess; + this.excess = 0; + } + } + } + return -1; + }; + /** + * Emit a named entity that was not terminated with a semicolon. + * + * @returns The number of characters consumed. + */ + EntityDecoder.prototype.emitNotTerminatedNamedEntity = function () { + var _a; + var _b = this, result = _b.result, decodeTree = _b.decodeTree; + var valueLength = (decodeTree[result] & BinTrieFlags.VALUE_LENGTH) >> 14; + this.emitNamedEntityData(result, valueLength, this.consumed); + (_a = this.errors) === null || _a === void 0 ? void 0 : _a.missingSemicolonAfterCharacterReference(); + return this.consumed; + }; + /** + * Emit a named entity. + * + * @param result The index of the entity in the decode tree. + * @param valueLength The number of bytes in the entity. + * @param consumed The number of characters consumed. + * + * @returns The number of characters consumed. + */ + EntityDecoder.prototype.emitNamedEntityData = function (result, valueLength, consumed) { + var decodeTree = this.decodeTree; + this.emitCodePoint(valueLength === 1 + ? decodeTree[result] & ~BinTrieFlags.VALUE_LENGTH + : decodeTree[result + 1], consumed); + if (valueLength === 3) { + // For multi-byte values, we need to emit the second byte. + this.emitCodePoint(decodeTree[result + 2], consumed); + } + return consumed; + }; + /** + * Signal to the parser that the end of the input was reached. + * + * Remaining data will be emitted and relevant errors will be produced. + * + * @returns The number of characters consumed. + */ + EntityDecoder.prototype.end = function () { + var _a; + switch (this.state) { + case EntityDecoderState.NamedEntity: { + // Emit a named entity if we have one. + return this.result !== 0 && + (this.decodeMode !== DecodingMode.Attribute || + this.result === this.treeIndex) + ? this.emitNotTerminatedNamedEntity() + : 0; + } + // Otherwise, emit a numeric entity if we have one. + case EntityDecoderState.NumericDecimal: { + return this.emitNumericEntity(0, 2); + } + case EntityDecoderState.NumericHex: { + return this.emitNumericEntity(0, 3); + } + case EntityDecoderState.NumericStart: { + (_a = this.errors) === null || _a === void 0 ? void 0 : _a.absenceOfDigitsInNumericCharacterReference(this.consumed); + return 0; + } + case EntityDecoderState.EntityStart: { + // Return 0 if we have no entity. + return 0; + } + } + }; + return EntityDecoder; + }()); + exports.EntityDecoder = EntityDecoder; + /** + * Creates a function that decodes entities in a string. + * + * @param decodeTree The decode tree. + * @returns A function that decodes entities in a string. + */ + function getDecoder(decodeTree) { + var ret = ""; + var decoder = new EntityDecoder(decodeTree, function (str) { return (ret += (0, decode_codepoint_js_1.fromCodePoint)(str)); }); + return function decodeWithTrie(str, decodeMode) { + var lastIndex = 0; + var offset = 0; + while ((offset = str.indexOf("&", offset)) >= 0) { + ret += str.slice(lastIndex, offset); + decoder.startEntity(decodeMode); + var len = decoder.write(str, + // Skip the "&" + offset + 1); + if (len < 0) { + lastIndex = offset + decoder.end(); + break; + } + lastIndex = offset + len; + // If `len` is 0, skip the current `&` and continue. + offset = len === 0 ? lastIndex + 1 : lastIndex; + } + var result = ret + str.slice(lastIndex); + // Make sure we don't keep a reference to the final string. + ret = ""; + return result; + }; + } + /** + * Determines the branch of the current node that is taken given the current + * character. This function is used to traverse the trie. + * + * @param decodeTree The trie. + * @param current The current node. + * @param nodeIdx The index right after the current node and its value. + * @param char The current character. + * @returns The index of the next node, or -1 if no branch is taken. + */ + function determineBranch(decodeTree, current, nodeIdx, char) { + var branchCount = (current & BinTrieFlags.BRANCH_LENGTH) >> 7; + var jumpOffset = current & BinTrieFlags.JUMP_TABLE; + // Case 1: Single branch encoded in jump offset + if (branchCount === 0) { + return jumpOffset !== 0 && char === jumpOffset ? nodeIdx : -1; + } + // Case 2: Multiple branches encoded in jump table + if (jumpOffset) { + var value = char - jumpOffset; + return value < 0 || value >= branchCount + ? -1 + : decodeTree[nodeIdx + value] - 1; + } + // Case 3: Multiple branches encoded in dictionary + // Binary search for the character. + var lo = nodeIdx; + var hi = lo + branchCount - 1; + while (lo <= hi) { + var mid = (lo + hi) >>> 1; + var midVal = decodeTree[mid]; + if (midVal < char) { + lo = mid + 1; + } + else if (midVal > char) { + hi = mid - 1; + } + else { + return decodeTree[mid + branchCount]; + } + } + return -1; + } + exports.determineBranch = determineBranch; + var htmlDecoder = getDecoder(decode_data_html_js_1.default); + var xmlDecoder = getDecoder(decode_data_xml_js_1.default); + /** + * Decodes an HTML string. + * + * @param str The string to decode. + * @param mode The decoding mode. + * @returns The decoded string. + */ + function decodeHTML(str, mode) { + if (mode === void 0) { mode = DecodingMode.Legacy; } + return htmlDecoder(str, mode); + } + exports.decodeHTML = decodeHTML; + /** + * Decodes an HTML string in an attribute. + * + * @param str The string to decode. + * @returns The decoded string. + */ + function decodeHTMLAttribute(str) { + return htmlDecoder(str, DecodingMode.Attribute); + } + exports.decodeHTMLAttribute = decodeHTMLAttribute; + /** + * Decodes an HTML string, requiring all entities to be terminated by a semicolon. + * + * @param str The string to decode. + * @returns The decoded string. + */ + function decodeHTMLStrict(str) { + return htmlDecoder(str, DecodingMode.Strict); + } + exports.decodeHTMLStrict = decodeHTMLStrict; + /** + * Decodes an XML string, requiring all entities to be terminated by a semicolon. + * + * @param str The string to decode. + * @returns The decoded string. + */ + function decodeXML(str) { + return xmlDecoder(str, DecodingMode.Strict); + } + exports.decodeXML = decodeXML; + + } (decode)); + + (function (exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + exports.QuoteType = void 0; + var decode_js_1 = decode; + var CharCodes; + (function (CharCodes) { + CharCodes[CharCodes["Tab"] = 9] = "Tab"; + CharCodes[CharCodes["NewLine"] = 10] = "NewLine"; + CharCodes[CharCodes["FormFeed"] = 12] = "FormFeed"; + CharCodes[CharCodes["CarriageReturn"] = 13] = "CarriageReturn"; + CharCodes[CharCodes["Space"] = 32] = "Space"; + CharCodes[CharCodes["ExclamationMark"] = 33] = "ExclamationMark"; + CharCodes[CharCodes["Number"] = 35] = "Number"; + CharCodes[CharCodes["Amp"] = 38] = "Amp"; + CharCodes[CharCodes["SingleQuote"] = 39] = "SingleQuote"; + CharCodes[CharCodes["DoubleQuote"] = 34] = "DoubleQuote"; + CharCodes[CharCodes["Dash"] = 45] = "Dash"; + CharCodes[CharCodes["Slash"] = 47] = "Slash"; + CharCodes[CharCodes["Zero"] = 48] = "Zero"; + CharCodes[CharCodes["Nine"] = 57] = "Nine"; + CharCodes[CharCodes["Semi"] = 59] = "Semi"; + CharCodes[CharCodes["Lt"] = 60] = "Lt"; + CharCodes[CharCodes["Eq"] = 61] = "Eq"; + CharCodes[CharCodes["Gt"] = 62] = "Gt"; + CharCodes[CharCodes["Questionmark"] = 63] = "Questionmark"; + CharCodes[CharCodes["UpperA"] = 65] = "UpperA"; + CharCodes[CharCodes["LowerA"] = 97] = "LowerA"; + CharCodes[CharCodes["UpperF"] = 70] = "UpperF"; + CharCodes[CharCodes["LowerF"] = 102] = "LowerF"; + CharCodes[CharCodes["UpperZ"] = 90] = "UpperZ"; + CharCodes[CharCodes["LowerZ"] = 122] = "LowerZ"; + CharCodes[CharCodes["LowerX"] = 120] = "LowerX"; + CharCodes[CharCodes["OpeningSquareBracket"] = 91] = "OpeningSquareBracket"; + })(CharCodes || (CharCodes = {})); + /** All the states the tokenizer can be in. */ + var State; + (function (State) { + State[State["Text"] = 1] = "Text"; + State[State["BeforeTagName"] = 2] = "BeforeTagName"; + State[State["InTagName"] = 3] = "InTagName"; + State[State["InSelfClosingTag"] = 4] = "InSelfClosingTag"; + State[State["BeforeClosingTagName"] = 5] = "BeforeClosingTagName"; + State[State["InClosingTagName"] = 6] = "InClosingTagName"; + State[State["AfterClosingTagName"] = 7] = "AfterClosingTagName"; + // Attributes + State[State["BeforeAttributeName"] = 8] = "BeforeAttributeName"; + State[State["InAttributeName"] = 9] = "InAttributeName"; + State[State["AfterAttributeName"] = 10] = "AfterAttributeName"; + State[State["BeforeAttributeValue"] = 11] = "BeforeAttributeValue"; + State[State["InAttributeValueDq"] = 12] = "InAttributeValueDq"; + State[State["InAttributeValueSq"] = 13] = "InAttributeValueSq"; + State[State["InAttributeValueNq"] = 14] = "InAttributeValueNq"; + // Declarations + State[State["BeforeDeclaration"] = 15] = "BeforeDeclaration"; + State[State["InDeclaration"] = 16] = "InDeclaration"; + // Processing instructions + State[State["InProcessingInstruction"] = 17] = "InProcessingInstruction"; + // Comments & CDATA + State[State["BeforeComment"] = 18] = "BeforeComment"; + State[State["CDATASequence"] = 19] = "CDATASequence"; + State[State["InSpecialComment"] = 20] = "InSpecialComment"; + State[State["InCommentLike"] = 21] = "InCommentLike"; + // Special tags + State[State["BeforeSpecialS"] = 22] = "BeforeSpecialS"; + State[State["SpecialStartSequence"] = 23] = "SpecialStartSequence"; + State[State["InSpecialTag"] = 24] = "InSpecialTag"; + State[State["BeforeEntity"] = 25] = "BeforeEntity"; + State[State["BeforeNumericEntity"] = 26] = "BeforeNumericEntity"; + State[State["InNamedEntity"] = 27] = "InNamedEntity"; + State[State["InNumericEntity"] = 28] = "InNumericEntity"; + State[State["InHexEntity"] = 29] = "InHexEntity"; + })(State || (State = {})); + function isWhitespace(c) { + return (c === CharCodes.Space || + c === CharCodes.NewLine || + c === CharCodes.Tab || + c === CharCodes.FormFeed || + c === CharCodes.CarriageReturn); + } + function isEndOfTagSection(c) { + return c === CharCodes.Slash || c === CharCodes.Gt || isWhitespace(c); + } + function isNumber(c) { + return c >= CharCodes.Zero && c <= CharCodes.Nine; + } + function isASCIIAlpha(c) { + return ((c >= CharCodes.LowerA && c <= CharCodes.LowerZ) || + (c >= CharCodes.UpperA && c <= CharCodes.UpperZ)); + } + function isHexDigit(c) { + return ((c >= CharCodes.UpperA && c <= CharCodes.UpperF) || + (c >= CharCodes.LowerA && c <= CharCodes.LowerF)); + } + var QuoteType; + (function (QuoteType) { + QuoteType[QuoteType["NoValue"] = 0] = "NoValue"; + QuoteType[QuoteType["Unquoted"] = 1] = "Unquoted"; + QuoteType[QuoteType["Single"] = 2] = "Single"; + QuoteType[QuoteType["Double"] = 3] = "Double"; + })(QuoteType = exports.QuoteType || (exports.QuoteType = {})); + /** + * Sequences used to match longer strings. + * + * We don't have `Script`, `Style`, or `Title` here. Instead, we re-use the *End + * sequences with an increased offset. + */ + var Sequences = { + Cdata: new Uint8Array([0x43, 0x44, 0x41, 0x54, 0x41, 0x5b]), + CdataEnd: new Uint8Array([0x5d, 0x5d, 0x3e]), + CommentEnd: new Uint8Array([0x2d, 0x2d, 0x3e]), + ScriptEnd: new Uint8Array([0x3c, 0x2f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74]), + StyleEnd: new Uint8Array([0x3c, 0x2f, 0x73, 0x74, 0x79, 0x6c, 0x65]), + TitleEnd: new Uint8Array([0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65]), // `</title` + }; + var Tokenizer = /** @class */ (function () { + function Tokenizer(_a, cbs) { + var _b = _a.xmlMode, xmlMode = _b === void 0 ? false : _b, _c = _a.decodeEntities, decodeEntities = _c === void 0 ? true : _c; + this.cbs = cbs; + /** The current state the tokenizer is in. */ + this.state = State.Text; + /** The read buffer. */ + this.buffer = ""; + /** The beginning of the section that is currently being read. */ + this.sectionStart = 0; + /** The index within the buffer that we are currently looking at. */ + this.index = 0; + /** Some behavior, eg. when decoding entities, is done while we are in another state. This keeps track of the other state type. */ + this.baseState = State.Text; + /** For special parsing behavior inside of script and style tags. */ + this.isSpecial = false; + /** Indicates whether the tokenizer has been paused. */ + this.running = true; + /** The offset of the current buffer. */ + this.offset = 0; + this.currentSequence = undefined; + this.sequenceIndex = 0; + this.trieIndex = 0; + this.trieCurrent = 0; + /** For named entities, the index of the value. For numeric entities, the code point. */ + this.entityResult = 0; + this.entityExcess = 0; + this.xmlMode = xmlMode; + this.decodeEntities = decodeEntities; + this.entityTrie = xmlMode ? decode_js_1.xmlDecodeTree : decode_js_1.htmlDecodeTree; + } + Tokenizer.prototype.reset = function () { + this.state = State.Text; + this.buffer = ""; + this.sectionStart = 0; + this.index = 0; + this.baseState = State.Text; + this.currentSequence = undefined; + this.running = true; + this.offset = 0; + }; + Tokenizer.prototype.write = function (chunk) { + this.offset += this.buffer.length; + this.buffer = chunk; + this.parse(); + }; + Tokenizer.prototype.end = function () { + if (this.running) + this.finish(); + }; + Tokenizer.prototype.pause = function () { + this.running = false; + }; + Tokenizer.prototype.resume = function () { + this.running = true; + if (this.index < this.buffer.length + this.offset) { + this.parse(); + } + }; + /** + * The current index within all of the written data. + */ + Tokenizer.prototype.getIndex = function () { + return this.index; + }; + /** + * The start of the current section. + */ + Tokenizer.prototype.getSectionStart = function () { + return this.sectionStart; + }; + Tokenizer.prototype.stateText = function (c) { + if (c === CharCodes.Lt || + (!this.decodeEntities && this.fastForwardTo(CharCodes.Lt))) { + if (this.index > this.sectionStart) { + this.cbs.ontext(this.sectionStart, this.index); + } + this.state = State.BeforeTagName; + this.sectionStart = this.index; + } + else if (this.decodeEntities && c === CharCodes.Amp) { + this.state = State.BeforeEntity; + } + }; + Tokenizer.prototype.stateSpecialStartSequence = function (c) { + var isEnd = this.sequenceIndex === this.currentSequence.length; + var isMatch = isEnd + ? // If we are at the end of the sequence, make sure the tag name has ended + isEndOfTagSection(c) + : // Otherwise, do a case-insensitive comparison + (c | 0x20) === this.currentSequence[this.sequenceIndex]; + if (!isMatch) { + this.isSpecial = false; + } + else if (!isEnd) { + this.sequenceIndex++; + return; + } + this.sequenceIndex = 0; + this.state = State.InTagName; + this.stateInTagName(c); + }; + /** Look for an end tag. For <title> tags, also decode entities. */ + Tokenizer.prototype.stateInSpecialTag = function (c) { + if (this.sequenceIndex === this.currentSequence.length) { + if (c === CharCodes.Gt || isWhitespace(c)) { + var endOfText = this.index - this.currentSequence.length; + if (this.sectionStart < endOfText) { + // Spoof the index so that reported locations match up. + var actualIndex = this.index; + this.index = endOfText; + this.cbs.ontext(this.sectionStart, endOfText); + this.index = actualIndex; + } + this.isSpecial = false; + this.sectionStart = endOfText + 2; // Skip over the `</` + this.stateInClosingTagName(c); + return; // We are done; skip the rest of the function. + } + this.sequenceIndex = 0; + } + if ((c | 0x20) === this.currentSequence[this.sequenceIndex]) { + this.sequenceIndex += 1; + } + else if (this.sequenceIndex === 0) { + if (this.currentSequence === Sequences.TitleEnd) { + // We have to parse entities in <title> tags. + if (this.decodeEntities && c === CharCodes.Amp) { + this.state = State.BeforeEntity; + } + } + else if (this.fastForwardTo(CharCodes.Lt)) { + // Outside of <title> tags, we can fast-forward. + this.sequenceIndex = 1; + } + } + else { + // If we see a `<`, set the sequence index to 1; useful for eg. `<</script>`. + this.sequenceIndex = Number(c === CharCodes.Lt); + } + }; + Tokenizer.prototype.stateCDATASequence = function (c) { + if (c === Sequences.Cdata[this.sequenceIndex]) { + if (++this.sequenceIndex === Sequences.Cdata.length) { + this.state = State.InCommentLike; + this.currentSequence = Sequences.CdataEnd; + this.sequenceIndex = 0; + this.sectionStart = this.index + 1; + } + } + else { + this.sequenceIndex = 0; + this.state = State.InDeclaration; + this.stateInDeclaration(c); // Reconsume the character + } + }; + /** + * When we wait for one specific character, we can speed things up + * by skipping through the buffer until we find it. + * + * @returns Whether the character was found. + */ + Tokenizer.prototype.fastForwardTo = function (c) { + while (++this.index < this.buffer.length + this.offset) { + if (this.buffer.charCodeAt(this.index - this.offset) === c) { + return true; + } + } + /* + * We increment the index at the end of the `parse` loop, + * so set it to `buffer.length - 1` here. + * + * TODO: Refactor `parse` to increment index before calling states. + */ + this.index = this.buffer.length + this.offset - 1; + return false; + }; + /** + * Comments and CDATA end with `-->` and `]]>`. + * + * Their common qualities are: + * - Their end sequences have a distinct character they start with. + * - That character is then repeated, so we have to check multiple repeats. + * - All characters but the start character of the sequence can be skipped. + */ + Tokenizer.prototype.stateInCommentLike = function (c) { + if (c === this.currentSequence[this.sequenceIndex]) { + if (++this.sequenceIndex === this.currentSequence.length) { + if (this.currentSequence === Sequences.CdataEnd) { + this.cbs.oncdata(this.sectionStart, this.index, 2); + } + else { + this.cbs.oncomment(this.sectionStart, this.index, 2); + } + this.sequenceIndex = 0; + this.sectionStart = this.index + 1; + this.state = State.Text; + } + } + else if (this.sequenceIndex === 0) { + // Fast-forward to the first character of the sequence + if (this.fastForwardTo(this.currentSequence[0])) { + this.sequenceIndex = 1; + } + } + else if (c !== this.currentSequence[this.sequenceIndex - 1]) { + // Allow long sequences, eg. --->, ]]]> + this.sequenceIndex = 0; + } + }; + /** + * HTML only allows ASCII alpha characters (a-z and A-Z) at the beginning of a tag name. + * + * XML allows a lot more characters here (@see https://www.w3.org/TR/REC-xml/#NT-NameStartChar). + * We allow anything that wouldn't end the tag. + */ + Tokenizer.prototype.isTagStartChar = function (c) { + return this.xmlMode ? !isEndOfTagSection(c) : isASCIIAlpha(c); + }; + Tokenizer.prototype.startSpecial = function (sequence, offset) { + this.isSpecial = true; + this.currentSequence = sequence; + this.sequenceIndex = offset; + this.state = State.SpecialStartSequence; + }; + Tokenizer.prototype.stateBeforeTagName = function (c) { + if (c === CharCodes.ExclamationMark) { + this.state = State.BeforeDeclaration; + this.sectionStart = this.index + 1; + } + else if (c === CharCodes.Questionmark) { + this.state = State.InProcessingInstruction; + this.sectionStart = this.index + 1; + } + else if (this.isTagStartChar(c)) { + var lower = c | 0x20; + this.sectionStart = this.index; + if (!this.xmlMode && lower === Sequences.TitleEnd[2]) { + this.startSpecial(Sequences.TitleEnd, 3); + } + else { + this.state = + !this.xmlMode && lower === Sequences.ScriptEnd[2] + ? State.BeforeSpecialS + : State.InTagName; + } + } + else if (c === CharCodes.Slash) { + this.state = State.BeforeClosingTagName; + } + else { + this.state = State.Text; + this.stateText(c); + } + }; + Tokenizer.prototype.stateInTagName = function (c) { + if (isEndOfTagSection(c)) { + this.cbs.onopentagname(this.sectionStart, this.index); + this.sectionStart = -1; + this.state = State.BeforeAttributeName; + this.stateBeforeAttributeName(c); + } + }; + Tokenizer.prototype.stateBeforeClosingTagName = function (c) { + if (isWhitespace(c)) ; + else if (c === CharCodes.Gt) { + this.state = State.Text; + } + else { + this.state = this.isTagStartChar(c) + ? State.InClosingTagName + : State.InSpecialComment; + this.sectionStart = this.index; + } + }; + Tokenizer.prototype.stateInClosingTagName = function (c) { + if (c === CharCodes.Gt || isWhitespace(c)) { + this.cbs.onclosetag(this.sectionStart, this.index); + this.sectionStart = -1; + this.state = State.AfterClosingTagName; + this.stateAfterClosingTagName(c); + } + }; + Tokenizer.prototype.stateAfterClosingTagName = function (c) { + // Skip everything until ">" + if (c === CharCodes.Gt || this.fastForwardTo(CharCodes.Gt)) { + this.state = State.Text; + this.baseState = State.Text; + this.sectionStart = this.index + 1; + } + }; + Tokenizer.prototype.stateBeforeAttributeName = function (c) { + if (c === CharCodes.Gt) { + this.cbs.onopentagend(this.index); + if (this.isSpecial) { + this.state = State.InSpecialTag; + this.sequenceIndex = 0; + } + else { + this.state = State.Text; + } + this.baseState = this.state; + this.sectionStart = this.index + 1; + } + else if (c === CharCodes.Slash) { + this.state = State.InSelfClosingTag; + } + else if (!isWhitespace(c)) { + this.state = State.InAttributeName; + this.sectionStart = this.index; + } + }; + Tokenizer.prototype.stateInSelfClosingTag = function (c) { + if (c === CharCodes.Gt) { + this.cbs.onselfclosingtag(this.index); + this.state = State.Text; + this.baseState = State.Text; + this.sectionStart = this.index + 1; + this.isSpecial = false; // Reset special state, in case of self-closing special tags + } + else if (!isWhitespace(c)) { + this.state = State.BeforeAttributeName; + this.stateBeforeAttributeName(c); + } + }; + Tokenizer.prototype.stateInAttributeName = function (c) { + if (c === CharCodes.Eq || isEndOfTagSection(c)) { + this.cbs.onattribname(this.sectionStart, this.index); + this.sectionStart = -1; + this.state = State.AfterAttributeName; + this.stateAfterAttributeName(c); + } + }; + Tokenizer.prototype.stateAfterAttributeName = function (c) { + if (c === CharCodes.Eq) { + this.state = State.BeforeAttributeValue; + } + else if (c === CharCodes.Slash || c === CharCodes.Gt) { + this.cbs.onattribend(QuoteType.NoValue, this.index); + this.state = State.BeforeAttributeName; + this.stateBeforeAttributeName(c); + } + else if (!isWhitespace(c)) { + this.cbs.onattribend(QuoteType.NoValue, this.index); + this.state = State.InAttributeName; + this.sectionStart = this.index; + } + }; + Tokenizer.prototype.stateBeforeAttributeValue = function (c) { + if (c === CharCodes.DoubleQuote) { + this.state = State.InAttributeValueDq; + this.sectionStart = this.index + 1; + } + else if (c === CharCodes.SingleQuote) { + this.state = State.InAttributeValueSq; + this.sectionStart = this.index + 1; + } + else if (!isWhitespace(c)) { + this.sectionStart = this.index; + this.state = State.InAttributeValueNq; + this.stateInAttributeValueNoQuotes(c); // Reconsume token + } + }; + Tokenizer.prototype.handleInAttributeValue = function (c, quote) { + if (c === quote || + (!this.decodeEntities && this.fastForwardTo(quote))) { + this.cbs.onattribdata(this.sectionStart, this.index); + this.sectionStart = -1; + this.cbs.onattribend(quote === CharCodes.DoubleQuote + ? QuoteType.Double + : QuoteType.Single, this.index); + this.state = State.BeforeAttributeName; + } + else if (this.decodeEntities && c === CharCodes.Amp) { + this.baseState = this.state; + this.state = State.BeforeEntity; + } + }; + Tokenizer.prototype.stateInAttributeValueDoubleQuotes = function (c) { + this.handleInAttributeValue(c, CharCodes.DoubleQuote); + }; + Tokenizer.prototype.stateInAttributeValueSingleQuotes = function (c) { + this.handleInAttributeValue(c, CharCodes.SingleQuote); + }; + Tokenizer.prototype.stateInAttributeValueNoQuotes = function (c) { + if (isWhitespace(c) || c === CharCodes.Gt) { + this.cbs.onattribdata(this.sectionStart, this.index); + this.sectionStart = -1; + this.cbs.onattribend(QuoteType.Unquoted, this.index); + this.state = State.BeforeAttributeName; + this.stateBeforeAttributeName(c); + } + else if (this.decodeEntities && c === CharCodes.Amp) { + this.baseState = this.state; + this.state = State.BeforeEntity; + } + }; + Tokenizer.prototype.stateBeforeDeclaration = function (c) { + if (c === CharCodes.OpeningSquareBracket) { + this.state = State.CDATASequence; + this.sequenceIndex = 0; + } + else { + this.state = + c === CharCodes.Dash + ? State.BeforeComment + : State.InDeclaration; + } + }; + Tokenizer.prototype.stateInDeclaration = function (c) { + if (c === CharCodes.Gt || this.fastForwardTo(CharCodes.Gt)) { + this.cbs.ondeclaration(this.sectionStart, this.index); + this.state = State.Text; + this.sectionStart = this.index + 1; + } + }; + Tokenizer.prototype.stateInProcessingInstruction = function (c) { + if (c === CharCodes.Gt || this.fastForwardTo(CharCodes.Gt)) { + this.cbs.onprocessinginstruction(this.sectionStart, this.index); + this.state = State.Text; + this.sectionStart = this.index + 1; + } + }; + Tokenizer.prototype.stateBeforeComment = function (c) { + if (c === CharCodes.Dash) { + this.state = State.InCommentLike; + this.currentSequence = Sequences.CommentEnd; + // Allow short comments (eg. <!-->) + this.sequenceIndex = 2; + this.sectionStart = this.index + 1; + } + else { + this.state = State.InDeclaration; + } + }; + Tokenizer.prototype.stateInSpecialComment = function (c) { + if (c === CharCodes.Gt || this.fastForwardTo(CharCodes.Gt)) { + this.cbs.oncomment(this.sectionStart, this.index, 0); + this.state = State.Text; + this.sectionStart = this.index + 1; + } + }; + Tokenizer.prototype.stateBeforeSpecialS = function (c) { + var lower = c | 0x20; + if (lower === Sequences.ScriptEnd[3]) { + this.startSpecial(Sequences.ScriptEnd, 4); + } + else if (lower === Sequences.StyleEnd[3]) { + this.startSpecial(Sequences.StyleEnd, 4); + } + else { + this.state = State.InTagName; + this.stateInTagName(c); // Consume the token again + } + }; + Tokenizer.prototype.stateBeforeEntity = function (c) { + // Start excess with 1 to include the '&' + this.entityExcess = 1; + this.entityResult = 0; + if (c === CharCodes.Number) { + this.state = State.BeforeNumericEntity; + } + else if (c === CharCodes.Amp) ; + else { + this.trieIndex = 0; + this.trieCurrent = this.entityTrie[0]; + this.state = State.InNamedEntity; + this.stateInNamedEntity(c); + } + }; + Tokenizer.prototype.stateInNamedEntity = function (c) { + this.entityExcess += 1; + this.trieIndex = (0, decode_js_1.determineBranch)(this.entityTrie, this.trieCurrent, this.trieIndex + 1, c); + if (this.trieIndex < 0) { + this.emitNamedEntity(); + this.index--; + return; + } + this.trieCurrent = this.entityTrie[this.trieIndex]; + var masked = this.trieCurrent & decode_js_1.BinTrieFlags.VALUE_LENGTH; + // If the branch is a value, store it and continue + if (masked) { + // The mask is the number of bytes of the value, including the current byte. + var valueLength = (masked >> 14) - 1; + // If we have a legacy entity while parsing strictly, just skip the number of bytes + if (!this.allowLegacyEntity() && c !== CharCodes.Semi) { + this.trieIndex += valueLength; + } + else { + // Add 1 as we have already incremented the excess + var entityStart = this.index - this.entityExcess + 1; + if (entityStart > this.sectionStart) { + this.emitPartial(this.sectionStart, entityStart); + } + // If this is a surrogate pair, consume the next two bytes + this.entityResult = this.trieIndex; + this.trieIndex += valueLength; + this.entityExcess = 0; + this.sectionStart = this.index + 1; + if (valueLength === 0) { + this.emitNamedEntity(); + } + } + } + }; + Tokenizer.prototype.emitNamedEntity = function () { + this.state = this.baseState; + if (this.entityResult === 0) { + return; + } + var valueLength = (this.entityTrie[this.entityResult] & decode_js_1.BinTrieFlags.VALUE_LENGTH) >> + 14; + switch (valueLength) { + case 1: { + this.emitCodePoint(this.entityTrie[this.entityResult] & + ~decode_js_1.BinTrieFlags.VALUE_LENGTH); + break; + } + case 2: { + this.emitCodePoint(this.entityTrie[this.entityResult + 1]); + break; + } + case 3: { + this.emitCodePoint(this.entityTrie[this.entityResult + 1]); + this.emitCodePoint(this.entityTrie[this.entityResult + 2]); + } + } + }; + Tokenizer.prototype.stateBeforeNumericEntity = function (c) { + if ((c | 0x20) === CharCodes.LowerX) { + this.entityExcess++; + this.state = State.InHexEntity; + } + else { + this.state = State.InNumericEntity; + this.stateInNumericEntity(c); + } + }; + Tokenizer.prototype.emitNumericEntity = function (strict) { + var entityStart = this.index - this.entityExcess - 1; + var numberStart = entityStart + 2 + Number(this.state === State.InHexEntity); + if (numberStart !== this.index) { + // Emit leading data if any + if (entityStart > this.sectionStart) { + this.emitPartial(this.sectionStart, entityStart); + } + this.sectionStart = this.index + Number(strict); + this.emitCodePoint((0, decode_js_1.replaceCodePoint)(this.entityResult)); + } + this.state = this.baseState; + }; + Tokenizer.prototype.stateInNumericEntity = function (c) { + if (c === CharCodes.Semi) { + this.emitNumericEntity(true); + } + else if (isNumber(c)) { + this.entityResult = this.entityResult * 10 + (c - CharCodes.Zero); + this.entityExcess++; + } + else { + if (this.allowLegacyEntity()) { + this.emitNumericEntity(false); + } + else { + this.state = this.baseState; + } + this.index--; + } + }; + Tokenizer.prototype.stateInHexEntity = function (c) { + if (c === CharCodes.Semi) { + this.emitNumericEntity(true); + } + else if (isNumber(c)) { + this.entityResult = this.entityResult * 16 + (c - CharCodes.Zero); + this.entityExcess++; + } + else if (isHexDigit(c)) { + this.entityResult = + this.entityResult * 16 + ((c | 0x20) - CharCodes.LowerA + 10); + this.entityExcess++; + } + else { + if (this.allowLegacyEntity()) { + this.emitNumericEntity(false); + } + else { + this.state = this.baseState; + } + this.index--; + } + }; + Tokenizer.prototype.allowLegacyEntity = function () { + return (!this.xmlMode && + (this.baseState === State.Text || + this.baseState === State.InSpecialTag)); + }; + /** + * Remove data that has already been consumed from the buffer. + */ + Tokenizer.prototype.cleanup = function () { + // If we are inside of text or attributes, emit what we already have. + if (this.running && this.sectionStart !== this.index) { + if (this.state === State.Text || + (this.state === State.InSpecialTag && this.sequenceIndex === 0)) { + this.cbs.ontext(this.sectionStart, this.index); + this.sectionStart = this.index; + } + else if (this.state === State.InAttributeValueDq || + this.state === State.InAttributeValueSq || + this.state === State.InAttributeValueNq) { + this.cbs.onattribdata(this.sectionStart, this.index); + this.sectionStart = this.index; + } + } + }; + Tokenizer.prototype.shouldContinue = function () { + return this.index < this.buffer.length + this.offset && this.running; + }; + /** + * Iterates through the buffer, calling the function corresponding to the current state. + * + * States that are more likely to be hit are higher up, as a performance improvement. + */ + Tokenizer.prototype.parse = function () { + while (this.shouldContinue()) { + var c = this.buffer.charCodeAt(this.index - this.offset); + switch (this.state) { + case State.Text: { + this.stateText(c); + break; + } + case State.SpecialStartSequence: { + this.stateSpecialStartSequence(c); + break; + } + case State.InSpecialTag: { + this.stateInSpecialTag(c); + break; + } + case State.CDATASequence: { + this.stateCDATASequence(c); + break; + } + case State.InAttributeValueDq: { + this.stateInAttributeValueDoubleQuotes(c); + break; + } + case State.InAttributeName: { + this.stateInAttributeName(c); + break; + } + case State.InCommentLike: { + this.stateInCommentLike(c); + break; + } + case State.InSpecialComment: { + this.stateInSpecialComment(c); + break; + } + case State.BeforeAttributeName: { + this.stateBeforeAttributeName(c); + break; + } + case State.InTagName: { + this.stateInTagName(c); + break; + } + case State.InClosingTagName: { + this.stateInClosingTagName(c); + break; + } + case State.BeforeTagName: { + this.stateBeforeTagName(c); + break; + } + case State.AfterAttributeName: { + this.stateAfterAttributeName(c); + break; + } + case State.InAttributeValueSq: { + this.stateInAttributeValueSingleQuotes(c); + break; + } + case State.BeforeAttributeValue: { + this.stateBeforeAttributeValue(c); + break; + } + case State.BeforeClosingTagName: { + this.stateBeforeClosingTagName(c); + break; + } + case State.AfterClosingTagName: { + this.stateAfterClosingTagName(c); + break; + } + case State.BeforeSpecialS: { + this.stateBeforeSpecialS(c); + break; + } + case State.InAttributeValueNq: { + this.stateInAttributeValueNoQuotes(c); + break; + } + case State.InSelfClosingTag: { + this.stateInSelfClosingTag(c); + break; + } + case State.InDeclaration: { + this.stateInDeclaration(c); + break; + } + case State.BeforeDeclaration: { + this.stateBeforeDeclaration(c); + break; + } + case State.BeforeComment: { + this.stateBeforeComment(c); + break; + } + case State.InProcessingInstruction: { + this.stateInProcessingInstruction(c); + break; + } + case State.InNamedEntity: { + this.stateInNamedEntity(c); + break; + } + case State.BeforeEntity: { + this.stateBeforeEntity(c); + break; + } + case State.InHexEntity: { + this.stateInHexEntity(c); + break; + } + case State.InNumericEntity: { + this.stateInNumericEntity(c); + break; + } + default: { + // `this._state === State.BeforeNumericEntity` + this.stateBeforeNumericEntity(c); + } + } + this.index++; + } + this.cleanup(); + }; + Tokenizer.prototype.finish = function () { + if (this.state === State.InNamedEntity) { + this.emitNamedEntity(); + } + // If there is remaining data, emit it in a reasonable way + if (this.sectionStart < this.index) { + this.handleTrailingData(); + } + this.cbs.onend(); + }; + /** Handle any trailing data. */ + Tokenizer.prototype.handleTrailingData = function () { + var endIndex = this.buffer.length + this.offset; + if (this.state === State.InCommentLike) { + if (this.currentSequence === Sequences.CdataEnd) { + this.cbs.oncdata(this.sectionStart, endIndex, 0); + } + else { + this.cbs.oncomment(this.sectionStart, endIndex, 0); + } + } + else if (this.state === State.InNumericEntity && + this.allowLegacyEntity()) { + this.emitNumericEntity(false); + // All trailing data will have been consumed + } + else if (this.state === State.InHexEntity && + this.allowLegacyEntity()) { + this.emitNumericEntity(false); + // All trailing data will have been consumed + } + else if (this.state === State.InTagName || + this.state === State.BeforeAttributeName || + this.state === State.BeforeAttributeValue || + this.state === State.AfterAttributeName || + this.state === State.InAttributeName || + this.state === State.InAttributeValueSq || + this.state === State.InAttributeValueDq || + this.state === State.InAttributeValueNq || + this.state === State.InClosingTagName) ; + else { + this.cbs.ontext(this.sectionStart, endIndex); + } + }; + Tokenizer.prototype.emitPartial = function (start, endIndex) { + if (this.baseState !== State.Text && + this.baseState !== State.InSpecialTag) { + this.cbs.onattribdata(start, endIndex); + } + else { + this.cbs.ontext(start, endIndex); + } + }; + Tokenizer.prototype.emitCodePoint = function (cp) { + if (this.baseState !== State.Text && + this.baseState !== State.InSpecialTag) { + this.cbs.onattribentity(cp); + } + else { + this.cbs.ontextentity(cp); + } + }; + return Tokenizer; + }()); + exports.default = Tokenizer; + + } (Tokenizer)); + + var __createBinding$1 = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __setModuleDefault$1 = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + }) : function(o, v) { + o["default"] = v; + }); + var __importStar$1 = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding$1(result, mod, k); + __setModuleDefault$1(result, mod); + return result; + }; + Object.defineProperty(Parser$3, "__esModule", { value: true }); + Parser$3.Parser = void 0; + var Tokenizer_js_1 = __importStar$1(Tokenizer); + var decode_js_1 = decode; + var formTags = new Set([ + "input", + "option", + "optgroup", + "select", + "button", + "datalist", + "textarea", + ]); + var pTag = new Set(["p"]); + var tableSectionTags = new Set(["thead", "tbody"]); + var ddtTags = new Set(["dd", "dt"]); + var rtpTags = new Set(["rt", "rp"]); + var openImpliesClose = new Map([ + ["tr", new Set(["tr", "th", "td"])], + ["th", new Set(["th"])], + ["td", new Set(["thead", "th", "td"])], + ["body", new Set(["head", "link", "script"])], + ["li", new Set(["li"])], + ["p", pTag], + ["h1", pTag], + ["h2", pTag], + ["h3", pTag], + ["h4", pTag], + ["h5", pTag], + ["h6", pTag], + ["select", formTags], + ["input", formTags], + ["output", formTags], + ["button", formTags], + ["datalist", formTags], + ["textarea", formTags], + ["option", new Set(["option"])], + ["optgroup", new Set(["optgroup", "option"])], + ["dd", ddtTags], + ["dt", ddtTags], + ["address", pTag], + ["article", pTag], + ["aside", pTag], + ["blockquote", pTag], + ["details", pTag], + ["div", pTag], + ["dl", pTag], + ["fieldset", pTag], + ["figcaption", pTag], + ["figure", pTag], + ["footer", pTag], + ["form", pTag], + ["header", pTag], + ["hr", pTag], + ["main", pTag], + ["nav", pTag], + ["ol", pTag], + ["pre", pTag], + ["section", pTag], + ["table", pTag], + ["ul", pTag], + ["rt", rtpTags], + ["rp", rtpTags], + ["tbody", tableSectionTags], + ["tfoot", tableSectionTags], + ]); + var voidElements = new Set([ + "area", + "base", + "basefont", + "br", + "col", + "command", + "embed", + "frame", + "hr", + "img", + "input", + "isindex", + "keygen", + "link", + "meta", + "param", + "source", + "track", + "wbr", + ]); + var foreignContextElements = new Set(["math", "svg"]); + var htmlIntegrationElements = new Set([ + "mi", + "mo", + "mn", + "ms", + "mtext", + "annotation-xml", + "foreignobject", + "desc", + "title", + ]); + var reNameEnd = /\s|\//; + var Parser$2 = /** @class */ (function () { + function Parser(cbs, options) { + if (options === void 0) { options = {}; } + var _a, _b, _c, _d, _e; + this.options = options; + /** The start index of the last event. */ + this.startIndex = 0; + /** The end index of the last event. */ + this.endIndex = 0; + /** + * Store the start index of the current open tag, + * so we can update the start index for attributes. + */ + this.openTagStart = 0; + this.tagname = ""; + this.attribname = ""; + this.attribvalue = ""; + this.attribs = null; + this.stack = []; + this.foreignContext = []; + this.buffers = []; + this.bufferOffset = 0; + /** The index of the last written buffer. Used when resuming after a `pause()`. */ + this.writeIndex = 0; + /** Indicates whether the parser has finished running / `.end` has been called. */ + this.ended = false; + this.cbs = cbs !== null && cbs !== void 0 ? cbs : {}; + this.lowerCaseTagNames = (_a = options.lowerCaseTags) !== null && _a !== void 0 ? _a : !options.xmlMode; + this.lowerCaseAttributeNames = + (_b = options.lowerCaseAttributeNames) !== null && _b !== void 0 ? _b : !options.xmlMode; + this.tokenizer = new ((_c = options.Tokenizer) !== null && _c !== void 0 ? _c : Tokenizer_js_1.default)(this.options, this); + (_e = (_d = this.cbs).onparserinit) === null || _e === void 0 ? void 0 : _e.call(_d, this); + } + // Tokenizer event handlers + /** @internal */ + Parser.prototype.ontext = function (start, endIndex) { + var _a, _b; + var data = this.getSlice(start, endIndex); + this.endIndex = endIndex - 1; + (_b = (_a = this.cbs).ontext) === null || _b === void 0 ? void 0 : _b.call(_a, data); + this.startIndex = endIndex; + }; + /** @internal */ + Parser.prototype.ontextentity = function (cp) { + var _a, _b; + /* + * Entities can be emitted on the character, or directly after. + * We use the section start here to get accurate indices. + */ + var index = this.tokenizer.getSectionStart(); + this.endIndex = index - 1; + (_b = (_a = this.cbs).ontext) === null || _b === void 0 ? void 0 : _b.call(_a, (0, decode_js_1.fromCodePoint)(cp)); + this.startIndex = index; + }; + Parser.prototype.isVoidElement = function (name) { + return !this.options.xmlMode && voidElements.has(name); + }; + /** @internal */ + Parser.prototype.onopentagname = function (start, endIndex) { + this.endIndex = endIndex; + var name = this.getSlice(start, endIndex); + if (this.lowerCaseTagNames) { + name = name.toLowerCase(); + } + this.emitOpenTag(name); + }; + Parser.prototype.emitOpenTag = function (name) { + var _a, _b, _c, _d; + this.openTagStart = this.startIndex; + this.tagname = name; + var impliesClose = !this.options.xmlMode && openImpliesClose.get(name); + if (impliesClose) { + while (this.stack.length > 0 && + impliesClose.has(this.stack[this.stack.length - 1])) { + var element = this.stack.pop(); + (_b = (_a = this.cbs).onclosetag) === null || _b === void 0 ? void 0 : _b.call(_a, element, true); + } + } + if (!this.isVoidElement(name)) { + this.stack.push(name); + if (foreignContextElements.has(name)) { + this.foreignContext.push(true); + } + else if (htmlIntegrationElements.has(name)) { + this.foreignContext.push(false); + } + } + (_d = (_c = this.cbs).onopentagname) === null || _d === void 0 ? void 0 : _d.call(_c, name); + if (this.cbs.onopentag) + this.attribs = {}; + }; + Parser.prototype.endOpenTag = function (isImplied) { + var _a, _b; + this.startIndex = this.openTagStart; + if (this.attribs) { + (_b = (_a = this.cbs).onopentag) === null || _b === void 0 ? void 0 : _b.call(_a, this.tagname, this.attribs, isImplied); + this.attribs = null; + } + if (this.cbs.onclosetag && this.isVoidElement(this.tagname)) { + this.cbs.onclosetag(this.tagname, true); + } + this.tagname = ""; + }; + /** @internal */ + Parser.prototype.onopentagend = function (endIndex) { + this.endIndex = endIndex; + this.endOpenTag(false); + // Set `startIndex` for next node + this.startIndex = endIndex + 1; + }; + /** @internal */ + Parser.prototype.onclosetag = function (start, endIndex) { + var _a, _b, _c, _d, _e, _f; + this.endIndex = endIndex; + var name = this.getSlice(start, endIndex); + if (this.lowerCaseTagNames) { + name = name.toLowerCase(); + } + if (foreignContextElements.has(name) || + htmlIntegrationElements.has(name)) { + this.foreignContext.pop(); + } + if (!this.isVoidElement(name)) { + var pos = this.stack.lastIndexOf(name); + if (pos !== -1) { + if (this.cbs.onclosetag) { + var count = this.stack.length - pos; + while (count--) { + // We know the stack has sufficient elements. + this.cbs.onclosetag(this.stack.pop(), count !== 0); + } + } + else + this.stack.length = pos; + } + else if (!this.options.xmlMode && name === "p") { + // Implicit open before close + this.emitOpenTag("p"); + this.closeCurrentTag(true); + } + } + else if (!this.options.xmlMode && name === "br") { + // We can't use `emitOpenTag` for implicit open, as `br` would be implicitly closed. + (_b = (_a = this.cbs).onopentagname) === null || _b === void 0 ? void 0 : _b.call(_a, "br"); + (_d = (_c = this.cbs).onopentag) === null || _d === void 0 ? void 0 : _d.call(_c, "br", {}, true); + (_f = (_e = this.cbs).onclosetag) === null || _f === void 0 ? void 0 : _f.call(_e, "br", false); + } + // Set `startIndex` for next node + this.startIndex = endIndex + 1; + }; + /** @internal */ + Parser.prototype.onselfclosingtag = function (endIndex) { + this.endIndex = endIndex; + if (this.options.xmlMode || + this.options.recognizeSelfClosing || + this.foreignContext[this.foreignContext.length - 1]) { + this.closeCurrentTag(false); + // Set `startIndex` for next node + this.startIndex = endIndex + 1; + } + else { + // Ignore the fact that the tag is self-closing. + this.onopentagend(endIndex); + } + }; + Parser.prototype.closeCurrentTag = function (isOpenImplied) { + var _a, _b; + var name = this.tagname; + this.endOpenTag(isOpenImplied); + // Self-closing tags will be on the top of the stack + if (this.stack[this.stack.length - 1] === name) { + // If the opening tag isn't implied, the closing tag has to be implied. + (_b = (_a = this.cbs).onclosetag) === null || _b === void 0 ? void 0 : _b.call(_a, name, !isOpenImplied); + this.stack.pop(); + } + }; + /** @internal */ + Parser.prototype.onattribname = function (start, endIndex) { + this.startIndex = start; + var name = this.getSlice(start, endIndex); + this.attribname = this.lowerCaseAttributeNames + ? name.toLowerCase() + : name; + }; + /** @internal */ + Parser.prototype.onattribdata = function (start, endIndex) { + this.attribvalue += this.getSlice(start, endIndex); + }; + /** @internal */ + Parser.prototype.onattribentity = function (cp) { + this.attribvalue += (0, decode_js_1.fromCodePoint)(cp); + }; + /** @internal */ + Parser.prototype.onattribend = function (quote, endIndex) { + var _a, _b; + this.endIndex = endIndex; + (_b = (_a = this.cbs).onattribute) === null || _b === void 0 ? void 0 : _b.call(_a, this.attribname, this.attribvalue, quote === Tokenizer_js_1.QuoteType.Double + ? '"' + : quote === Tokenizer_js_1.QuoteType.Single + ? "'" + : quote === Tokenizer_js_1.QuoteType.NoValue + ? undefined + : null); + if (this.attribs && + !Object.prototype.hasOwnProperty.call(this.attribs, this.attribname)) { + this.attribs[this.attribname] = this.attribvalue; + } + this.attribvalue = ""; + }; + Parser.prototype.getInstructionName = function (value) { + var index = value.search(reNameEnd); + var name = index < 0 ? value : value.substr(0, index); + if (this.lowerCaseTagNames) { + name = name.toLowerCase(); + } + return name; + }; + /** @internal */ + Parser.prototype.ondeclaration = function (start, endIndex) { + this.endIndex = endIndex; + var value = this.getSlice(start, endIndex); + if (this.cbs.onprocessinginstruction) { + var name = this.getInstructionName(value); + this.cbs.onprocessinginstruction("!".concat(name), "!".concat(value)); + } + // Set `startIndex` for next node + this.startIndex = endIndex + 1; + }; + /** @internal */ + Parser.prototype.onprocessinginstruction = function (start, endIndex) { + this.endIndex = endIndex; + var value = this.getSlice(start, endIndex); + if (this.cbs.onprocessinginstruction) { + var name = this.getInstructionName(value); + this.cbs.onprocessinginstruction("?".concat(name), "?".concat(value)); + } + // Set `startIndex` for next node + this.startIndex = endIndex + 1; + }; + /** @internal */ + Parser.prototype.oncomment = function (start, endIndex, offset) { + var _a, _b, _c, _d; + this.endIndex = endIndex; + (_b = (_a = this.cbs).oncomment) === null || _b === void 0 ? void 0 : _b.call(_a, this.getSlice(start, endIndex - offset)); + (_d = (_c = this.cbs).oncommentend) === null || _d === void 0 ? void 0 : _d.call(_c); + // Set `startIndex` for next node + this.startIndex = endIndex + 1; + }; + /** @internal */ + Parser.prototype.oncdata = function (start, endIndex, offset) { + var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; + this.endIndex = endIndex; + var value = this.getSlice(start, endIndex - offset); + if (this.options.xmlMode || this.options.recognizeCDATA) { + (_b = (_a = this.cbs).oncdatastart) === null || _b === void 0 ? void 0 : _b.call(_a); + (_d = (_c = this.cbs).ontext) === null || _d === void 0 ? void 0 : _d.call(_c, value); + (_f = (_e = this.cbs).oncdataend) === null || _f === void 0 ? void 0 : _f.call(_e); + } + else { + (_h = (_g = this.cbs).oncomment) === null || _h === void 0 ? void 0 : _h.call(_g, "[CDATA[".concat(value, "]]")); + (_k = (_j = this.cbs).oncommentend) === null || _k === void 0 ? void 0 : _k.call(_j); + } + // Set `startIndex` for next node + this.startIndex = endIndex + 1; + }; + /** @internal */ + Parser.prototype.onend = function () { + var _a, _b; + if (this.cbs.onclosetag) { + // Set the end index for all remaining tags + this.endIndex = this.startIndex; + for (var index = this.stack.length; index > 0; this.cbs.onclosetag(this.stack[--index], true)) + ; + } + (_b = (_a = this.cbs).onend) === null || _b === void 0 ? void 0 : _b.call(_a); + }; + /** + * Resets the parser to a blank state, ready to parse a new HTML document + */ + Parser.prototype.reset = function () { + var _a, _b, _c, _d; + (_b = (_a = this.cbs).onreset) === null || _b === void 0 ? void 0 : _b.call(_a); + this.tokenizer.reset(); + this.tagname = ""; + this.attribname = ""; + this.attribs = null; + this.stack.length = 0; + this.startIndex = 0; + this.endIndex = 0; + (_d = (_c = this.cbs).onparserinit) === null || _d === void 0 ? void 0 : _d.call(_c, this); + this.buffers.length = 0; + this.bufferOffset = 0; + this.writeIndex = 0; + this.ended = false; + }; + /** + * Resets the parser, then parses a complete document and + * pushes it to the handler. + * + * @param data Document to parse. + */ + Parser.prototype.parseComplete = function (data) { + this.reset(); + this.end(data); + }; + Parser.prototype.getSlice = function (start, end) { + while (start - this.bufferOffset >= this.buffers[0].length) { + this.shiftBuffer(); + } + var slice = this.buffers[0].slice(start - this.bufferOffset, end - this.bufferOffset); + while (end - this.bufferOffset > this.buffers[0].length) { + this.shiftBuffer(); + slice += this.buffers[0].slice(0, end - this.bufferOffset); + } + return slice; + }; + Parser.prototype.shiftBuffer = function () { + this.bufferOffset += this.buffers[0].length; + this.writeIndex--; + this.buffers.shift(); + }; + /** + * Parses a chunk of data and calls the corresponding callbacks. + * + * @param chunk Chunk to parse. + */ + Parser.prototype.write = function (chunk) { + var _a, _b; + if (this.ended) { + (_b = (_a = this.cbs).onerror) === null || _b === void 0 ? void 0 : _b.call(_a, new Error(".write() after done!")); + return; + } + this.buffers.push(chunk); + if (this.tokenizer.running) { + this.tokenizer.write(chunk); + this.writeIndex++; + } + }; + /** + * Parses the end of the buffer and clears the stack, calls onend. + * + * @param chunk Optional final chunk to parse. + */ + Parser.prototype.end = function (chunk) { + var _a, _b; + if (this.ended) { + (_b = (_a = this.cbs).onerror) === null || _b === void 0 ? void 0 : _b.call(_a, new Error(".end() after done!")); + return; + } + if (chunk) + this.write(chunk); + this.ended = true; + this.tokenizer.end(); + }; + /** + * Pauses parsing. The parser won't emit events until `resume` is called. + */ + Parser.prototype.pause = function () { + this.tokenizer.pause(); + }; + /** + * Resumes parsing after `pause` was called. + */ + Parser.prototype.resume = function () { + this.tokenizer.resume(); + while (this.tokenizer.running && + this.writeIndex < this.buffers.length) { + this.tokenizer.write(this.buffers[this.writeIndex++]); + } + if (this.ended) + this.tokenizer.end(); + }; + /** + * Alias of `write`, for backwards compatibility. + * + * @param chunk Chunk to parse. + * @deprecated + */ + Parser.prototype.parseChunk = function (chunk) { + this.write(chunk); + }; + /** + * Alias of `end`, for backwards compatibility. + * + * @param chunk Optional final chunk to parse. + * @deprecated + */ + Parser.prototype.done = function (chunk) { + this.end(chunk); + }; + return Parser; + }()); + Parser$3.Parser = Parser$2; + + var lib$4 = {}; + + var lib$3 = {}; + + (function (exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + exports.Doctype = exports.CDATA = exports.Tag = exports.Style = exports.Script = exports.Comment = exports.Directive = exports.Text = exports.Root = exports.isTag = exports.ElementType = void 0; + /** Types of elements found in htmlparser2's DOM */ + var ElementType; + (function (ElementType) { + /** Type for the root element of a document */ + ElementType["Root"] = "root"; + /** Type for Text */ + ElementType["Text"] = "text"; + /** Type for <? ... ?> */ + ElementType["Directive"] = "directive"; + /** Type for <!-- ... --> */ + ElementType["Comment"] = "comment"; + /** Type for <script> tags */ + ElementType["Script"] = "script"; + /** Type for <style> tags */ + ElementType["Style"] = "style"; + /** Type for Any tag */ + ElementType["Tag"] = "tag"; + /** Type for <![CDATA[ ... ]]> */ + ElementType["CDATA"] = "cdata"; + /** Type for <!doctype ...> */ + ElementType["Doctype"] = "doctype"; + })(ElementType = exports.ElementType || (exports.ElementType = {})); + /** + * Tests whether an element is a tag or not. + * + * @param elem Element to test + */ + function isTag(elem) { + return (elem.type === ElementType.Tag || + elem.type === ElementType.Script || + elem.type === ElementType.Style); + } + exports.isTag = isTag; + // Exports for backwards compatibility + /** Type for the root element of a document */ + exports.Root = ElementType.Root; + /** Type for Text */ + exports.Text = ElementType.Text; + /** Type for <? ... ?> */ + exports.Directive = ElementType.Directive; + /** Type for <!-- ... --> */ + exports.Comment = ElementType.Comment; + /** Type for <script> tags */ + exports.Script = ElementType.Script; + /** Type for <style> tags */ + exports.Style = ElementType.Style; + /** Type for Any tag */ + exports.Tag = ElementType.Tag; + /** Type for <![CDATA[ ... ]]> */ + exports.CDATA = ElementType.CDATA; + /** Type for <!doctype ...> */ + exports.Doctype = ElementType.Doctype; + } (lib$3)); + + var node$1 = {}; + + var __extends = (commonjsGlobal && commonjsGlobal.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + })(); + var __assign$1 = (commonjsGlobal && commonjsGlobal.__assign) || function () { + __assign$1 = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign$1.apply(this, arguments); + }; + Object.defineProperty(node$1, "__esModule", { value: true }); + node$1.cloneNode = node$1.hasChildren = node$1.isDocument = node$1.isDirective = node$1.isComment = node$1.isText = node$1.isCDATA = node$1.isTag = node$1.Element = node$1.Document = node$1.CDATA = node$1.NodeWithChildren = node$1.ProcessingInstruction = node$1.Comment = node$1.Text = node$1.DataNode = node$1.Node = void 0; + var domelementtype_1$1 = lib$3; + /** + * This object will be used as the prototype for Nodes when creating a + * DOM-Level-1-compliant structure. + */ + var Node$5 = /** @class */ (function () { + function Node() { + /** Parent of the node */ + this.parent = null; + /** Previous sibling */ + this.prev = null; + /** Next sibling */ + this.next = null; + /** The start index of the node. Requires `withStartIndices` on the handler to be `true. */ + this.startIndex = null; + /** The end index of the node. Requires `withEndIndices` on the handler to be `true. */ + this.endIndex = null; + } + Object.defineProperty(Node.prototype, "parentNode", { + // Read-write aliases for properties + /** + * Same as {@link parent}. + * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + get: function () { + return this.parent; + }, + set: function (parent) { + this.parent = parent; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Node.prototype, "previousSibling", { + /** + * Same as {@link prev}. + * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + get: function () { + return this.prev; + }, + set: function (prev) { + this.prev = prev; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Node.prototype, "nextSibling", { + /** + * Same as {@link next}. + * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + get: function () { + return this.next; + }, + set: function (next) { + this.next = next; + }, + enumerable: false, + configurable: true + }); + /** + * Clone this node, and optionally its children. + * + * @param recursive Clone child nodes as well. + * @returns A clone of the node. + */ + Node.prototype.cloneNode = function (recursive) { + if (recursive === void 0) { recursive = false; } + return cloneNode$1(this, recursive); + }; + return Node; + }()); + node$1.Node = Node$5; + /** + * A node that contains some data. + */ + var DataNode = /** @class */ (function (_super) { + __extends(DataNode, _super); + /** + * @param data The content of the data node + */ + function DataNode(data) { + var _this = _super.call(this) || this; + _this.data = data; + return _this; + } + Object.defineProperty(DataNode.prototype, "nodeValue", { + /** + * Same as {@link data}. + * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + get: function () { + return this.data; + }, + set: function (data) { + this.data = data; + }, + enumerable: false, + configurable: true + }); + return DataNode; + }(Node$5)); + node$1.DataNode = DataNode; + /** + * Text within the document. + */ + var Text = /** @class */ (function (_super) { + __extends(Text, _super); + function Text() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.type = domelementtype_1$1.ElementType.Text; + return _this; + } + Object.defineProperty(Text.prototype, "nodeType", { + get: function () { + return 3; + }, + enumerable: false, + configurable: true + }); + return Text; + }(DataNode)); + node$1.Text = Text; + /** + * Comments within the document. + */ + var Comment$5 = /** @class */ (function (_super) { + __extends(Comment, _super); + function Comment() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.type = domelementtype_1$1.ElementType.Comment; + return _this; + } + Object.defineProperty(Comment.prototype, "nodeType", { + get: function () { + return 8; + }, + enumerable: false, + configurable: true + }); + return Comment; + }(DataNode)); + node$1.Comment = Comment$5; + /** + * Processing instructions, including doc types. + */ + var ProcessingInstruction = /** @class */ (function (_super) { + __extends(ProcessingInstruction, _super); + function ProcessingInstruction(name, data) { + var _this = _super.call(this, data) || this; + _this.name = name; + _this.type = domelementtype_1$1.ElementType.Directive; + return _this; + } + Object.defineProperty(ProcessingInstruction.prototype, "nodeType", { + get: function () { + return 1; + }, + enumerable: false, + configurable: true + }); + return ProcessingInstruction; + }(DataNode)); + node$1.ProcessingInstruction = ProcessingInstruction; + /** + * A `Node` that can have children. + */ + var NodeWithChildren = /** @class */ (function (_super) { + __extends(NodeWithChildren, _super); + /** + * @param children Children of the node. Only certain node types can have children. + */ + function NodeWithChildren(children) { + var _this = _super.call(this) || this; + _this.children = children; + return _this; + } + Object.defineProperty(NodeWithChildren.prototype, "firstChild", { + // Aliases + /** First child of the node. */ + get: function () { + var _a; + return (_a = this.children[0]) !== null && _a !== void 0 ? _a : null; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(NodeWithChildren.prototype, "lastChild", { + /** Last child of the node. */ + get: function () { + return this.children.length > 0 + ? this.children[this.children.length - 1] + : null; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(NodeWithChildren.prototype, "childNodes", { + /** + * Same as {@link children}. + * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + get: function () { + return this.children; + }, + set: function (children) { + this.children = children; + }, + enumerable: false, + configurable: true + }); + return NodeWithChildren; + }(Node$5)); + node$1.NodeWithChildren = NodeWithChildren; + var CDATA = /** @class */ (function (_super) { + __extends(CDATA, _super); + function CDATA() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.type = domelementtype_1$1.ElementType.CDATA; + return _this; + } + Object.defineProperty(CDATA.prototype, "nodeType", { + get: function () { + return 4; + }, + enumerable: false, + configurable: true + }); + return CDATA; + }(NodeWithChildren)); + node$1.CDATA = CDATA; + /** + * The root node of the document. + */ + var Document$4 = /** @class */ (function (_super) { + __extends(Document, _super); + function Document() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.type = domelementtype_1$1.ElementType.Root; + return _this; + } + Object.defineProperty(Document.prototype, "nodeType", { + get: function () { + return 9; + }, + enumerable: false, + configurable: true + }); + return Document; + }(NodeWithChildren)); + node$1.Document = Document$4; + /** + * An element within the DOM. + */ + var Element = /** @class */ (function (_super) { + __extends(Element, _super); + /** + * @param name Name of the tag, eg. `div`, `span`. + * @param attribs Object mapping attribute names to attribute values. + * @param children Children of the node. + */ + function Element(name, attribs, children, type) { + if (children === void 0) { children = []; } + if (type === void 0) { type = name === "script" + ? domelementtype_1$1.ElementType.Script + : name === "style" + ? domelementtype_1$1.ElementType.Style + : domelementtype_1$1.ElementType.Tag; } + var _this = _super.call(this, children) || this; + _this.name = name; + _this.attribs = attribs; + _this.type = type; + return _this; + } + Object.defineProperty(Element.prototype, "nodeType", { + get: function () { + return 1; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Element.prototype, "tagName", { + // DOM Level 1 aliases + /** + * Same as {@link name}. + * [DOM spec](https://dom.spec.whatwg.org)-compatible alias. + */ + get: function () { + return this.name; + }, + set: function (name) { + this.name = name; + }, + enumerable: false, + configurable: true + }); + Object.defineProperty(Element.prototype, "attributes", { + get: function () { + var _this = this; + return Object.keys(this.attribs).map(function (name) { + var _a, _b; + return ({ + name: name, + value: _this.attribs[name], + namespace: (_a = _this["x-attribsNamespace"]) === null || _a === void 0 ? void 0 : _a[name], + prefix: (_b = _this["x-attribsPrefix"]) === null || _b === void 0 ? void 0 : _b[name], + }); + }); + }, + enumerable: false, + configurable: true + }); + return Element; + }(NodeWithChildren)); + node$1.Element = Element; + /** + * @param node Node to check. + * @returns `true` if the node is a `Element`, `false` otherwise. + */ + function isTag(node) { + return (0, domelementtype_1$1.isTag)(node); + } + node$1.isTag = isTag; + /** + * @param node Node to check. + * @returns `true` if the node has the type `CDATA`, `false` otherwise. + */ + function isCDATA(node) { + return node.type === domelementtype_1$1.ElementType.CDATA; + } + node$1.isCDATA = isCDATA; + /** + * @param node Node to check. + * @returns `true` if the node has the type `Text`, `false` otherwise. + */ + function isText(node) { + return node.type === domelementtype_1$1.ElementType.Text; + } + node$1.isText = isText; + /** + * @param node Node to check. + * @returns `true` if the node has the type `Comment`, `false` otherwise. + */ + function isComment(node) { + return node.type === domelementtype_1$1.ElementType.Comment; + } + node$1.isComment = isComment; + /** + * @param node Node to check. + * @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise. + */ + function isDirective(node) { + return node.type === domelementtype_1$1.ElementType.Directive; + } + node$1.isDirective = isDirective; + /** + * @param node Node to check. + * @returns `true` if the node has the type `ProcessingInstruction`, `false` otherwise. + */ + function isDocument(node) { + return node.type === domelementtype_1$1.ElementType.Root; + } + node$1.isDocument = isDocument; + /** + * @param node Node to check. + * @returns `true` if the node has children, `false` otherwise. + */ + function hasChildren(node) { + return Object.prototype.hasOwnProperty.call(node, "children"); + } + node$1.hasChildren = hasChildren; + /** + * Clone a node, and optionally its children. + * + * @param recursive Clone child nodes as well. + * @returns A clone of the node. + */ + function cloneNode$1(node, recursive) { + if (recursive === void 0) { recursive = false; } + var result; + if (isText(node)) { + result = new Text(node.data); + } + else if (isComment(node)) { + result = new Comment$5(node.data); + } + else if (isTag(node)) { + var children = recursive ? cloneChildren(node.children) : []; + var clone_1 = new Element(node.name, __assign$1({}, node.attribs), children); + children.forEach(function (child) { return (child.parent = clone_1); }); + if (node.namespace != null) { + clone_1.namespace = node.namespace; + } + if (node["x-attribsNamespace"]) { + clone_1["x-attribsNamespace"] = __assign$1({}, node["x-attribsNamespace"]); + } + if (node["x-attribsPrefix"]) { + clone_1["x-attribsPrefix"] = __assign$1({}, node["x-attribsPrefix"]); + } + result = clone_1; + } + else if (isCDATA(node)) { + var children = recursive ? cloneChildren(node.children) : []; + var clone_2 = new CDATA(children); + children.forEach(function (child) { return (child.parent = clone_2); }); + result = clone_2; + } + else if (isDocument(node)) { + var children = recursive ? cloneChildren(node.children) : []; + var clone_3 = new Document$4(children); + children.forEach(function (child) { return (child.parent = clone_3); }); + if (node["x-mode"]) { + clone_3["x-mode"] = node["x-mode"]; + } + result = clone_3; + } + else if (isDirective(node)) { + var instruction = new ProcessingInstruction(node.name, node.data); + if (node["x-name"] != null) { + instruction["x-name"] = node["x-name"]; + instruction["x-publicId"] = node["x-publicId"]; + instruction["x-systemId"] = node["x-systemId"]; + } + result = instruction; + } + else { + throw new Error("Not implemented yet: ".concat(node.type)); + } + result.startIndex = node.startIndex; + result.endIndex = node.endIndex; + if (node.sourceCodeLocation != null) { + result.sourceCodeLocation = node.sourceCodeLocation; + } + return result; + } + node$1.cloneNode = cloneNode$1; + function cloneChildren(childs) { + var children = childs.map(function (child) { return cloneNode$1(child, true); }); + for (var i = 1; i < children.length; i++) { + children[i].prev = children[i - 1]; + children[i - 1].next = children[i]; + } + return children; + } + + (function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.DomHandler = void 0; + var domelementtype_1 = lib$3; + var node_js_1 = node$1; + __exportStar(node$1, exports); + // Default options + var defaultOpts = { + withStartIndices: false, + withEndIndices: false, + xmlMode: false, + }; + var DomHandler = /** @class */ (function () { + /** + * @param callback Called once parsing has completed. + * @param options Settings for the handler. + * @param elementCB Callback whenever a tag is closed. + */ + function DomHandler(callback, options, elementCB) { + /** The elements of the DOM */ + this.dom = []; + /** The root element for the DOM */ + this.root = new node_js_1.Document(this.dom); + /** Indicated whether parsing has been completed. */ + this.done = false; + /** Stack of open tags. */ + this.tagStack = [this.root]; + /** A data node that is still being written to. */ + this.lastNode = null; + /** Reference to the parser instance. Used for location information. */ + this.parser = null; + // Make it possible to skip arguments, for backwards-compatibility + if (typeof options === "function") { + elementCB = options; + options = defaultOpts; + } + if (typeof callback === "object") { + options = callback; + callback = undefined; + } + this.callback = callback !== null && callback !== void 0 ? callback : null; + this.options = options !== null && options !== void 0 ? options : defaultOpts; + this.elementCB = elementCB !== null && elementCB !== void 0 ? elementCB : null; + } + DomHandler.prototype.onparserinit = function (parser) { + this.parser = parser; + }; + // Resets the handler back to starting state + DomHandler.prototype.onreset = function () { + this.dom = []; + this.root = new node_js_1.Document(this.dom); + this.done = false; + this.tagStack = [this.root]; + this.lastNode = null; + this.parser = null; + }; + // Signals the handler that parsing is done + DomHandler.prototype.onend = function () { + if (this.done) + return; + this.done = true; + this.parser = null; + this.handleCallback(null); + }; + DomHandler.prototype.onerror = function (error) { + this.handleCallback(error); + }; + DomHandler.prototype.onclosetag = function () { + this.lastNode = null; + var elem = this.tagStack.pop(); + if (this.options.withEndIndices) { + elem.endIndex = this.parser.endIndex; + } + if (this.elementCB) + this.elementCB(elem); + }; + DomHandler.prototype.onopentag = function (name, attribs) { + var type = this.options.xmlMode ? domelementtype_1.ElementType.Tag : undefined; + var element = new node_js_1.Element(name, attribs, undefined, type); + this.addNode(element); + this.tagStack.push(element); + }; + DomHandler.prototype.ontext = function (data) { + var lastNode = this.lastNode; + if (lastNode && lastNode.type === domelementtype_1.ElementType.Text) { + lastNode.data += data; + if (this.options.withEndIndices) { + lastNode.endIndex = this.parser.endIndex; + } + } + else { + var node = new node_js_1.Text(data); + this.addNode(node); + this.lastNode = node; + } + }; + DomHandler.prototype.oncomment = function (data) { + if (this.lastNode && this.lastNode.type === domelementtype_1.ElementType.Comment) { + this.lastNode.data += data; + return; + } + var node = new node_js_1.Comment(data); + this.addNode(node); + this.lastNode = node; + }; + DomHandler.prototype.oncommentend = function () { + this.lastNode = null; + }; + DomHandler.prototype.oncdatastart = function () { + var text = new node_js_1.Text(""); + var node = new node_js_1.CDATA([text]); + this.addNode(node); + text.parent = node; + this.lastNode = text; + }; + DomHandler.prototype.oncdataend = function () { + this.lastNode = null; + }; + DomHandler.prototype.onprocessinginstruction = function (name, data) { + var node = new node_js_1.ProcessingInstruction(name, data); + this.addNode(node); + }; + DomHandler.prototype.handleCallback = function (error) { + if (typeof this.callback === "function") { + this.callback(error, this.dom); + } + else if (error) { + throw error; + } + }; + DomHandler.prototype.addNode = function (node) { + var parent = this.tagStack[this.tagStack.length - 1]; + var previousSibling = parent.children[parent.children.length - 1]; + if (this.options.withStartIndices) { + node.startIndex = this.parser.startIndex; + } + if (this.options.withEndIndices) { + node.endIndex = this.parser.endIndex; + } + parent.children.push(node); + if (previousSibling) { + node.prev = previousSibling; + previousSibling.next = node; + } + node.parent = parent; + this.lastNode = null; + }; + return DomHandler; + }()); + exports.DomHandler = DomHandler; + exports.default = DomHandler; + } (lib$4)); + + var lib$2 = {}; + + var stringify$6 = {}; + + var lib$1 = {}; + + var lib = {}; + + var encode$1 = {}; + + var encodeHtml = {}; + + // Generated using scripts/write-encode-map.ts + Object.defineProperty(encodeHtml, "__esModule", { value: true }); + function restoreDiff(arr) { + for (var i = 1; i < arr.length; i++) { + arr[i][0] += arr[i - 1][0] + 1; + } + return arr; + } + // prettier-ignore + encodeHtml.default = new Map(/* #__PURE__ */ restoreDiff([[9, " "], [0, " "], [22, "!"], [0, """], [0, "#"], [0, "$"], [0, "%"], [0, "&"], [0, "'"], [0, "("], [0, ")"], [0, "*"], [0, "+"], [0, ","], [1, "."], [0, "/"], [10, ":"], [0, ";"], [0, { v: "<", n: 8402, o: "<⃒" }], [0, { v: "=", n: 8421, o: "=⃥" }], [0, { v: ">", n: 8402, o: ">⃒" }], [0, "?"], [0, "@"], [26, "["], [0, "\"], [0, "]"], [0, "^"], [0, "_"], [0, "`"], [5, { n: 106, o: "fj" }], [20, "{"], [0, "|"], [0, "}"], [34, " "], [0, "¡"], [0, "¢"], [0, "£"], [0, "¤"], [0, "¥"], [0, "¦"], [0, "§"], [0, "¨"], [0, "©"], [0, "ª"], [0, "«"], [0, "¬"], [0, "­"], [0, "®"], [0, "¯"], [0, "°"], [0, "±"], [0, "²"], [0, "³"], [0, "´"], [0, "µ"], [0, "¶"], [0, "·"], [0, "¸"], [0, "¹"], [0, "º"], [0, "»"], [0, "¼"], [0, "½"], [0, "¾"], [0, "¿"], [0, "À"], [0, "Á"], [0, "Â"], [0, "Ã"], [0, "Ä"], [0, "Å"], [0, "Æ"], [0, "Ç"], [0, "È"], [0, "É"], [0, "Ê"], [0, "Ë"], [0, "Ì"], [0, "Í"], [0, "Î"], [0, "Ï"], [0, "Ð"], [0, "Ñ"], [0, "Ò"], [0, "Ó"], [0, "Ô"], [0, "Õ"], [0, "Ö"], [0, "×"], [0, "Ø"], [0, "Ù"], [0, "Ú"], [0, "Û"], [0, "Ü"], [0, "Ý"], [0, "Þ"], [0, "ß"], [0, "à"], [0, "á"], [0, "â"], [0, "ã"], [0, "ä"], [0, "å"], [0, "æ"], [0, "ç"], [0, "è"], [0, "é"], [0, "ê"], [0, "ë"], [0, "ì"], [0, "í"], [0, "î"], [0, "ï"], [0, "ð"], [0, "ñ"], [0, "ò"], [0, "ó"], [0, "ô"], [0, "õ"], [0, "ö"], [0, "÷"], [0, "ø"], [0, "ù"], [0, "ú"], [0, "û"], [0, "ü"], [0, "ý"], [0, "þ"], [0, "ÿ"], [0, "Ā"], [0, "ā"], [0, "Ă"], [0, "ă"], [0, "Ą"], [0, "ą"], [0, "Ć"], [0, "ć"], [0, "Ĉ"], [0, "ĉ"], [0, "Ċ"], [0, "ċ"], [0, "Č"], [0, "č"], [0, "Ď"], [0, "ď"], [0, "Đ"], [0, "đ"], [0, "Ē"], [0, "ē"], [2, "Ė"], [0, "ė"], [0, "Ę"], [0, "ę"], [0, "Ě"], [0, "ě"], [0, "Ĝ"], [0, "ĝ"], [0, "Ğ"], [0, "ğ"], [0, "Ġ"], [0, "ġ"], [0, "Ģ"], [1, "Ĥ"], [0, "ĥ"], [0, "Ħ"], [0, "ħ"], [0, "Ĩ"], [0, "ĩ"], [0, "Ī"], [0, "ī"], [2, "Į"], [0, "į"], [0, "İ"], [0, "ı"], [0, "IJ"], [0, "ij"], [0, "Ĵ"], [0, "ĵ"], [0, "Ķ"], [0, "ķ"], [0, "ĸ"], [0, "Ĺ"], [0, "ĺ"], [0, "Ļ"], [0, "ļ"], [0, "Ľ"], [0, "ľ"], [0, "Ŀ"], [0, "ŀ"], [0, "Ł"], [0, "ł"], [0, "Ń"], [0, "ń"], [0, "Ņ"], [0, "ņ"], [0, "Ň"], [0, "ň"], [0, "ʼn"], [0, "Ŋ"], [0, "ŋ"], [0, "Ō"], [0, "ō"], [2, "Ő"], [0, "ő"], [0, "Œ"], [0, "œ"], [0, "Ŕ"], [0, "ŕ"], [0, "Ŗ"], [0, "ŗ"], [0, "Ř"], [0, "ř"], [0, "Ś"], [0, "ś"], [0, "Ŝ"], [0, "ŝ"], [0, "Ş"], [0, "ş"], [0, "Š"], [0, "š"], [0, "Ţ"], [0, "ţ"], [0, "Ť"], [0, "ť"], [0, "Ŧ"], [0, "ŧ"], [0, "Ũ"], [0, "ũ"], [0, "Ū"], [0, "ū"], [0, "Ŭ"], [0, "ŭ"], [0, "Ů"], [0, "ů"], [0, "Ű"], [0, "ű"], [0, "Ų"], [0, "ų"], [0, "Ŵ"], [0, "ŵ"], [0, "Ŷ"], [0, "ŷ"], [0, "Ÿ"], [0, "Ź"], [0, "ź"], [0, "Ż"], [0, "ż"], [0, "Ž"], [0, "ž"], [19, "ƒ"], [34, "Ƶ"], [63, "ǵ"], [65, "ȷ"], [142, "ˆ"], [0, "ˇ"], [16, "˘"], [0, "˙"], [0, "˚"], [0, "˛"], [0, "˜"], [0, "˝"], [51, "̑"], [127, "Α"], [0, "Β"], [0, "Γ"], [0, "Δ"], [0, "Ε"], [0, "Ζ"], [0, "Η"], [0, "Θ"], [0, "Ι"], [0, "Κ"], [0, "Λ"], [0, "Μ"], [0, "Ν"], [0, "Ξ"], [0, "Ο"], [0, "Π"], [0, "Ρ"], [1, "Σ"], [0, "Τ"], [0, "Υ"], [0, "Φ"], [0, "Χ"], [0, "Ψ"], [0, "Ω"], [7, "α"], [0, "β"], [0, "γ"], [0, "δ"], [0, "ε"], [0, "ζ"], [0, "η"], [0, "θ"], [0, "ι"], [0, "κ"], [0, "λ"], [0, "μ"], [0, "ν"], [0, "ξ"], [0, "ο"], [0, "π"], [0, "ρ"], [0, "ς"], [0, "σ"], [0, "τ"], [0, "υ"], [0, "φ"], [0, "χ"], [0, "ψ"], [0, "ω"], [7, "ϑ"], [0, "ϒ"], [2, "ϕ"], [0, "ϖ"], [5, "Ϝ"], [0, "ϝ"], [18, "ϰ"], [0, "ϱ"], [3, "ϵ"], [0, "϶"], [10, "Ё"], [0, "Ђ"], [0, "Ѓ"], [0, "Є"], [0, "Ѕ"], [0, "І"], [0, "Ї"], [0, "Ј"], [0, "Љ"], [0, "Њ"], [0, "Ћ"], [0, "Ќ"], [1, "Ў"], [0, "Џ"], [0, "А"], [0, "Б"], [0, "В"], [0, "Г"], [0, "Д"], [0, "Е"], [0, "Ж"], [0, "З"], [0, "И"], [0, "Й"], [0, "К"], [0, "Л"], [0, "М"], [0, "Н"], [0, "О"], [0, "П"], [0, "Р"], [0, "С"], [0, "Т"], [0, "У"], [0, "Ф"], [0, "Х"], [0, "Ц"], [0, "Ч"], [0, "Ш"], [0, "Щ"], [0, "Ъ"], [0, "Ы"], [0, "Ь"], [0, "Э"], [0, "Ю"], [0, "Я"], [0, "а"], [0, "б"], [0, "в"], [0, "г"], [0, "д"], [0, "е"], [0, "ж"], [0, "з"], [0, "и"], [0, "й"], [0, "к"], [0, "л"], [0, "м"], [0, "н"], [0, "о"], [0, "п"], [0, "р"], [0, "с"], [0, "т"], [0, "у"], [0, "ф"], [0, "х"], [0, "ц"], [0, "ч"], [0, "ш"], [0, "щ"], [0, "ъ"], [0, "ы"], [0, "ь"], [0, "э"], [0, "ю"], [0, "я"], [1, "ё"], [0, "ђ"], [0, "ѓ"], [0, "є"], [0, "ѕ"], [0, "і"], [0, "ї"], [0, "ј"], [0, "љ"], [0, "њ"], [0, "ћ"], [0, "ќ"], [1, "ў"], [0, "џ"], [7074, " "], [0, " "], [0, " "], [0, " "], [1, " "], [0, " "], [0, " "], [0, " "], [0, "​"], [0, "‌"], [0, "‍"], [0, "‎"], [0, "‏"], [0, "‐"], [2, "–"], [0, "—"], [0, "―"], [0, "‖"], [1, "‘"], [0, "’"], [0, "‚"], [1, "“"], [0, "”"], [0, "„"], [1, "†"], [0, "‡"], [0, "•"], [2, "‥"], [0, "…"], [9, "‰"], [0, "‱"], [0, "′"], [0, "″"], [0, "‴"], [0, "‵"], [3, "‹"], [0, "›"], [3, "‾"], [2, "⁁"], [1, "⁃"], [0, "⁄"], [10, "⁏"], [7, "⁗"], [7, { v: " ", n: 8202, o: "  " }], [0, "⁠"], [0, "⁡"], [0, "⁢"], [0, "⁣"], [72, "€"], [46, "⃛"], [0, "⃜"], [37, "ℂ"], [2, "℅"], [4, "ℊ"], [0, "ℋ"], [0, "ℌ"], [0, "ℍ"], [0, "ℎ"], [0, "ℏ"], [0, "ℐ"], [0, "ℑ"], [0, "ℒ"], [0, "ℓ"], [1, "ℕ"], [0, "№"], [0, "℗"], [0, "℘"], [0, "ℙ"], [0, "ℚ"], [0, "ℛ"], [0, "ℜ"], [0, "ℝ"], [0, "℞"], [3, "™"], [1, "ℤ"], [2, "℧"], [0, "ℨ"], [0, "℩"], [2, "ℬ"], [0, "ℭ"], [1, "ℯ"], [0, "ℰ"], [0, "ℱ"], [1, "ℳ"], [0, "ℴ"], [0, "ℵ"], [0, "ℶ"], [0, "ℷ"], [0, "ℸ"], [12, "ⅅ"], [0, "ⅆ"], [0, "ⅇ"], [0, "ⅈ"], [10, "⅓"], [0, "⅔"], [0, "⅕"], [0, "⅖"], [0, "⅗"], [0, "⅘"], [0, "⅙"], [0, "⅚"], [0, "⅛"], [0, "⅜"], [0, "⅝"], [0, "⅞"], [49, "←"], [0, "↑"], [0, "→"], [0, "↓"], [0, "↔"], [0, "↕"], [0, "↖"], [0, "↗"], [0, "↘"], [0, "↙"], [0, "↚"], [0, "↛"], [1, { v: "↝", n: 824, o: "↝̸" }], [0, "↞"], [0, "↟"], [0, "↠"], [0, "↡"], [0, "↢"], [0, "↣"], [0, "↤"], [0, "↥"], [0, "↦"], [0, "↧"], [1, "↩"], [0, "↪"], [0, "↫"], [0, "↬"], [0, "↭"], [0, "↮"], [1, "↰"], [0, "↱"], [0, "↲"], [0, "↳"], [1, "↵"], [0, "↶"], [0, "↷"], [2, "↺"], [0, "↻"], [0, "↼"], [0, "↽"], [0, "↾"], [0, "↿"], [0, "⇀"], [0, "⇁"], [0, "⇂"], [0, "⇃"], [0, "⇄"], [0, "⇅"], [0, "⇆"], [0, "⇇"], [0, "⇈"], [0, "⇉"], [0, "⇊"], [0, "⇋"], [0, "⇌"], [0, "⇍"], [0, "⇎"], [0, "⇏"], [0, "⇐"], [0, "⇑"], [0, "⇒"], [0, "⇓"], [0, "⇔"], [0, "⇕"], [0, "⇖"], [0, "⇗"], [0, "⇘"], [0, "⇙"], [0, "⇚"], [0, "⇛"], [1, "⇝"], [6, "⇤"], [0, "⇥"], [15, "⇵"], [7, "⇽"], [0, "⇾"], [0, "⇿"], [0, "∀"], [0, "∁"], [0, { v: "∂", n: 824, o: "∂̸" }], [0, "∃"], [0, "∄"], [0, "∅"], [1, "∇"], [0, "∈"], [0, "∉"], [1, "∋"], [0, "∌"], [2, "∏"], [0, "∐"], [0, "∑"], [0, "−"], [0, "∓"], [0, "∔"], [1, "∖"], [0, "∗"], [0, "∘"], [1, "√"], [2, "∝"], [0, "∞"], [0, "∟"], [0, { v: "∠", n: 8402, o: "∠⃒" }], [0, "∡"], [0, "∢"], [0, "∣"], [0, "∤"], [0, "∥"], [0, "∦"], [0, "∧"], [0, "∨"], [0, { v: "∩", n: 65024, o: "∩︀" }], [0, { v: "∪", n: 65024, o: "∪︀" }], [0, "∫"], [0, "∬"], [0, "∭"], [0, "∮"], [0, "∯"], [0, "∰"], [0, "∱"], [0, "∲"], [0, "∳"], [0, "∴"], [0, "∵"], [0, "∶"], [0, "∷"], [0, "∸"], [1, "∺"], [0, "∻"], [0, { v: "∼", n: 8402, o: "∼⃒" }], [0, { v: "∽", n: 817, o: "∽̱" }], [0, { v: "∾", n: 819, o: "∾̳" }], [0, "∿"], [0, "≀"], [0, "≁"], [0, { v: "≂", n: 824, o: "≂̸" }], [0, "≃"], [0, "≄"], [0, "≅"], [0, "≆"], [0, "≇"], [0, "≈"], [0, "≉"], [0, "≊"], [0, { v: "≋", n: 824, o: "≋̸" }], [0, "≌"], [0, { v: "≍", n: 8402, o: "≍⃒" }], [0, { v: "≎", n: 824, o: "≎̸" }], [0, { v: "≏", n: 824, o: "≏̸" }], [0, { v: "≐", n: 824, o: "≐̸" }], [0, "≑"], [0, "≒"], [0, "≓"], [0, "≔"], [0, "≕"], [0, "≖"], [0, "≗"], [1, "≙"], [0, "≚"], [1, "≜"], [2, "≟"], [0, "≠"], [0, { v: "≡", n: 8421, o: "≡⃥" }], [0, "≢"], [1, { v: "≤", n: 8402, o: "≤⃒" }], [0, { v: "≥", n: 8402, o: "≥⃒" }], [0, { v: "≦", n: 824, o: "≦̸" }], [0, { v: "≧", n: 824, o: "≧̸" }], [0, { v: "≨", n: 65024, o: "≨︀" }], [0, { v: "≩", n: 65024, o: "≩︀" }], [0, { v: "≪", n: new Map(/* #__PURE__ */ restoreDiff([[824, "≪̸"], [7577, "≪⃒"]])) }], [0, { v: "≫", n: new Map(/* #__PURE__ */ restoreDiff([[824, "≫̸"], [7577, "≫⃒"]])) }], [0, "≬"], [0, "≭"], [0, "≮"], [0, "≯"], [0, "≰"], [0, "≱"], [0, "≲"], [0, "≳"], [0, "≴"], [0, "≵"], [0, "≶"], [0, "≷"], [0, "≸"], [0, "≹"], [0, "≺"], [0, "≻"], [0, "≼"], [0, "≽"], [0, "≾"], [0, { v: "≿", n: 824, o: "≿̸" }], [0, "⊀"], [0, "⊁"], [0, { v: "⊂", n: 8402, o: "⊂⃒" }], [0, { v: "⊃", n: 8402, o: "⊃⃒" }], [0, "⊄"], [0, "⊅"], [0, "⊆"], [0, "⊇"], [0, "⊈"], [0, "⊉"], [0, { v: "⊊", n: 65024, o: "⊊︀" }], [0, { v: "⊋", n: 65024, o: "⊋︀" }], [1, "⊍"], [0, "⊎"], [0, { v: "⊏", n: 824, o: "⊏̸" }], [0, { v: "⊐", n: 824, o: "⊐̸" }], [0, "⊑"], [0, "⊒"], [0, { v: "⊓", n: 65024, o: "⊓︀" }], [0, { v: "⊔", n: 65024, o: "⊔︀" }], [0, "⊕"], [0, "⊖"], [0, "⊗"], [0, "⊘"], [0, "⊙"], [0, "⊚"], [0, "⊛"], [1, "⊝"], [0, "⊞"], [0, "⊟"], [0, "⊠"], [0, "⊡"], [0, "⊢"], [0, "⊣"], [0, "⊤"], [0, "⊥"], [1, "⊧"], [0, "⊨"], [0, "⊩"], [0, "⊪"], [0, "⊫"], [0, "⊬"], [0, "⊭"], [0, "⊮"], [0, "⊯"], [0, "⊰"], [1, "⊲"], [0, "⊳"], [0, { v: "⊴", n: 8402, o: "⊴⃒" }], [0, { v: "⊵", n: 8402, o: "⊵⃒" }], [0, "⊶"], [0, "⊷"], [0, "⊸"], [0, "⊹"], [0, "⊺"], [0, "⊻"], [1, "⊽"], [0, "⊾"], [0, "⊿"], [0, "⋀"], [0, "⋁"], [0, "⋂"], [0, "⋃"], [0, "⋄"], [0, "⋅"], [0, "⋆"], [0, "⋇"], [0, "⋈"], [0, "⋉"], [0, "⋊"], [0, "⋋"], [0, "⋌"], [0, "⋍"], [0, "⋎"], [0, "⋏"], [0, "⋐"], [0, "⋑"], [0, "⋒"], [0, "⋓"], [0, "⋔"], [0, "⋕"], [0, "⋖"], [0, "⋗"], [0, { v: "⋘", n: 824, o: "⋘̸" }], [0, { v: "⋙", n: 824, o: "⋙̸" }], [0, { v: "⋚", n: 65024, o: "⋚︀" }], [0, { v: "⋛", n: 65024, o: "⋛︀" }], [2, "⋞"], [0, "⋟"], [0, "⋠"], [0, "⋡"], [0, "⋢"], [0, "⋣"], [2, "⋦"], [0, "⋧"], [0, "⋨"], [0, "⋩"], [0, "⋪"], [0, "⋫"], [0, "⋬"], [0, "⋭"], [0, "⋮"], [0, "⋯"], [0, "⋰"], [0, "⋱"], [0, "⋲"], [0, "⋳"], [0, "⋴"], [0, { v: "⋵", n: 824, o: "⋵̸" }], [0, "⋶"], [0, "⋷"], [1, { v: "⋹", n: 824, o: "⋹̸" }], [0, "⋺"], [0, "⋻"], [0, "⋼"], [0, "⋽"], [0, "⋾"], [6, "⌅"], [0, "⌆"], [1, "⌈"], [0, "⌉"], [0, "⌊"], [0, "⌋"], [0, "⌌"], [0, "⌍"], [0, "⌎"], [0, "⌏"], [0, "⌐"], [1, "⌒"], [0, "⌓"], [1, "⌕"], [0, "⌖"], [5, "⌜"], [0, "⌝"], [0, "⌞"], [0, "⌟"], [2, "⌢"], [0, "⌣"], [9, "⌭"], [0, "⌮"], [7, "⌶"], [6, "⌽"], [1, "⌿"], [60, "⍼"], [51, "⎰"], [0, "⎱"], [2, "⎴"], [0, "⎵"], [0, "⎶"], [37, "⏜"], [0, "⏝"], [0, "⏞"], [0, "⏟"], [2, "⏢"], [4, "⏧"], [59, "␣"], [164, "Ⓢ"], [55, "─"], [1, "│"], [9, "┌"], [3, "┐"], [3, "└"], [3, "┘"], [3, "├"], [7, "┤"], [7, "┬"], [7, "┴"], [7, "┼"], [19, "═"], [0, "║"], [0, "╒"], [0, "╓"], [0, "╔"], [0, "╕"], [0, "╖"], [0, "╗"], [0, "╘"], [0, "╙"], [0, "╚"], [0, "╛"], [0, "╜"], [0, "╝"], [0, "╞"], [0, "╟"], [0, "╠"], [0, "╡"], [0, "╢"], [0, "╣"], [0, "╤"], [0, "╥"], [0, "╦"], [0, "╧"], [0, "╨"], [0, "╩"], [0, "╪"], [0, "╫"], [0, "╬"], [19, "▀"], [3, "▄"], [3, "█"], [8, "░"], [0, "▒"], [0, "▓"], [13, "□"], [8, "▪"], [0, "▫"], [1, "▭"], [0, "▮"], [2, "▱"], [1, "△"], [0, "▴"], [0, "▵"], [2, "▸"], [0, "▹"], [3, "▽"], [0, "▾"], [0, "▿"], [2, "◂"], [0, "◃"], [6, "◊"], [0, "○"], [32, "◬"], [2, "◯"], [8, "◸"], [0, "◹"], [0, "◺"], [0, "◻"], [0, "◼"], [8, "★"], [0, "☆"], [7, "☎"], [49, "♀"], [1, "♂"], [29, "♠"], [2, "♣"], [1, "♥"], [0, "♦"], [3, "♪"], [2, "♭"], [0, "♮"], [0, "♯"], [163, "✓"], [3, "✗"], [8, "✠"], [21, "✶"], [33, "❘"], [25, "❲"], [0, "❳"], [84, "⟈"], [0, "⟉"], [28, "⟦"], [0, "⟧"], [0, "⟨"], [0, "⟩"], [0, "⟪"], [0, "⟫"], [0, "⟬"], [0, "⟭"], [7, "⟵"], [0, "⟶"], [0, "⟷"], [0, "⟸"], [0, "⟹"], [0, "⟺"], [1, "⟼"], [2, "⟿"], [258, "⤂"], [0, "⤃"], [0, "⤄"], [0, "⤅"], [6, "⤌"], [0, "⤍"], [0, "⤎"], [0, "⤏"], [0, "⤐"], [0, "⤑"], [0, "⤒"], [0, "⤓"], [2, "⤖"], [2, "⤙"], [0, "⤚"], [0, "⤛"], [0, "⤜"], [0, "⤝"], [0, "⤞"], [0, "⤟"], [0, "⤠"], [2, "⤣"], [0, "⤤"], [0, "⤥"], [0, "⤦"], [0, "⤧"], [0, "⤨"], [0, "⤩"], [0, "⤪"], [8, { v: "⤳", n: 824, o: "⤳̸" }], [1, "⤵"], [0, "⤶"], [0, "⤷"], [0, "⤸"], [0, "⤹"], [2, "⤼"], [0, "⤽"], [7, "⥅"], [2, "⥈"], [0, "⥉"], [0, "⥊"], [0, "⥋"], [2, "⥎"], [0, "⥏"], [0, "⥐"], [0, "⥑"], [0, "⥒"], [0, "⥓"], [0, "⥔"], [0, "⥕"], [0, "⥖"], [0, "⥗"], [0, "⥘"], [0, "⥙"], [0, "⥚"], [0, "⥛"], [0, "⥜"], [0, "⥝"], [0, "⥞"], [0, "⥟"], [0, "⥠"], [0, "⥡"], [0, "⥢"], [0, "⥣"], [0, "⥤"], [0, "⥥"], [0, "⥦"], [0, "⥧"], [0, "⥨"], [0, "⥩"], [0, "⥪"], [0, "⥫"], [0, "⥬"], [0, "⥭"], [0, "⥮"], [0, "⥯"], [0, "⥰"], [0, "⥱"], [0, "⥲"], [0, "⥳"], [0, "⥴"], [0, "⥵"], [0, "⥶"], [1, "⥸"], [0, "⥹"], [1, "⥻"], [0, "⥼"], [0, "⥽"], [0, "⥾"], [0, "⥿"], [5, "⦅"], [0, "⦆"], [4, "⦋"], [0, "⦌"], [0, "⦍"], [0, "⦎"], [0, "⦏"], [0, "⦐"], [0, "⦑"], [0, "⦒"], [0, "⦓"], [0, "⦔"], [0, "⦕"], [0, "⦖"], [3, "⦚"], [1, "⦜"], [0, "⦝"], [6, "⦤"], [0, "⦥"], [0, "⦦"], [0, "⦧"], [0, "⦨"], [0, "⦩"], [0, "⦪"], [0, "⦫"], [0, "⦬"], [0, "⦭"], [0, "⦮"], [0, "⦯"], [0, "⦰"], [0, "⦱"], [0, "⦲"], [0, "⦳"], [0, "⦴"], [0, "⦵"], [0, "⦶"], [0, "⦷"], [1, "⦹"], [1, "⦻"], [0, "⦼"], [1, "⦾"], [0, "⦿"], [0, "⧀"], [0, "⧁"], [0, "⧂"], [0, "⧃"], [0, "⧄"], [0, "⧅"], [3, "⧉"], [3, "⧍"], [0, "⧎"], [0, { v: "⧏", n: 824, o: "⧏̸" }], [0, { v: "⧐", n: 824, o: "⧐̸" }], [11, "⧜"], [0, "⧝"], [0, "⧞"], [4, "⧣"], [0, "⧤"], [0, "⧥"], [5, "⧫"], [8, "⧴"], [1, "⧶"], [9, "⨀"], [0, "⨁"], [0, "⨂"], [1, "⨄"], [1, "⨆"], [5, "⨌"], [0, "⨍"], [2, "⨐"], [0, "⨑"], [0, "⨒"], [0, "⨓"], [0, "⨔"], [0, "⨕"], [0, "⨖"], [0, "⨗"], [10, "⨢"], [0, "⨣"], [0, "⨤"], [0, "⨥"], [0, "⨦"], [0, "⨧"], [1, "⨩"], [0, "⨪"], [2, "⨭"], [0, "⨮"], [0, "⨯"], [0, "⨰"], [0, "⨱"], [1, "⨳"], [0, "⨴"], [0, "⨵"], [0, "⨶"], [0, "⨷"], [0, "⨸"], [0, "⨹"], [0, "⨺"], [0, "⨻"], [0, "⨼"], [2, "⨿"], [0, "⩀"], [1, "⩂"], [0, "⩃"], [0, "⩄"], [0, "⩅"], [0, "⩆"], [0, "⩇"], [0, "⩈"], [0, "⩉"], [0, "⩊"], [0, "⩋"], [0, "⩌"], [0, "⩍"], [2, "⩐"], [2, "⩓"], [0, "⩔"], [0, "⩕"], [0, "⩖"], [0, "⩗"], [0, "⩘"], [1, "⩚"], [0, "⩛"], [0, "⩜"], [0, "⩝"], [1, "⩟"], [6, "⩦"], [3, "⩪"], [2, { v: "⩭", n: 824, o: "⩭̸" }], [0, "⩮"], [0, "⩯"], [0, { v: "⩰", n: 824, o: "⩰̸" }], [0, "⩱"], [0, "⩲"], [0, "⩳"], [0, "⩴"], [0, "⩵"], [1, "⩷"], [0, "⩸"], [0, "⩹"], [0, "⩺"], [0, "⩻"], [0, "⩼"], [0, { v: "⩽", n: 824, o: "⩽̸" }], [0, { v: "⩾", n: 824, o: "⩾̸" }], [0, "⩿"], [0, "⪀"], [0, "⪁"], [0, "⪂"], [0, "⪃"], [0, "⪄"], [0, "⪅"], [0, "⪆"], [0, "⪇"], [0, "⪈"], [0, "⪉"], [0, "⪊"], [0, "⪋"], [0, "⪌"], [0, "⪍"], [0, "⪎"], [0, "⪏"], [0, "⪐"], [0, "⪑"], [0, "⪒"], [0, "⪓"], [0, "⪔"], [0, "⪕"], [0, "⪖"], [0, "⪗"], [0, "⪘"], [0, "⪙"], [0, "⪚"], [2, "⪝"], [0, "⪞"], [0, "⪟"], [0, "⪠"], [0, { v: "⪡", n: 824, o: "⪡̸" }], [0, { v: "⪢", n: 824, o: "⪢̸" }], [1, "⪤"], [0, "⪥"], [0, "⪦"], [0, "⪧"], [0, "⪨"], [0, "⪩"], [0, "⪪"], [0, "⪫"], [0, { v: "⪬", n: 65024, o: "⪬︀" }], [0, { v: "⪭", n: 65024, o: "⪭︀" }], [0, "⪮"], [0, { v: "⪯", n: 824, o: "⪯̸" }], [0, { v: "⪰", n: 824, o: "⪰̸" }], [2, "⪳"], [0, "⪴"], [0, "⪵"], [0, "⪶"], [0, "⪷"], [0, "⪸"], [0, "⪹"], [0, "⪺"], [0, "⪻"], [0, "⪼"], [0, "⪽"], [0, "⪾"], [0, "⪿"], [0, "⫀"], [0, "⫁"], [0, "⫂"], [0, "⫃"], [0, "⫄"], [0, { v: "⫅", n: 824, o: "⫅̸" }], [0, { v: "⫆", n: 824, o: "⫆̸" }], [0, "⫇"], [0, "⫈"], [2, { v: "⫋", n: 65024, o: "⫋︀" }], [0, { v: "⫌", n: 65024, o: "⫌︀" }], [2, "⫏"], [0, "⫐"], [0, "⫑"], [0, "⫒"], [0, "⫓"], [0, "⫔"], [0, "⫕"], [0, "⫖"], [0, "⫗"], [0, "⫘"], [0, "⫙"], [0, "⫚"], [0, "⫛"], [8, "⫤"], [1, "⫦"], [0, "⫧"], [0, "⫨"], [0, "⫩"], [1, "⫫"], [0, "⫬"], [0, "⫭"], [0, "⫮"], [0, "⫯"], [0, "⫰"], [0, "⫱"], [0, "⫲"], [0, "⫳"], [9, { v: "⫽", n: 8421, o: "⫽⃥" }], [44343, { n: new Map(/* #__PURE__ */ restoreDiff([[56476, "𝒜"], [1, "𝒞"], [0, "𝒟"], [2, "𝒢"], [2, "𝒥"], [0, "𝒦"], [2, "𝒩"], [0, "𝒪"], [0, "𝒫"], [0, "𝒬"], [1, "𝒮"], [0, "𝒯"], [0, "𝒰"], [0, "𝒱"], [0, "𝒲"], [0, "𝒳"], [0, "𝒴"], [0, "𝒵"], [0, "𝒶"], [0, "𝒷"], [0, "𝒸"], [0, "𝒹"], [1, "𝒻"], [1, "𝒽"], [0, "𝒾"], [0, "𝒿"], [0, "𝓀"], [0, "𝓁"], [0, "𝓂"], [0, "𝓃"], [1, "𝓅"], [0, "𝓆"], [0, "𝓇"], [0, "𝓈"], [0, "𝓉"], [0, "𝓊"], [0, "𝓋"], [0, "𝓌"], [0, "𝓍"], [0, "𝓎"], [0, "𝓏"], [52, "𝔄"], [0, "𝔅"], [1, "𝔇"], [0, "𝔈"], [0, "𝔉"], [0, "𝔊"], [2, "𝔍"], [0, "𝔎"], [0, "𝔏"], [0, "𝔐"], [0, "𝔑"], [0, "𝔒"], [0, "𝔓"], [0, "𝔔"], [1, "𝔖"], [0, "𝔗"], [0, "𝔘"], [0, "𝔙"], [0, "𝔚"], [0, "𝔛"], [0, "𝔜"], [1, "𝔞"], [0, "𝔟"], [0, "𝔠"], [0, "𝔡"], [0, "𝔢"], [0, "𝔣"], [0, "𝔤"], [0, "𝔥"], [0, "𝔦"], [0, "𝔧"], [0, "𝔨"], [0, "𝔩"], [0, "𝔪"], [0, "𝔫"], [0, "𝔬"], [0, "𝔭"], [0, "𝔮"], [0, "𝔯"], [0, "𝔰"], [0, "𝔱"], [0, "𝔲"], [0, "𝔳"], [0, "𝔴"], [0, "𝔵"], [0, "𝔶"], [0, "𝔷"], [0, "𝔸"], [0, "𝔹"], [1, "𝔻"], [0, "𝔼"], [0, "𝔽"], [0, "𝔾"], [1, "𝕀"], [0, "𝕁"], [0, "𝕂"], [0, "𝕃"], [0, "𝕄"], [1, "𝕆"], [3, "𝕊"], [0, "𝕋"], [0, "𝕌"], [0, "𝕍"], [0, "𝕎"], [0, "𝕏"], [0, "𝕐"], [1, "𝕒"], [0, "𝕓"], [0, "𝕔"], [0, "𝕕"], [0, "𝕖"], [0, "𝕗"], [0, "𝕘"], [0, "𝕙"], [0, "𝕚"], [0, "𝕛"], [0, "𝕜"], [0, "𝕝"], [0, "𝕞"], [0, "𝕟"], [0, "𝕠"], [0, "𝕡"], [0, "𝕢"], [0, "𝕣"], [0, "𝕤"], [0, "𝕥"], [0, "𝕦"], [0, "𝕧"], [0, "𝕨"], [0, "𝕩"], [0, "𝕪"], [0, "𝕫"]])) }], [8906, "ff"], [0, "fi"], [0, "fl"], [0, "ffi"], [0, "ffl"]])); + + var _escape = {}; + + (function (exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + exports.escapeText = exports.escapeAttribute = exports.escapeUTF8 = exports.escape = exports.encodeXML = exports.getCodePoint = exports.xmlReplacer = void 0; + exports.xmlReplacer = /["&'<>$\x80-\uFFFF]/g; + var xmlCodeMap = new Map([ + [34, """], + [38, "&"], + [39, "'"], + [60, "<"], + [62, ">"], + ]); + // For compatibility with node < 4, we wrap `codePointAt` + exports.getCodePoint = + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + String.prototype.codePointAt != null + ? function (str, index) { return str.codePointAt(index); } + : // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + function (c, index) { + return (c.charCodeAt(index) & 0xfc00) === 0xd800 + ? (c.charCodeAt(index) - 0xd800) * 0x400 + + c.charCodeAt(index + 1) - + 0xdc00 + + 0x10000 + : c.charCodeAt(index); + }; + /** + * Encodes all non-ASCII characters, as well as characters not valid in XML + * documents using XML entities. + * + * If a character has no equivalent entity, a + * numeric hexadecimal reference (eg. `ü`) will be used. + */ + function encodeXML(str) { + var ret = ""; + var lastIdx = 0; + var match; + while ((match = exports.xmlReplacer.exec(str)) !== null) { + var i = match.index; + var char = str.charCodeAt(i); + var next = xmlCodeMap.get(char); + if (next !== undefined) { + ret += str.substring(lastIdx, i) + next; + lastIdx = i + 1; + } + else { + ret += "".concat(str.substring(lastIdx, i), "&#x").concat((0, exports.getCodePoint)(str, i).toString(16), ";"); + // Increase by 1 if we have a surrogate pair + lastIdx = exports.xmlReplacer.lastIndex += Number((char & 0xfc00) === 0xd800); + } + } + return ret + str.substr(lastIdx); + } + exports.encodeXML = encodeXML; + /** + * Encodes all non-ASCII characters, as well as characters not valid in XML + * documents using numeric hexadecimal reference (eg. `ü`). + * + * Have a look at `escapeUTF8` if you want a more concise output at the expense + * of reduced transportability. + * + * @param data String to escape. + */ + exports.escape = encodeXML; + /** + * Creates a function that escapes all characters matched by the given regular + * expression using the given map of characters to escape to their entities. + * + * @param regex Regular expression to match characters to escape. + * @param map Map of characters to escape to their entities. + * + * @returns Function that escapes all characters matched by the given regular + * expression using the given map of characters to escape to their entities. + */ + function getEscaper(regex, map) { + return function escape(data) { + var match; + var lastIdx = 0; + var result = ""; + while ((match = regex.exec(data))) { + if (lastIdx !== match.index) { + result += data.substring(lastIdx, match.index); + } + // We know that this character will be in the map. + result += map.get(match[0].charCodeAt(0)); + // Every match will be of length 1 + lastIdx = match.index + 1; + } + return result + data.substring(lastIdx); + }; + } + /** + * Encodes all characters not valid in XML documents using XML entities. + * + * Note that the output will be character-set dependent. + * + * @param data String to escape. + */ + exports.escapeUTF8 = getEscaper(/[&<>'"]/g, xmlCodeMap); + /** + * Encodes all characters that have to be escaped in HTML attributes, + * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}. + * + * @param data String to escape. + */ + exports.escapeAttribute = getEscaper(/["&\u00A0]/g, new Map([ + [34, """], + [38, "&"], + [160, " "], + ])); + /** + * Encodes all characters that have to be escaped in HTML text, + * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}. + * + * @param data String to escape. + */ + exports.escapeText = getEscaper(/[&<>\u00A0]/g, new Map([ + [38, "&"], + [60, "<"], + [62, ">"], + [160, " "], + ])); + + } (_escape)); + + var __importDefault$1 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + Object.defineProperty(encode$1, "__esModule", { value: true }); + encode$1.encodeNonAsciiHTML = encode$1.encodeHTML = void 0; + var encode_html_js_1 = __importDefault$1(encodeHtml); + var escape_js_1 = _escape; + var htmlReplacer = /[\t\n!-,./:-@[-`\f{-}$\x80-\uFFFF]/g; + /** + * Encodes all characters in the input using HTML entities. This includes + * characters that are valid ASCII characters in HTML documents, such as `#`. + * + * To get a more compact output, consider using the `encodeNonAsciiHTML` + * function, which will only encode characters that are not valid in HTML + * documents, as well as non-ASCII characters. + * + * If a character has no equivalent entity, a numeric hexadecimal reference + * (eg. `ü`) will be used. + */ + function encodeHTML(data) { + return encodeHTMLTrieRe(htmlReplacer, data); + } + encode$1.encodeHTML = encodeHTML; + /** + * Encodes all non-ASCII characters, as well as characters not valid in HTML + * documents using HTML entities. This function will not encode characters that + * are valid in HTML documents, such as `#`. + * + * If a character has no equivalent entity, a numeric hexadecimal reference + * (eg. `ü`) will be used. + */ + function encodeNonAsciiHTML(data) { + return encodeHTMLTrieRe(escape_js_1.xmlReplacer, data); + } + encode$1.encodeNonAsciiHTML = encodeNonAsciiHTML; + function encodeHTMLTrieRe(regExp, str) { + var ret = ""; + var lastIdx = 0; + var match; + while ((match = regExp.exec(str)) !== null) { + var i = match.index; + ret += str.substring(lastIdx, i); + var char = str.charCodeAt(i); + var next = encode_html_js_1.default.get(char); + if (typeof next === "object") { + // We are in a branch. Try to match the next char. + if (i + 1 < str.length) { + var nextChar = str.charCodeAt(i + 1); + var value = typeof next.n === "number" + ? next.n === nextChar + ? next.o + : undefined + : next.n.get(nextChar); + if (value !== undefined) { + ret += value; + lastIdx = regExp.lastIndex += 1; + continue; + } + } + next = next.v; + } + // We might have a tree node without a value; skip and use a numeric entity. + if (next !== undefined) { + ret += next; + lastIdx = i + 1; + } + else { + var cp = (0, escape_js_1.getCodePoint)(str, i); + ret += "&#x".concat(cp.toString(16), ";"); + // Increase by 1 if we have a surrogate pair + lastIdx = regExp.lastIndex += Number(cp !== char); + } + } + return ret + str.substr(lastIdx); + } + + (function (exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + exports.decodeXMLStrict = exports.decodeHTML5Strict = exports.decodeHTML4Strict = exports.decodeHTML5 = exports.decodeHTML4 = exports.decodeHTMLAttribute = exports.decodeHTMLStrict = exports.decodeHTML = exports.decodeXML = exports.DecodingMode = exports.EntityDecoder = exports.encodeHTML5 = exports.encodeHTML4 = exports.encodeNonAsciiHTML = exports.encodeHTML = exports.escapeText = exports.escapeAttribute = exports.escapeUTF8 = exports.escape = exports.encodeXML = exports.encode = exports.decodeStrict = exports.decode = exports.EncodingMode = exports.EntityLevel = void 0; + var decode_js_1 = decode; + var encode_js_1 = encode$1; + var escape_js_1 = _escape; + /** The level of entities to support. */ + var EntityLevel; + (function (EntityLevel) { + /** Support only XML entities. */ + EntityLevel[EntityLevel["XML"] = 0] = "XML"; + /** Support HTML entities, which are a superset of XML entities. */ + EntityLevel[EntityLevel["HTML"] = 1] = "HTML"; + })(EntityLevel = exports.EntityLevel || (exports.EntityLevel = {})); + var EncodingMode; + (function (EncodingMode) { + /** + * The output is UTF-8 encoded. Only characters that need escaping within + * XML will be escaped. + */ + EncodingMode[EncodingMode["UTF8"] = 0] = "UTF8"; + /** + * The output consists only of ASCII characters. Characters that need + * escaping within HTML, and characters that aren't ASCII characters will + * be escaped. + */ + EncodingMode[EncodingMode["ASCII"] = 1] = "ASCII"; + /** + * Encode all characters that have an equivalent entity, as well as all + * characters that are not ASCII characters. + */ + EncodingMode[EncodingMode["Extensive"] = 2] = "Extensive"; + /** + * Encode all characters that have to be escaped in HTML attributes, + * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}. + */ + EncodingMode[EncodingMode["Attribute"] = 3] = "Attribute"; + /** + * Encode all characters that have to be escaped in HTML text, + * following {@link https://html.spec.whatwg.org/multipage/parsing.html#escapingString}. + */ + EncodingMode[EncodingMode["Text"] = 4] = "Text"; + })(EncodingMode = exports.EncodingMode || (exports.EncodingMode = {})); + /** + * Decodes a string with entities. + * + * @param data String to decode. + * @param options Decoding options. + */ + function decode$1(data, options) { + if (options === void 0) { options = EntityLevel.XML; } + var level = typeof options === "number" ? options : options.level; + if (level === EntityLevel.HTML) { + var mode = typeof options === "object" ? options.mode : undefined; + return (0, decode_js_1.decodeHTML)(data, mode); + } + return (0, decode_js_1.decodeXML)(data); + } + exports.decode = decode$1; + /** + * Decodes a string with entities. Does not allow missing trailing semicolons for entities. + * + * @param data String to decode. + * @param options Decoding options. + * @deprecated Use `decode` with the `mode` set to `Strict`. + */ + function decodeStrict(data, options) { + var _a; + if (options === void 0) { options = EntityLevel.XML; } + var opts = typeof options === "number" ? { level: options } : options; + (_a = opts.mode) !== null && _a !== void 0 ? _a : (opts.mode = decode_js_1.DecodingMode.Strict); + return decode$1(data, opts); + } + exports.decodeStrict = decodeStrict; + /** + * Encodes a string with entities. + * + * @param data String to encode. + * @param options Encoding options. + */ + function encode(data, options) { + if (options === void 0) { options = EntityLevel.XML; } + var opts = typeof options === "number" ? { level: options } : options; + // Mode `UTF8` just escapes XML entities + if (opts.mode === EncodingMode.UTF8) + return (0, escape_js_1.escapeUTF8)(data); + if (opts.mode === EncodingMode.Attribute) + return (0, escape_js_1.escapeAttribute)(data); + if (opts.mode === EncodingMode.Text) + return (0, escape_js_1.escapeText)(data); + if (opts.level === EntityLevel.HTML) { + if (opts.mode === EncodingMode.ASCII) { + return (0, encode_js_1.encodeNonAsciiHTML)(data); + } + return (0, encode_js_1.encodeHTML)(data); + } + // ASCII and Extensive are equivalent + return (0, escape_js_1.encodeXML)(data); + } + exports.encode = encode; + var escape_js_2 = _escape; + Object.defineProperty(exports, "encodeXML", { enumerable: true, get: function () { return escape_js_2.encodeXML; } }); + Object.defineProperty(exports, "escape", { enumerable: true, get: function () { return escape_js_2.escape; } }); + Object.defineProperty(exports, "escapeUTF8", { enumerable: true, get: function () { return escape_js_2.escapeUTF8; } }); + Object.defineProperty(exports, "escapeAttribute", { enumerable: true, get: function () { return escape_js_2.escapeAttribute; } }); + Object.defineProperty(exports, "escapeText", { enumerable: true, get: function () { return escape_js_2.escapeText; } }); + var encode_js_2 = encode$1; + Object.defineProperty(exports, "encodeHTML", { enumerable: true, get: function () { return encode_js_2.encodeHTML; } }); + Object.defineProperty(exports, "encodeNonAsciiHTML", { enumerable: true, get: function () { return encode_js_2.encodeNonAsciiHTML; } }); + // Legacy aliases (deprecated) + Object.defineProperty(exports, "encodeHTML4", { enumerable: true, get: function () { return encode_js_2.encodeHTML; } }); + Object.defineProperty(exports, "encodeHTML5", { enumerable: true, get: function () { return encode_js_2.encodeHTML; } }); + var decode_js_2 = decode; + Object.defineProperty(exports, "EntityDecoder", { enumerable: true, get: function () { return decode_js_2.EntityDecoder; } }); + Object.defineProperty(exports, "DecodingMode", { enumerable: true, get: function () { return decode_js_2.DecodingMode; } }); + Object.defineProperty(exports, "decodeXML", { enumerable: true, get: function () { return decode_js_2.decodeXML; } }); + Object.defineProperty(exports, "decodeHTML", { enumerable: true, get: function () { return decode_js_2.decodeHTML; } }); + Object.defineProperty(exports, "decodeHTMLStrict", { enumerable: true, get: function () { return decode_js_2.decodeHTMLStrict; } }); + Object.defineProperty(exports, "decodeHTMLAttribute", { enumerable: true, get: function () { return decode_js_2.decodeHTMLAttribute; } }); + // Legacy aliases (deprecated) + Object.defineProperty(exports, "decodeHTML4", { enumerable: true, get: function () { return decode_js_2.decodeHTML; } }); + Object.defineProperty(exports, "decodeHTML5", { enumerable: true, get: function () { return decode_js_2.decodeHTML; } }); + Object.defineProperty(exports, "decodeHTML4Strict", { enumerable: true, get: function () { return decode_js_2.decodeHTMLStrict; } }); + Object.defineProperty(exports, "decodeHTML5Strict", { enumerable: true, get: function () { return decode_js_2.decodeHTMLStrict; } }); + Object.defineProperty(exports, "decodeXMLStrict", { enumerable: true, get: function () { return decode_js_2.decodeXML; } }); + + } (lib)); + + var foreignNames = {}; + + Object.defineProperty(foreignNames, "__esModule", { value: true }); + foreignNames.attributeNames = foreignNames.elementNames = void 0; + foreignNames.elementNames = new Map([ + "altGlyph", + "altGlyphDef", + "altGlyphItem", + "animateColor", + "animateMotion", + "animateTransform", + "clipPath", + "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", + "foreignObject", + "glyphRef", + "linearGradient", + "radialGradient", + "textPath", + ].map(function (val) { return [val.toLowerCase(), val]; })); + foreignNames.attributeNames = new Map([ + "definitionURL", + "attributeName", + "attributeType", + "baseFrequency", + "baseProfile", + "calcMode", + "clipPathUnits", + "diffuseConstant", + "edgeMode", + "filterUnits", + "glyphRef", + "gradientTransform", + "gradientUnits", + "kernelMatrix", + "kernelUnitLength", + "keyPoints", + "keySplines", + "keyTimes", + "lengthAdjust", + "limitingConeAngle", + "markerHeight", + "markerUnits", + "markerWidth", + "maskContentUnits", + "maskUnits", + "numOctaves", + "pathLength", + "patternContentUnits", + "patternTransform", + "patternUnits", + "pointsAtX", + "pointsAtY", + "pointsAtZ", + "preserveAlpha", + "preserveAspectRatio", + "primitiveUnits", + "refX", + "refY", + "repeatCount", + "repeatDur", + "requiredExtensions", + "requiredFeatures", + "specularConstant", + "specularExponent", + "spreadMethod", + "startOffset", + "stdDeviation", + "stitchTiles", + "surfaceScale", + "systemLanguage", + "tableValues", + "targetX", + "targetY", + "textLength", + "viewBox", + "viewTarget", + "xChannelSelector", + "yChannelSelector", + "zoomAndPan", + ].map(function (val) { return [val.toLowerCase(), val]; })); + + var __assign = (commonjsGlobal && commonjsGlobal.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __setModuleDefault = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + }) : function(o, v) { + o["default"] = v; + }); + var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; + }; + Object.defineProperty(lib$1, "__esModule", { value: true }); + lib$1.render = void 0; + /* + * Module dependencies + */ + var ElementType = __importStar(lib$3); + var entities_1 = lib; + /** + * Mixed-case SVG and MathML tags & attributes + * recognized by the HTML parser. + * + * @see https://html.spec.whatwg.org/multipage/parsing.html#parsing-main-inforeign + */ + var foreignNames_js_1 = foreignNames; + var unencodedElements = new Set([ + "style", + "script", + "xmp", + "iframe", + "noembed", + "noframes", + "plaintext", + "noscript", + ]); + function replaceQuotes(value) { + return value.replace(/"/g, """); + } + /** + * Format attributes + */ + function formatAttributes(attributes, opts) { + var _a; + if (!attributes) + return; + var encode = ((_a = opts.encodeEntities) !== null && _a !== void 0 ? _a : opts.decodeEntities) === false + ? replaceQuotes + : opts.xmlMode || opts.encodeEntities !== "utf8" + ? entities_1.encodeXML + : entities_1.escapeAttribute; + return Object.keys(attributes) + .map(function (key) { + var _a, _b; + var value = (_a = attributes[key]) !== null && _a !== void 0 ? _a : ""; + if (opts.xmlMode === "foreign") { + /* Fix up mixed-case attribute names */ + key = (_b = foreignNames_js_1.attributeNames.get(key)) !== null && _b !== void 0 ? _b : key; + } + if (!opts.emptyAttrs && !opts.xmlMode && value === "") { + return key; + } + return "".concat(key, "=\"").concat(encode(value), "\""); + }) + .join(" "); + } + /** + * Self-enclosing tags + */ + var singleTag = new Set([ + "area", + "base", + "basefont", + "br", + "col", + "command", + "embed", + "frame", + "hr", + "img", + "input", + "isindex", + "keygen", + "link", + "meta", + "param", + "source", + "track", + "wbr", + ]); + /** + * Renders a DOM node or an array of DOM nodes to a string. + * + * Can be thought of as the equivalent of the `outerHTML` of the passed node(s). + * + * @param node Node to be rendered. + * @param options Changes serialization behavior + */ + function render(node, options) { + if (options === void 0) { options = {}; } + var nodes = "length" in node ? node : [node]; + var output = ""; + for (var i = 0; i < nodes.length; i++) { + output += renderNode(nodes[i], options); + } + return output; + } + lib$1.render = render; + lib$1.default = render; + function renderNode(node, options) { + switch (node.type) { + case ElementType.Root: + return render(node.children, options); + // @ts-expect-error We don't use `Doctype` yet + case ElementType.Doctype: + case ElementType.Directive: + return renderDirective(node); + case ElementType.Comment: + return renderComment(node); + case ElementType.CDATA: + return renderCdata(node); + case ElementType.Script: + case ElementType.Style: + case ElementType.Tag: + return renderTag(node, options); + case ElementType.Text: + return renderText(node, options); + } + } + var foreignModeIntegrationPoints = new Set([ + "mi", + "mo", + "mn", + "ms", + "mtext", + "annotation-xml", + "foreignObject", + "desc", + "title", + ]); + var foreignElements = new Set(["svg", "math"]); + function renderTag(elem, opts) { + var _a; + // Handle SVG / MathML in HTML + if (opts.xmlMode === "foreign") { + /* Fix up mixed-case element names */ + elem.name = (_a = foreignNames_js_1.elementNames.get(elem.name)) !== null && _a !== void 0 ? _a : elem.name; + /* Exit foreign mode at integration points */ + if (elem.parent && + foreignModeIntegrationPoints.has(elem.parent.name)) { + opts = __assign(__assign({}, opts), { xmlMode: false }); + } + } + if (!opts.xmlMode && foreignElements.has(elem.name)) { + opts = __assign(__assign({}, opts), { xmlMode: "foreign" }); + } + var tag = "<".concat(elem.name); + var attribs = formatAttributes(elem.attribs, opts); + if (attribs) { + tag += " ".concat(attribs); + } + if (elem.children.length === 0 && + (opts.xmlMode + ? // In XML mode or foreign mode, and user hasn't explicitly turned off self-closing tags + opts.selfClosingTags !== false + : // User explicitly asked for self-closing tags, even in HTML mode + opts.selfClosingTags && singleTag.has(elem.name))) { + if (!opts.xmlMode) + tag += " "; + tag += "/>"; + } + else { + tag += ">"; + if (elem.children.length > 0) { + tag += render(elem.children, opts); + } + if (opts.xmlMode || !singleTag.has(elem.name)) { + tag += "</".concat(elem.name, ">"); + } + } + return tag; + } + function renderDirective(elem) { + return "<".concat(elem.data, ">"); + } + function renderText(elem, opts) { + var _a; + var data = elem.data || ""; + // If entities weren't decoded, no need to encode them back + if (((_a = opts.encodeEntities) !== null && _a !== void 0 ? _a : opts.decodeEntities) !== false && + !(!opts.xmlMode && + elem.parent && + unencodedElements.has(elem.parent.name))) { + data = + opts.xmlMode || opts.encodeEntities !== "utf8" + ? (0, entities_1.encodeXML)(data) + : (0, entities_1.escapeText)(data); + } + return data; + } + function renderCdata(elem) { + return "<![CDATA[".concat(elem.children[0].data, "]]>"); + } + function renderComment(elem) { + return "<!--".concat(elem.data, "-->"); + } + + var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + Object.defineProperty(stringify$6, "__esModule", { value: true }); + stringify$6.innerText = stringify$6.textContent = stringify$6.getText = stringify$6.getInnerHTML = stringify$6.getOuterHTML = void 0; + var domhandler_1$3 = lib$4; + var dom_serializer_1 = __importDefault(lib$1); + var domelementtype_1 = lib$3; + /** + * @category Stringify + * @deprecated Use the `dom-serializer` module directly. + * @param node Node to get the outer HTML of. + * @param options Options for serialization. + * @returns `node`'s outer HTML. + */ + function getOuterHTML(node, options) { + return (0, dom_serializer_1.default)(node, options); + } + stringify$6.getOuterHTML = getOuterHTML; + /** + * @category Stringify + * @deprecated Use the `dom-serializer` module directly. + * @param node Node to get the inner HTML of. + * @param options Options for serialization. + * @returns `node`'s inner HTML. + */ + function getInnerHTML(node, options) { + return (0, domhandler_1$3.hasChildren)(node) + ? node.children.map(function (node) { return getOuterHTML(node, options); }).join("") + : ""; + } + stringify$6.getInnerHTML = getInnerHTML; + /** + * Get a node's inner text. Same as `textContent`, but inserts newlines for `<br>` tags. Ignores comments. + * + * @category Stringify + * @deprecated Use `textContent` instead. + * @param node Node to get the inner text of. + * @returns `node`'s inner text. + */ + function getText(node) { + if (Array.isArray(node)) + return node.map(getText).join(""); + if ((0, domhandler_1$3.isTag)(node)) + return node.name === "br" ? "\n" : getText(node.children); + if ((0, domhandler_1$3.isCDATA)(node)) + return getText(node.children); + if ((0, domhandler_1$3.isText)(node)) + return node.data; + return ""; + } + stringify$6.getText = getText; + /** + * Get a node's text content. Ignores comments. + * + * @category Stringify + * @param node Node to get the text content of. + * @returns `node`'s text content. + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent} + */ + function textContent(node) { + if (Array.isArray(node)) + return node.map(textContent).join(""); + if ((0, domhandler_1$3.hasChildren)(node) && !(0, domhandler_1$3.isComment)(node)) { + return textContent(node.children); + } + if ((0, domhandler_1$3.isText)(node)) + return node.data; + return ""; + } + stringify$6.textContent = textContent; + /** + * Get a node's inner text, ignoring `<script>` and `<style>` tags. Ignores comments. + * + * @category Stringify + * @param node Node to get the inner text of. + * @returns `node`'s inner text. + * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Node/innerText} + */ + function innerText(node) { + if (Array.isArray(node)) + return node.map(innerText).join(""); + if ((0, domhandler_1$3.hasChildren)(node) && (node.type === domelementtype_1.ElementType.Tag || (0, domhandler_1$3.isCDATA)(node))) { + return innerText(node.children); + } + if ((0, domhandler_1$3.isText)(node)) + return node.data; + return ""; + } + stringify$6.innerText = innerText; + + var traversal = {}; + + Object.defineProperty(traversal, "__esModule", { value: true }); + traversal.prevElementSibling = traversal.nextElementSibling = traversal.getName = traversal.hasAttrib = traversal.getAttributeValue = traversal.getSiblings = traversal.getParent = traversal.getChildren = void 0; + var domhandler_1$2 = lib$4; + /** + * Get a node's children. + * + * @category Traversal + * @param elem Node to get the children of. + * @returns `elem`'s children, or an empty array. + */ + function getChildren(elem) { + return (0, domhandler_1$2.hasChildren)(elem) ? elem.children : []; + } + traversal.getChildren = getChildren; + /** + * Get a node's parent. + * + * @category Traversal + * @param elem Node to get the parent of. + * @returns `elem`'s parent node, or `null` if `elem` is a root node. + */ + function getParent(elem) { + return elem.parent || null; + } + traversal.getParent = getParent; + /** + * Gets an elements siblings, including the element itself. + * + * Attempts to get the children through the element's parent first. If we don't + * have a parent (the element is a root node), we walk the element's `prev` & + * `next` to get all remaining nodes. + * + * @category Traversal + * @param elem Element to get the siblings of. + * @returns `elem`'s siblings, including `elem`. + */ + function getSiblings(elem) { + var _a, _b; + var parent = getParent(elem); + if (parent != null) + return getChildren(parent); + var siblings = [elem]; + var prev = elem.prev, next = elem.next; + while (prev != null) { + siblings.unshift(prev); + (_a = prev, prev = _a.prev); + } + while (next != null) { + siblings.push(next); + (_b = next, next = _b.next); + } + return siblings; + } + traversal.getSiblings = getSiblings; + /** + * Gets an attribute from an element. + * + * @category Traversal + * @param elem Element to check. + * @param name Attribute name to retrieve. + * @returns The element's attribute value, or `undefined`. + */ + function getAttributeValue(elem, name) { + var _a; + return (_a = elem.attribs) === null || _a === void 0 ? void 0 : _a[name]; + } + traversal.getAttributeValue = getAttributeValue; + /** + * Checks whether an element has an attribute. + * + * @category Traversal + * @param elem Element to check. + * @param name Attribute name to look for. + * @returns Returns whether `elem` has the attribute `name`. + */ + function hasAttrib(elem, name) { + return (elem.attribs != null && + Object.prototype.hasOwnProperty.call(elem.attribs, name) && + elem.attribs[name] != null); + } + traversal.hasAttrib = hasAttrib; + /** + * Get the tag name of an element. + * + * @category Traversal + * @param elem The element to get the name for. + * @returns The tag name of `elem`. + */ + function getName(elem) { + return elem.name; + } + traversal.getName = getName; + /** + * Returns the next element sibling of a node. + * + * @category Traversal + * @param elem The element to get the next sibling of. + * @returns `elem`'s next sibling that is a tag, or `null` if there is no next + * sibling. + */ + function nextElementSibling(elem) { + var _a; + var next = elem.next; + while (next !== null && !(0, domhandler_1$2.isTag)(next)) + (_a = next, next = _a.next); + return next; + } + traversal.nextElementSibling = nextElementSibling; + /** + * Returns the previous element sibling of a node. + * + * @category Traversal + * @param elem The element to get the previous sibling of. + * @returns `elem`'s previous sibling that is a tag, or `null` if there is no + * previous sibling. + */ + function prevElementSibling(elem) { + var _a; + var prev = elem.prev; + while (prev !== null && !(0, domhandler_1$2.isTag)(prev)) + (_a = prev, prev = _a.prev); + return prev; + } + traversal.prevElementSibling = prevElementSibling; + + var manipulation = {}; + + Object.defineProperty(manipulation, "__esModule", { value: true }); + manipulation.prepend = manipulation.prependChild = manipulation.append = manipulation.appendChild = manipulation.replaceElement = manipulation.removeElement = void 0; + /** + * Remove an element from the dom + * + * @category Manipulation + * @param elem The element to be removed + */ + function removeElement(elem) { + if (elem.prev) + elem.prev.next = elem.next; + if (elem.next) + elem.next.prev = elem.prev; + if (elem.parent) { + var childs = elem.parent.children; + var childsIndex = childs.lastIndexOf(elem); + if (childsIndex >= 0) { + childs.splice(childsIndex, 1); + } + } + elem.next = null; + elem.prev = null; + elem.parent = null; + } + manipulation.removeElement = removeElement; + /** + * Replace an element in the dom + * + * @category Manipulation + * @param elem The element to be replaced + * @param replacement The element to be added + */ + function replaceElement(elem, replacement) { + var prev = (replacement.prev = elem.prev); + if (prev) { + prev.next = replacement; + } + var next = (replacement.next = elem.next); + if (next) { + next.prev = replacement; + } + var parent = (replacement.parent = elem.parent); + if (parent) { + var childs = parent.children; + childs[childs.lastIndexOf(elem)] = replacement; + elem.parent = null; + } + } + manipulation.replaceElement = replaceElement; + /** + * Append a child to an element. + * + * @category Manipulation + * @param parent The element to append to. + * @param child The element to be added as a child. + */ + function appendChild(parent, child) { + removeElement(child); + child.next = null; + child.parent = parent; + if (parent.children.push(child) > 1) { + var sibling = parent.children[parent.children.length - 2]; + sibling.next = child; + child.prev = sibling; + } + else { + child.prev = null; + } + } + manipulation.appendChild = appendChild; + /** + * Append an element after another. + * + * @category Manipulation + * @param elem The element to append after. + * @param next The element be added. + */ + function append(elem, next) { + removeElement(next); + var parent = elem.parent; + var currNext = elem.next; + next.next = currNext; + next.prev = elem; + elem.next = next; + next.parent = parent; + if (currNext) { + currNext.prev = next; + if (parent) { + var childs = parent.children; + childs.splice(childs.lastIndexOf(currNext), 0, next); + } + } + else if (parent) { + parent.children.push(next); + } + } + manipulation.append = append; + /** + * Prepend a child to an element. + * + * @category Manipulation + * @param parent The element to prepend before. + * @param child The element to be added as a child. + */ + function prependChild(parent, child) { + removeElement(child); + child.parent = parent; + child.prev = null; + if (parent.children.unshift(child) !== 1) { + var sibling = parent.children[1]; + sibling.prev = child; + child.next = sibling; + } + else { + child.next = null; + } + } + manipulation.prependChild = prependChild; + /** + * Prepend an element before another. + * + * @category Manipulation + * @param elem The element to prepend before. + * @param prev The element be added. + */ + function prepend(elem, prev) { + removeElement(prev); + var parent = elem.parent; + if (parent) { + var childs = parent.children; + childs.splice(childs.indexOf(elem), 0, prev); + } + if (elem.prev) { + elem.prev.next = prev; + } + prev.parent = parent; + prev.prev = elem.prev; + prev.next = elem; + elem.prev = prev; + } + manipulation.prepend = prepend; + + var querying = {}; + + Object.defineProperty(querying, "__esModule", { value: true }); + querying.findAll = querying.existsOne = querying.findOne = querying.findOneChild = querying.find = querying.filter = void 0; + var domhandler_1$1 = lib$4; + /** + * Search a node and its children for nodes passing a test function. If `node` is not an array, it will be wrapped in one. + * + * @category Querying + * @param test Function to test nodes on. + * @param node Node to search. Will be included in the result set if it matches. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes passing `test`. + */ + function filter$2(test, node, recurse, limit) { + if (recurse === void 0) { recurse = true; } + if (limit === void 0) { limit = Infinity; } + return find(test, Array.isArray(node) ? node : [node], recurse, limit); + } + querying.filter = filter$2; + /** + * Search an array of nodes and their children for nodes passing a test function. + * + * @category Querying + * @param test Function to test nodes on. + * @param nodes Array of nodes to search. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes passing `test`. + */ + function find(test, nodes, recurse, limit) { + var result = []; + /** Stack of the arrays we are looking at. */ + var nodeStack = [nodes]; + /** Stack of the indices within the arrays. */ + var indexStack = [0]; + for (;;) { + // First, check if the current array has any more elements to look at. + if (indexStack[0] >= nodeStack[0].length) { + // If we have no more arrays to look at, we are done. + if (indexStack.length === 1) { + return result; + } + // Otherwise, remove the current array from the stack. + nodeStack.shift(); + indexStack.shift(); + // Loop back to the start to continue with the next array. + continue; + } + var elem = nodeStack[0][indexStack[0]++]; + if (test(elem)) { + result.push(elem); + if (--limit <= 0) + return result; + } + if (recurse && (0, domhandler_1$1.hasChildren)(elem) && elem.children.length > 0) { + /* + * Add the children to the stack. We are depth-first, so this is + * the next array we look at. + */ + indexStack.unshift(0); + nodeStack.unshift(elem.children); + } + } + } + querying.find = find; + /** + * Finds the first element inside of an array that matches a test function. This is an alias for `Array.prototype.find`. + * + * @category Querying + * @param test Function to test nodes on. + * @param nodes Array of nodes to search. + * @returns The first node in the array that passes `test`. + * @deprecated Use `Array.prototype.find` directly. + */ + function findOneChild(test, nodes) { + return nodes.find(test); + } + querying.findOneChild = findOneChild; + /** + * Finds one element in a tree that passes a test. + * + * @category Querying + * @param test Function to test nodes on. + * @param nodes Node or array of nodes to search. + * @param recurse Also consider child nodes. + * @returns The first node that passes `test`. + */ + function findOne(test, nodes, recurse) { + if (recurse === void 0) { recurse = true; } + var elem = null; + for (var i = 0; i < nodes.length && !elem; i++) { + var node = nodes[i]; + if (!(0, domhandler_1$1.isTag)(node)) { + continue; + } + else if (test(node)) { + elem = node; + } + else if (recurse && node.children.length > 0) { + elem = findOne(test, node.children, true); + } + } + return elem; + } + querying.findOne = findOne; + /** + * Checks if a tree of nodes contains at least one node passing a test. + * + * @category Querying + * @param test Function to test nodes on. + * @param nodes Array of nodes to search. + * @returns Whether a tree of nodes contains at least one node passing the test. + */ + function existsOne(test, nodes) { + return nodes.some(function (checked) { + return (0, domhandler_1$1.isTag)(checked) && + (test(checked) || existsOne(test, checked.children)); + }); + } + querying.existsOne = existsOne; + /** + * Search an array of nodes and their children for elements passing a test function. + * + * Same as `find`, but limited to elements and with less options, leading to reduced complexity. + * + * @category Querying + * @param test Function to test nodes on. + * @param nodes Array of nodes to search. + * @returns All nodes passing `test`. + */ + function findAll(test, nodes) { + var result = []; + var nodeStack = [nodes]; + var indexStack = [0]; + for (;;) { + if (indexStack[0] >= nodeStack[0].length) { + if (nodeStack.length === 1) { + return result; + } + // Otherwise, remove the current array from the stack. + nodeStack.shift(); + indexStack.shift(); + // Loop back to the start to continue with the next array. + continue; + } + var elem = nodeStack[0][indexStack[0]++]; + if (!(0, domhandler_1$1.isTag)(elem)) + continue; + if (test(elem)) + result.push(elem); + if (elem.children.length > 0) { + indexStack.unshift(0); + nodeStack.unshift(elem.children); + } + } + } + querying.findAll = findAll; + + var legacy = {}; + + Object.defineProperty(legacy, "__esModule", { value: true }); + legacy.getElementsByTagType = legacy.getElementsByTagName = legacy.getElementById = legacy.getElements = legacy.testElement = void 0; + var domhandler_1 = lib$4; + var querying_js_1 = querying; + /** + * A map of functions to check nodes against. + */ + var Checks = { + tag_name: function (name) { + if (typeof name === "function") { + return function (elem) { return (0, domhandler_1.isTag)(elem) && name(elem.name); }; + } + else if (name === "*") { + return domhandler_1.isTag; + } + return function (elem) { return (0, domhandler_1.isTag)(elem) && elem.name === name; }; + }, + tag_type: function (type) { + if (typeof type === "function") { + return function (elem) { return type(elem.type); }; + } + return function (elem) { return elem.type === type; }; + }, + tag_contains: function (data) { + if (typeof data === "function") { + return function (elem) { return (0, domhandler_1.isText)(elem) && data(elem.data); }; + } + return function (elem) { return (0, domhandler_1.isText)(elem) && elem.data === data; }; + }, + }; + /** + * Returns a function to check whether a node has an attribute with a particular + * value. + * + * @param attrib Attribute to check. + * @param value Attribute value to look for. + * @returns A function to check whether the a node has an attribute with a + * particular value. + */ + function getAttribCheck(attrib, value) { + if (typeof value === "function") { + return function (elem) { return (0, domhandler_1.isTag)(elem) && value(elem.attribs[attrib]); }; + } + return function (elem) { return (0, domhandler_1.isTag)(elem) && elem.attribs[attrib] === value; }; + } + /** + * Returns a function that returns `true` if either of the input functions + * returns `true` for a node. + * + * @param a First function to combine. + * @param b Second function to combine. + * @returns A function taking a node and returning `true` if either of the input + * functions returns `true` for the node. + */ + function combineFuncs(a, b) { + return function (elem) { return a(elem) || b(elem); }; + } + /** + * Returns a function that executes all checks in `options` and returns `true` + * if any of them match a node. + * + * @param options An object describing nodes to look for. + * @returns A function that executes all checks in `options` and returns `true` + * if any of them match a node. + */ + function compileTest(options) { + var funcs = Object.keys(options).map(function (key) { + var value = options[key]; + return Object.prototype.hasOwnProperty.call(Checks, key) + ? Checks[key](value) + : getAttribCheck(key, value); + }); + return funcs.length === 0 ? null : funcs.reduce(combineFuncs); + } + /** + * Checks whether a node matches the description in `options`. + * + * @category Legacy Query Functions + * @param options An object describing nodes to look for. + * @param node The element to test. + * @returns Whether the element matches the description in `options`. + */ + function testElement(options, node) { + var test = compileTest(options); + return test ? test(node) : true; + } + legacy.testElement = testElement; + /** + * Returns all nodes that match `options`. + * + * @category Legacy Query Functions + * @param options An object describing nodes to look for. + * @param nodes Nodes to search through. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes that match `options`. + */ + function getElements(options, nodes, recurse, limit) { + if (limit === void 0) { limit = Infinity; } + var test = compileTest(options); + return test ? (0, querying_js_1.filter)(test, nodes, recurse, limit) : []; + } + legacy.getElements = getElements; + /** + * Returns the node with the supplied ID. + * + * @category Legacy Query Functions + * @param id The unique ID attribute value to look for. + * @param nodes Nodes to search through. + * @param recurse Also consider child nodes. + * @returns The node with the supplied ID. + */ + function getElementById(id, nodes, recurse) { + if (recurse === void 0) { recurse = true; } + if (!Array.isArray(nodes)) + nodes = [nodes]; + return (0, querying_js_1.findOne)(getAttribCheck("id", id), nodes, recurse); + } + legacy.getElementById = getElementById; + /** + * Returns all nodes with the supplied `tagName`. + * + * @category Legacy Query Functions + * @param tagName Tag name to search for. + * @param nodes Nodes to search through. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes with the supplied `tagName`. + */ + function getElementsByTagName(tagName, nodes, recurse, limit) { + if (recurse === void 0) { recurse = true; } + if (limit === void 0) { limit = Infinity; } + return (0, querying_js_1.filter)(Checks["tag_name"](tagName), nodes, recurse, limit); + } + legacy.getElementsByTagName = getElementsByTagName; + /** + * Returns all nodes with the supplied `type`. + * + * @category Legacy Query Functions + * @param type Element type to look for. + * @param nodes Nodes to search through. + * @param recurse Also consider child nodes. + * @param limit Maximum number of nodes to return. + * @returns All nodes with the supplied `type`. + */ + function getElementsByTagType(type, nodes, recurse, limit) { + if (recurse === void 0) { recurse = true; } + if (limit === void 0) { limit = Infinity; } + return (0, querying_js_1.filter)(Checks["tag_type"](type), nodes, recurse, limit); + } + legacy.getElementsByTagType = getElementsByTagType; + + var helpers = {}; + + (function (exports) { + Object.defineProperty(exports, "__esModule", { value: true }); + exports.uniqueSort = exports.compareDocumentPosition = exports.DocumentPosition = exports.removeSubsets = void 0; + var domhandler_1 = lib$4; + /** + * Given an array of nodes, remove any member that is contained by another + * member. + * + * @category Helpers + * @param nodes Nodes to filter. + * @returns Remaining nodes that aren't contained by other nodes. + */ + function removeSubsets(nodes) { + var idx = nodes.length; + /* + * Check if each node (or one of its ancestors) is already contained in the + * array. + */ + while (--idx >= 0) { + var node = nodes[idx]; + /* + * Remove the node if it is not unique. + * We are going through the array from the end, so we only + * have to check nodes that preceed the node under consideration in the array. + */ + if (idx > 0 && nodes.lastIndexOf(node, idx - 1) >= 0) { + nodes.splice(idx, 1); + continue; + } + for (var ancestor = node.parent; ancestor; ancestor = ancestor.parent) { + if (nodes.includes(ancestor)) { + nodes.splice(idx, 1); + break; + } + } + } + return nodes; + } + exports.removeSubsets = removeSubsets; + /** + * @category Helpers + * @see {@link http://dom.spec.whatwg.org/#dom-node-comparedocumentposition} + */ + var DocumentPosition; + (function (DocumentPosition) { + DocumentPosition[DocumentPosition["DISCONNECTED"] = 1] = "DISCONNECTED"; + DocumentPosition[DocumentPosition["PRECEDING"] = 2] = "PRECEDING"; + DocumentPosition[DocumentPosition["FOLLOWING"] = 4] = "FOLLOWING"; + DocumentPosition[DocumentPosition["CONTAINS"] = 8] = "CONTAINS"; + DocumentPosition[DocumentPosition["CONTAINED_BY"] = 16] = "CONTAINED_BY"; + })(DocumentPosition = exports.DocumentPosition || (exports.DocumentPosition = {})); + /** + * Compare the position of one node against another node in any other document, + * returning a bitmask with the values from {@link DocumentPosition}. + * + * Document order: + * > There is an ordering, document order, defined on all the nodes in the + * > document corresponding to the order in which the first character of the + * > XML representation of each node occurs in the XML representation of the + * > document after expansion of general entities. Thus, the document element + * > node will be the first node. Element nodes occur before their children. + * > Thus, document order orders element nodes in order of the occurrence of + * > their start-tag in the XML (after expansion of entities). The attribute + * > nodes of an element occur after the element and before its children. The + * > relative order of attribute nodes is implementation-dependent. + * + * Source: + * http://www.w3.org/TR/DOM-Level-3-Core/glossary.html#dt-document-order + * + * @category Helpers + * @param nodeA The first node to use in the comparison + * @param nodeB The second node to use in the comparison + * @returns A bitmask describing the input nodes' relative position. + * + * See http://dom.spec.whatwg.org/#dom-node-comparedocumentposition for + * a description of these values. + */ + function compareDocumentPosition(nodeA, nodeB) { + var aParents = []; + var bParents = []; + if (nodeA === nodeB) { + return 0; + } + var current = (0, domhandler_1.hasChildren)(nodeA) ? nodeA : nodeA.parent; + while (current) { + aParents.unshift(current); + current = current.parent; + } + current = (0, domhandler_1.hasChildren)(nodeB) ? nodeB : nodeB.parent; + while (current) { + bParents.unshift(current); + current = current.parent; + } + var maxIdx = Math.min(aParents.length, bParents.length); + var idx = 0; + while (idx < maxIdx && aParents[idx] === bParents[idx]) { + idx++; + } + if (idx === 0) { + return DocumentPosition.DISCONNECTED; + } + var sharedParent = aParents[idx - 1]; + var siblings = sharedParent.children; + var aSibling = aParents[idx]; + var bSibling = bParents[idx]; + if (siblings.indexOf(aSibling) > siblings.indexOf(bSibling)) { + if (sharedParent === nodeB) { + return DocumentPosition.FOLLOWING | DocumentPosition.CONTAINED_BY; + } + return DocumentPosition.FOLLOWING; + } + if (sharedParent === nodeA) { + return DocumentPosition.PRECEDING | DocumentPosition.CONTAINS; + } + return DocumentPosition.PRECEDING; + } + exports.compareDocumentPosition = compareDocumentPosition; + /** + * Sort an array of nodes based on their relative position in the document, + * removing any duplicate nodes. If the array contains nodes that do not belong + * to the same document, sort order is unspecified. + * + * @category Helpers + * @param nodes Array of DOM nodes. + * @returns Collection of unique nodes, sorted in document order. + */ + function uniqueSort(nodes) { + nodes = nodes.filter(function (node, i, arr) { return !arr.includes(node, i + 1); }); + nodes.sort(function (a, b) { + var relative = compareDocumentPosition(a, b); + if (relative & DocumentPosition.PRECEDING) { + return -1; + } + else if (relative & DocumentPosition.FOLLOWING) { + return 1; + } + return 0; + }); + return nodes; + } + exports.uniqueSort = uniqueSort; + + } (helpers)); + + var feeds = {}; + + Object.defineProperty(feeds, "__esModule", { value: true }); + feeds.getFeed = void 0; + var stringify_js_1 = stringify$6; + var legacy_js_1 = legacy; + /** + * Get the feed object from the root of a DOM tree. + * + * @category Feeds + * @param doc - The DOM to to extract the feed from. + * @returns The feed. + */ + function getFeed(doc) { + var feedRoot = getOneElement(isValidFeed, doc); + return !feedRoot + ? null + : feedRoot.name === "feed" + ? getAtomFeed(feedRoot) + : getRssFeed(feedRoot); + } + feeds.getFeed = getFeed; + /** + * Parse an Atom feed. + * + * @param feedRoot The root of the feed. + * @returns The parsed feed. + */ + function getAtomFeed(feedRoot) { + var _a; + var childs = feedRoot.children; + var feed = { + type: "atom", + items: (0, legacy_js_1.getElementsByTagName)("entry", childs).map(function (item) { + var _a; + var children = item.children; + var entry = { media: getMediaElements(children) }; + addConditionally(entry, "id", "id", children); + addConditionally(entry, "title", "title", children); + var href = (_a = getOneElement("link", children)) === null || _a === void 0 ? void 0 : _a.attribs["href"]; + if (href) { + entry.link = href; + } + var description = fetch("summary", children) || fetch("content", children); + if (description) { + entry.description = description; + } + var pubDate = fetch("updated", children); + if (pubDate) { + entry.pubDate = new Date(pubDate); + } + return entry; + }), + }; + addConditionally(feed, "id", "id", childs); + addConditionally(feed, "title", "title", childs); + var href = (_a = getOneElement("link", childs)) === null || _a === void 0 ? void 0 : _a.attribs["href"]; + if (href) { + feed.link = href; + } + addConditionally(feed, "description", "subtitle", childs); + var updated = fetch("updated", childs); + if (updated) { + feed.updated = new Date(updated); + } + addConditionally(feed, "author", "email", childs, true); + return feed; + } + /** + * Parse a RSS feed. + * + * @param feedRoot The root of the feed. + * @returns The parsed feed. + */ + function getRssFeed(feedRoot) { + var _a, _b; + var childs = (_b = (_a = getOneElement("channel", feedRoot.children)) === null || _a === void 0 ? void 0 : _a.children) !== null && _b !== void 0 ? _b : []; + var feed = { + type: feedRoot.name.substr(0, 3), + id: "", + items: (0, legacy_js_1.getElementsByTagName)("item", feedRoot.children).map(function (item) { + var children = item.children; + var entry = { media: getMediaElements(children) }; + addConditionally(entry, "id", "guid", children); + addConditionally(entry, "title", "title", children); + addConditionally(entry, "link", "link", children); + addConditionally(entry, "description", "description", children); + var pubDate = fetch("pubDate", children) || fetch("dc:date", children); + if (pubDate) + entry.pubDate = new Date(pubDate); + return entry; + }), + }; + addConditionally(feed, "title", "title", childs); + addConditionally(feed, "link", "link", childs); + addConditionally(feed, "description", "description", childs); + var updated = fetch("lastBuildDate", childs); + if (updated) { + feed.updated = new Date(updated); + } + addConditionally(feed, "author", "managingEditor", childs, true); + return feed; + } + var MEDIA_KEYS_STRING = ["url", "type", "lang"]; + var MEDIA_KEYS_INT = [ + "fileSize", + "bitrate", + "framerate", + "samplingrate", + "channels", + "duration", + "height", + "width", + ]; + /** + * Get all media elements of a feed item. + * + * @param where Nodes to search in. + * @returns Media elements. + */ + function getMediaElements(where) { + return (0, legacy_js_1.getElementsByTagName)("media:content", where).map(function (elem) { + var attribs = elem.attribs; + var media = { + medium: attribs["medium"], + isDefault: !!attribs["isDefault"], + }; + for (var _i = 0, MEDIA_KEYS_STRING_1 = MEDIA_KEYS_STRING; _i < MEDIA_KEYS_STRING_1.length; _i++) { + var attrib = MEDIA_KEYS_STRING_1[_i]; + if (attribs[attrib]) { + media[attrib] = attribs[attrib]; + } + } + for (var _a = 0, MEDIA_KEYS_INT_1 = MEDIA_KEYS_INT; _a < MEDIA_KEYS_INT_1.length; _a++) { + var attrib = MEDIA_KEYS_INT_1[_a]; + if (attribs[attrib]) { + media[attrib] = parseInt(attribs[attrib], 10); + } + } + if (attribs["expression"]) { + media.expression = attribs["expression"]; + } + return media; + }); + } + /** + * Get one element by tag name. + * + * @param tagName Tag name to look for + * @param node Node to search in + * @returns The element or null + */ + function getOneElement(tagName, node) { + return (0, legacy_js_1.getElementsByTagName)(tagName, node, true, 1)[0]; + } + /** + * Get the text content of an element with a certain tag name. + * + * @param tagName Tag name to look for. + * @param where Node to search in. + * @param recurse Whether to recurse into child nodes. + * @returns The text content of the element. + */ + function fetch(tagName, where, recurse) { + if (recurse === void 0) { recurse = false; } + return (0, stringify_js_1.textContent)((0, legacy_js_1.getElementsByTagName)(tagName, where, recurse, 1)).trim(); + } + /** + * Adds a property to an object if it has a value. + * + * @param obj Object to be extended + * @param prop Property name + * @param tagName Tag name that contains the conditionally added property + * @param where Element to search for the property + * @param recurse Whether to recurse into child nodes. + */ + function addConditionally(obj, prop, tagName, where, recurse) { + if (recurse === void 0) { recurse = false; } + var val = fetch(tagName, where, recurse); + if (val) + obj[prop] = val; + } + /** + * Checks if an element is a feed root node. + * + * @param value The name of the element to check. + * @returns Whether an element is a feed root node. + */ + function isValidFeed(value) { + return value === "rss" || value === "feed" || value === "rdf:RDF"; + } + + (function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.hasChildren = exports.isDocument = exports.isComment = exports.isText = exports.isCDATA = exports.isTag = void 0; + __exportStar(stringify$6, exports); + __exportStar(traversal, exports); + __exportStar(manipulation, exports); + __exportStar(querying, exports); + __exportStar(legacy, exports); + __exportStar(helpers, exports); + __exportStar(feeds, exports); + /** @deprecated Use these methods from `domhandler` directly. */ + var domhandler_1 = lib$4; + Object.defineProperty(exports, "isTag", { enumerable: true, get: function () { return domhandler_1.isTag; } }); + Object.defineProperty(exports, "isCDATA", { enumerable: true, get: function () { return domhandler_1.isCDATA; } }); + Object.defineProperty(exports, "isText", { enumerable: true, get: function () { return domhandler_1.isText; } }); + Object.defineProperty(exports, "isComment", { enumerable: true, get: function () { return domhandler_1.isComment; } }); + Object.defineProperty(exports, "isDocument", { enumerable: true, get: function () { return domhandler_1.isDocument; } }); + Object.defineProperty(exports, "hasChildren", { enumerable: true, get: function () { return domhandler_1.hasChildren; } }); + + } (lib$2)); + + (function (exports) { + var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); + }) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; + })); + var __setModuleDefault = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + }) : function(o, v) { + o["default"] = v; + }); + var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; + }; + var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; + }; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.DomUtils = exports.parseFeed = exports.getFeed = exports.ElementType = exports.Tokenizer = exports.createDomStream = exports.parseDOM = exports.parseDocument = exports.DefaultHandler = exports.DomHandler = exports.Parser = void 0; + var Parser_js_1 = Parser$3; + var Parser_js_2 = Parser$3; + Object.defineProperty(exports, "Parser", { enumerable: true, get: function () { return Parser_js_2.Parser; } }); + var domhandler_1 = lib$4; + var domhandler_2 = lib$4; + Object.defineProperty(exports, "DomHandler", { enumerable: true, get: function () { return domhandler_2.DomHandler; } }); + // Old name for DomHandler + Object.defineProperty(exports, "DefaultHandler", { enumerable: true, get: function () { return domhandler_2.DomHandler; } }); + // Helper methods + /** + * Parses the data, returns the resulting document. + * + * @param data The data that should be parsed. + * @param options Optional options for the parser and DOM builder. + */ + function parseDocument(data, options) { + var handler = new domhandler_1.DomHandler(undefined, options); + new Parser_js_1.Parser(handler, options).end(data); + return handler.root; + } + exports.parseDocument = parseDocument; + /** + * Parses data, returns an array of the root nodes. + * + * Note that the root nodes still have a `Document` node as their parent. + * Use `parseDocument` to get the `Document` node instead. + * + * @param data The data that should be parsed. + * @param options Optional options for the parser and DOM builder. + * @deprecated Use `parseDocument` instead. + */ + function parseDOM(data, options) { + return parseDocument(data, options).children; + } + exports.parseDOM = parseDOM; + /** + * Creates a parser instance, with an attached DOM handler. + * + * @param callback A callback that will be called once parsing has been completed. + * @param options Optional options for the parser and DOM builder. + * @param elementCallback An optional callback that will be called every time a tag has been completed inside of the DOM. + */ + function createDomStream(callback, options, elementCallback) { + var handler = new domhandler_1.DomHandler(callback, options, elementCallback); + return new Parser_js_1.Parser(handler, options); + } + exports.createDomStream = createDomStream; + var Tokenizer_js_1 = Tokenizer; + Object.defineProperty(exports, "Tokenizer", { enumerable: true, get: function () { return __importDefault(Tokenizer_js_1).default; } }); + /* + * All of the following exports exist for backwards-compatibility. + * They should probably be removed eventually. + */ + exports.ElementType = __importStar(lib$3); + var domutils_1 = lib$2; + var domutils_2 = lib$2; + Object.defineProperty(exports, "getFeed", { enumerable: true, get: function () { return domutils_2.getFeed; } }); + var parseFeedDefaultOptions = { xmlMode: true }; + /** + * Parse a feed. + * + * @param feed The feed that should be parsed, as a string. + * @param options Optionally, options for parsing. When using this, you should set `xmlMode` to `true`. + */ + function parseFeed(feed, options) { + if (options === void 0) { options = parseFeedDefaultOptions; } + return (0, domutils_1.getFeed)(parseDOM(feed, options)); + } + exports.parseFeed = parseFeed; + exports.DomUtils = __importStar(lib$2); + + } (lib$5)); + + var escapeStringRegexp$1 = string => { + if (typeof string !== 'string') { + throw new TypeError('Expected a string'); + } + + // Escape characters with special meaning either inside or outside character sets. + // Use a simple backslash escape when it’s always valid, and a \unnnn escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar. + return string + .replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') + .replace(/-/g, '\\x2d'); + }; + + var isPlainObject$2 = {}; + + Object.defineProperty(isPlainObject$2, '__esModule', { value: true }); + + /*! + * is-plain-object <https://github.com/jonschlinkert/is-plain-object> + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ + + function isObject$1(o) { + return Object.prototype.toString.call(o) === '[object Object]'; + } + + function isPlainObject$1(o) { + var ctor,prot; + + if (isObject$1(o) === false) return false; + + // If has modified constructor + ctor = o.constructor; + if (ctor === undefined) return true; + + // If has modified prototype + prot = ctor.prototype; + if (isObject$1(prot) === false) return false; + + // If constructor does not have an Object-specific method + if (prot.hasOwnProperty('isPrototypeOf') === false) { + return false; + } + + // Most likely a plain Object + return true; + } + + isPlainObject$2.isPlainObject = isPlainObject$1; + + var isMergeableObject = function isMergeableObject(value) { + return isNonNullObject(value) + && !isSpecial(value) + }; + + function isNonNullObject(value) { + return !!value && typeof value === 'object' + } + + function isSpecial(value) { + var stringValue = Object.prototype.toString.call(value); + + return stringValue === '[object RegExp]' + || stringValue === '[object Date]' + || isReactElement(value) + } + + // see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25 + var canUseSymbol = typeof Symbol === 'function' && Symbol.for; + var REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7; + + function isReactElement(value) { + return value.$$typeof === REACT_ELEMENT_TYPE + } + + function emptyTarget(val) { + return Array.isArray(val) ? [] : {} + } + + function cloneUnlessOtherwiseSpecified(value, options) { + return (options.clone !== false && options.isMergeableObject(value)) + ? deepmerge$1(emptyTarget(value), value, options) + : value + } + + function defaultArrayMerge(target, source, options) { + return target.concat(source).map(function(element) { + return cloneUnlessOtherwiseSpecified(element, options) + }) + } + + function getMergeFunction(key, options) { + if (!options.customMerge) { + return deepmerge$1 + } + var customMerge = options.customMerge(key); + return typeof customMerge === 'function' ? customMerge : deepmerge$1 + } + + function getEnumerableOwnPropertySymbols(target) { + return Object.getOwnPropertySymbols + ? Object.getOwnPropertySymbols(target).filter(function(symbol) { + return Object.propertyIsEnumerable.call(target, symbol) + }) + : [] + } + + function getKeys(target) { + return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target)) + } + + function propertyIsOnObject(object, property) { + try { + return property in object + } catch(_) { + return false + } + } + + // Protects from prototype poisoning and unexpected merging up the prototype chain. + function propertyIsUnsafe(target, key) { + return propertyIsOnObject(target, key) // Properties are safe to merge if they don't exist in the target yet, + && !(Object.hasOwnProperty.call(target, key) // unsafe if they exist up the prototype chain, + && Object.propertyIsEnumerable.call(target, key)) // and also unsafe if they're nonenumerable. + } + + function mergeObject(target, source, options) { + var destination = {}; + if (options.isMergeableObject(target)) { + getKeys(target).forEach(function(key) { + destination[key] = cloneUnlessOtherwiseSpecified(target[key], options); + }); + } + getKeys(source).forEach(function(key) { + if (propertyIsUnsafe(target, key)) { + return + } + + if (propertyIsOnObject(target, key) && options.isMergeableObject(source[key])) { + destination[key] = getMergeFunction(key, options)(target[key], source[key], options); + } else { + destination[key] = cloneUnlessOtherwiseSpecified(source[key], options); + } + }); + return destination + } + + function deepmerge$1(target, source, options) { + options = options || {}; + options.arrayMerge = options.arrayMerge || defaultArrayMerge; + options.isMergeableObject = options.isMergeableObject || isMergeableObject; + // cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge() + // implementations can use it. The caller may not replace it. + options.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified; + + var sourceIsArray = Array.isArray(source); + var targetIsArray = Array.isArray(target); + var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray; + + if (!sourceAndTargetTypesMatch) { + return cloneUnlessOtherwiseSpecified(source, options) + } else if (sourceIsArray) { + return options.arrayMerge(target, source, options) + } else { + return mergeObject(target, source, options) + } + } + + deepmerge$1.all = function deepmergeAll(array, options) { + if (!Array.isArray(array)) { + throw new Error('first argument should be an array') + } + + return array.reduce(function(prev, next) { + return deepmerge$1(prev, next, options) + }, {}) + }; + + var deepmerge_1 = deepmerge$1; + + var cjs = deepmerge_1; + + var parseSrcset$1 = {exports: {}}; + + /** + * Srcset Parser + * + * By Alex Bell | MIT License + * + * JS Parser for the string value that appears in markup <img srcset="here"> + * + * @returns Array [{url: _, d: _, w: _, h:_}, ...] + * + * Based super duper closely on the reference algorithm at: + * https://html.spec.whatwg.org/multipage/embedded-content.html#parse-a-srcset-attribute + * + * Most comments are copied in directly from the spec + * (except for comments in parens). + */ + + (function (module) { + (function (root, factory) { + if (module.exports) { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(); + } else { + // Browser globals (root is window) + root.parseSrcset = factory(); + } + }(commonjsGlobal, function () { + + // 1. Let input be the value passed to this algorithm. + return function (input) { + + // UTILITY FUNCTIONS + + // Manual is faster than RegEx + // http://bjorn.tipling.com/state-and-regular-expressions-in-javascript + // http://jsperf.com/whitespace-character/5 + function isSpace(c) { + return (c === "\u0020" || // space + c === "\u0009" || // horizontal tab + c === "\u000A" || // new line + c === "\u000C" || // form feed + c === "\u000D"); // carriage return + } + + function collectCharacters(regEx) { + var chars, + match = regEx.exec(input.substring(pos)); + if (match) { + chars = match[ 0 ]; + pos += chars.length; + return chars; + } + } + + var inputLength = input.length, + + // (Don't use \s, to avoid matching non-breaking space) + regexLeadingSpaces = /^[ \t\n\r\u000c]+/, + regexLeadingCommasOrSpaces = /^[, \t\n\r\u000c]+/, + regexLeadingNotSpaces = /^[^ \t\n\r\u000c]+/, + regexTrailingCommas = /[,]+$/, + regexNonNegativeInteger = /^\d+$/, + + // ( Positive or negative or unsigned integers or decimals, without or without exponents. + // Must include at least one digit. + // According to spec tests any decimal point must be followed by a digit. + // No leading plus sign is allowed.) + // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-floating-point-number + regexFloatingPoint = /^-?(?:[0-9]+|[0-9]*\.[0-9]+)(?:[eE][+-]?[0-9]+)?$/, + + url, + descriptors, + currentDescriptor, + state, + c, + + // 2. Let position be a pointer into input, initially pointing at the start + // of the string. + pos = 0, + + // 3. Let candidates be an initially empty source set. + candidates = []; + + // 4. Splitting loop: Collect a sequence of characters that are space + // characters or U+002C COMMA characters. If any U+002C COMMA characters + // were collected, that is a parse error. + while (true) { + collectCharacters(regexLeadingCommasOrSpaces); + + // 5. If position is past the end of input, return candidates and abort these steps. + if (pos >= inputLength) { + return candidates; // (we're done, this is the sole return path) + } + + // 6. Collect a sequence of characters that are not space characters, + // and let that be url. + url = collectCharacters(regexLeadingNotSpaces); + + // 7. Let descriptors be a new empty list. + descriptors = []; + + // 8. If url ends with a U+002C COMMA character (,), follow these substeps: + // (1). Remove all trailing U+002C COMMA characters from url. If this removed + // more than one character, that is a parse error. + if (url.slice(-1) === ",") { + url = url.replace(regexTrailingCommas, ""); + // (Jump ahead to step 9 to skip tokenization and just push the candidate). + parseDescriptors(); + + // Otherwise, follow these substeps: + } else { + tokenize(); + } // (close else of step 8) + + // 16. Return to the step labeled splitting loop. + } // (Close of big while loop.) + + /** + * Tokenizes descriptor properties prior to parsing + * Returns undefined. + */ + function tokenize() { + + // 8.1. Descriptor tokeniser: Skip whitespace + collectCharacters(regexLeadingSpaces); + + // 8.2. Let current descriptor be the empty string. + currentDescriptor = ""; + + // 8.3. Let state be in descriptor. + state = "in descriptor"; + + while (true) { + + // 8.4. Let c be the character at position. + c = input.charAt(pos); + + // Do the following depending on the value of state. + // For the purpose of this step, "EOF" is a special character representing + // that position is past the end of input. + + // In descriptor + if (state === "in descriptor") { + // Do the following, depending on the value of c: + + // Space character + // If current descriptor is not empty, append current descriptor to + // descriptors and let current descriptor be the empty string. + // Set state to after descriptor. + if (isSpace(c)) { + if (currentDescriptor) { + descriptors.push(currentDescriptor); + currentDescriptor = ""; + state = "after descriptor"; + } + + // U+002C COMMA (,) + // Advance position to the next character in input. If current descriptor + // is not empty, append current descriptor to descriptors. Jump to the step + // labeled descriptor parser. + } else if (c === ",") { + pos += 1; + if (currentDescriptor) { + descriptors.push(currentDescriptor); + } + parseDescriptors(); + return; + + // U+0028 LEFT PARENTHESIS (() + // Append c to current descriptor. Set state to in parens. + } else if (c === "\u0028") { + currentDescriptor = currentDescriptor + c; + state = "in parens"; + + // EOF + // If current descriptor is not empty, append current descriptor to + // descriptors. Jump to the step labeled descriptor parser. + } else if (c === "") { + if (currentDescriptor) { + descriptors.push(currentDescriptor); + } + parseDescriptors(); + return; + + // Anything else + // Append c to current descriptor. + } else { + currentDescriptor = currentDescriptor + c; + } + // (end "in descriptor" + + // In parens + } else if (state === "in parens") { + + // U+0029 RIGHT PARENTHESIS ()) + // Append c to current descriptor. Set state to in descriptor. + if (c === ")") { + currentDescriptor = currentDescriptor + c; + state = "in descriptor"; + + // EOF + // Append current descriptor to descriptors. Jump to the step labeled + // descriptor parser. + } else if (c === "") { + descriptors.push(currentDescriptor); + parseDescriptors(); + return; + + // Anything else + // Append c to current descriptor. + } else { + currentDescriptor = currentDescriptor + c; + } + + // After descriptor + } else if (state === "after descriptor") { + + // Do the following, depending on the value of c: + // Space character: Stay in this state. + if (isSpace(c)) ; else if (c === "") { + parseDescriptors(); + return; + + // Anything else + // Set state to in descriptor. Set position to the previous character in input. + } else { + state = "in descriptor"; + pos -= 1; + + } + } + + // Advance position to the next character in input. + pos += 1; + + // Repeat this step. + } // (close while true loop) + } + + /** + * Adds descriptor properties to a candidate, pushes to the candidates array + * @return undefined + */ + // Declared outside of the while loop so that it's only created once. + function parseDescriptors() { + + // 9. Descriptor parser: Let error be no. + var pError = false, + + // 10. Let width be absent. + // 11. Let density be absent. + // 12. Let future-compat-h be absent. (We're implementing it now as h) + w, d, h, i, + candidate = {}, + desc, lastChar, value, intVal, floatVal; + + // 13. For each descriptor in descriptors, run the appropriate set of steps + // from the following list: + for (i = 0 ; i < descriptors.length; i++) { + desc = descriptors[ i ]; + + lastChar = desc[ desc.length - 1 ]; + value = desc.substring(0, desc.length - 1); + intVal = parseInt(value, 10); + floatVal = parseFloat(value); + + // If the descriptor consists of a valid non-negative integer followed by + // a U+0077 LATIN SMALL LETTER W character + if (regexNonNegativeInteger.test(value) && (lastChar === "w")) { + + // If width and density are not both absent, then let error be yes. + if (w || d) {pError = true;} + + // Apply the rules for parsing non-negative integers to the descriptor. + // If the result is zero, let error be yes. + // Otherwise, let width be the result. + if (intVal === 0) {pError = true;} else {w = intVal;} + + // If the descriptor consists of a valid floating-point number followed by + // a U+0078 LATIN SMALL LETTER X character + } else if (regexFloatingPoint.test(value) && (lastChar === "x")) { + + // If width, density and future-compat-h are not all absent, then let error + // be yes. + if (w || d || h) {pError = true;} + + // Apply the rules for parsing floating-point number values to the descriptor. + // If the result is less than zero, let error be yes. Otherwise, let density + // be the result. + if (floatVal < 0) {pError = true;} else {d = floatVal;} + + // If the descriptor consists of a valid non-negative integer followed by + // a U+0068 LATIN SMALL LETTER H character + } else if (regexNonNegativeInteger.test(value) && (lastChar === "h")) { + + // If height and density are not both absent, then let error be yes. + if (h || d) {pError = true;} + + // Apply the rules for parsing non-negative integers to the descriptor. + // If the result is zero, let error be yes. Otherwise, let future-compat-h + // be the result. + if (intVal === 0) {pError = true;} else {h = intVal;} + + // Anything else, Let error be yes. + } else {pError = true;} + } // (close step 13 for loop) + + // 15. If error is still no, then append a new image source to candidates whose + // URL is url, associated with a width width if not absent and a pixel + // density density if not absent. Otherwise, there is a parse error. + if (!pError) { + candidate.url = url; + if (w) { candidate.w = w;} + if (d) { candidate.d = d;} + if (h) { candidate.h = h;} + candidates.push(candidate); + } else if (console && console.log) { + console.log("Invalid srcset descriptor found in '" + + input + "' at '" + desc + "'."); + } + } // (close parseDescriptors fn) + + } + })); + } (parseSrcset$1)); + + var parseSrcsetExports = parseSrcset$1.exports; + + var global$1 = (typeof global !== "undefined" ? global : + typeof self !== "undefined" ? self : + typeof window !== "undefined" ? window : {}); + + // shim for using process in browser + // based off https://github.com/defunctzombie/node-process/blob/master/browser.js + + function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); + } + function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); + } + var cachedSetTimeout = defaultSetTimout; + var cachedClearTimeout = defaultClearTimeout; + if (typeof global$1.setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } + if (typeof global$1.clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } + + function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + + } + function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + + } + var queue = []; + var draining = false; + var currentQueue; + var queueIndex = -1; + + function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } + } + + function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); + } + function nextTick(fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } + } + // v8 likes predictible objects + function Item(fun, array) { + this.fun = fun; + this.array = array; + } + Item.prototype.run = function () { + this.fun.apply(null, this.array); + }; + var title = 'browser'; + var platform = 'browser'; + var browser = true; + var env$1 = {}; + var argv$1 = []; + var version = ''; // empty string to avoid regexp issues + var versions = {}; + var release = {}; + var config = {}; + + function noop() {} + + var on = noop; + var addListener = noop; + var once = noop; + var off = noop; + var removeListener = noop; + var removeAllListeners = noop; + var emit = noop; + + function binding(name) { + throw new Error('process.binding is not supported'); + } + + function cwd () { return '/' } + function chdir (dir) { + throw new Error('process.chdir is not supported'); + }function umask() { return 0; } + + // from https://github.com/kumavis/browser-process-hrtime/blob/master/index.js + var performance = global$1.performance || {}; + var performanceNow = + performance.now || + performance.mozNow || + performance.msNow || + performance.oNow || + performance.webkitNow || + function(){ return (new Date()).getTime() }; + + // generate timestamp or delta + // see http://nodejs.org/api/process.html#process_process_hrtime + function hrtime(previousTimestamp){ + var clocktime = performanceNow.call(performance)*1e-3; + var seconds = Math.floor(clocktime); + var nanoseconds = Math.floor((clocktime%1)*1e9); + if (previousTimestamp) { + seconds = seconds - previousTimestamp[0]; + nanoseconds = nanoseconds - previousTimestamp[1]; + if (nanoseconds<0) { + seconds--; + nanoseconds += 1e9; + } + } + return [seconds,nanoseconds] + } + + var startTime = new Date(); + function uptime() { + var currentTime = new Date(); + var dif = currentTime - startTime; + return dif / 1000; + } + + var browser$1 = { + nextTick: nextTick, + title: title, + browser: browser, + env: env$1, + argv: argv$1, + version: version, + versions: versions, + on: on, + addListener: addListener, + once: once, + off: off, + removeListener: removeListener, + removeAllListeners: removeAllListeners, + emit: emit, + binding: binding, + cwd: cwd, + chdir: chdir, + umask: umask, + hrtime: hrtime, + platform: platform, + release: release, + config: config, + uptime: uptime + }; + + function commonjsRequire(path) { + throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.'); + } + + var picocolors = {exports: {}}; + + // MIT lisence + // from https://github.com/substack/tty-browserify/blob/1ba769a6429d242f36226538835b4034bf6b7886/index.js + + function isatty() { + return false; + } + + function ReadStream() { + throw new Error('tty.ReadStream is not implemented'); + } + + function WriteStream() { + throw new Error('tty.ReadStream is not implemented'); + } + + var _polyfillNode_tty = { + isatty: isatty, + ReadStream: ReadStream, + WriteStream: WriteStream + }; + + var _polyfillNode_tty$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + ReadStream: ReadStream, + WriteStream: WriteStream, + default: _polyfillNode_tty, + isatty: isatty + }); + + var require$$0 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_tty$1); + + let argv = browser$1.argv || [], + env = browser$1.env; + let isColorSupported = + !("NO_COLOR" in env || argv.includes("--no-color")) && + ("FORCE_COLOR" in env || + argv.includes("--color") || + browser$1.platform === "win32" || + (commonjsRequire != null && require$$0.isatty(1) && env.TERM !== "dumb") || + "CI" in env); + + let formatter = + (open, close, replace = open) => + input => { + let string = "" + input; + let index = string.indexOf(close, open.length); + return ~index + ? open + replaceClose(string, close, replace, index) + close + : open + string + close + }; + + let replaceClose = (string, close, replace, index) => { + let result = ""; + let cursor = 0; + do { + result += string.substring(cursor, index) + replace; + cursor = index + close.length; + index = string.indexOf(close, cursor); + } while (~index) + return result + string.substring(cursor) + }; + + let createColors = (enabled = isColorSupported) => { + let init = enabled ? formatter : () => String; + return { + isColorSupported: enabled, + reset: init("\x1b[0m", "\x1b[0m"), + bold: init("\x1b[1m", "\x1b[22m", "\x1b[22m\x1b[1m"), + dim: init("\x1b[2m", "\x1b[22m", "\x1b[22m\x1b[2m"), + italic: init("\x1b[3m", "\x1b[23m"), + underline: init("\x1b[4m", "\x1b[24m"), + inverse: init("\x1b[7m", "\x1b[27m"), + hidden: init("\x1b[8m", "\x1b[28m"), + strikethrough: init("\x1b[9m", "\x1b[29m"), + black: init("\x1b[30m", "\x1b[39m"), + red: init("\x1b[31m", "\x1b[39m"), + green: init("\x1b[32m", "\x1b[39m"), + yellow: init("\x1b[33m", "\x1b[39m"), + blue: init("\x1b[34m", "\x1b[39m"), + magenta: init("\x1b[35m", "\x1b[39m"), + cyan: init("\x1b[36m", "\x1b[39m"), + white: init("\x1b[37m", "\x1b[39m"), + gray: init("\x1b[90m", "\x1b[39m"), + bgBlack: init("\x1b[40m", "\x1b[49m"), + bgRed: init("\x1b[41m", "\x1b[49m"), + bgGreen: init("\x1b[42m", "\x1b[49m"), + bgYellow: init("\x1b[43m", "\x1b[49m"), + bgBlue: init("\x1b[44m", "\x1b[49m"), + bgMagenta: init("\x1b[45m", "\x1b[49m"), + bgCyan: init("\x1b[46m", "\x1b[49m"), + bgWhite: init("\x1b[47m", "\x1b[49m"), + } + }; + + picocolors.exports = createColors(); + picocolors.exports.createColors = createColors; + + var picocolorsExports = picocolors.exports; + + const SINGLE_QUOTE = "'".charCodeAt(0); + const DOUBLE_QUOTE = '"'.charCodeAt(0); + const BACKSLASH = '\\'.charCodeAt(0); + const SLASH = '/'.charCodeAt(0); + const NEWLINE = '\n'.charCodeAt(0); + const SPACE = ' '.charCodeAt(0); + const FEED = '\f'.charCodeAt(0); + const TAB = '\t'.charCodeAt(0); + const CR = '\r'.charCodeAt(0); + const OPEN_SQUARE = '['.charCodeAt(0); + const CLOSE_SQUARE = ']'.charCodeAt(0); + const OPEN_PARENTHESES = '('.charCodeAt(0); + const CLOSE_PARENTHESES = ')'.charCodeAt(0); + const OPEN_CURLY = '{'.charCodeAt(0); + const CLOSE_CURLY = '}'.charCodeAt(0); + const SEMICOLON = ';'.charCodeAt(0); + const ASTERISK = '*'.charCodeAt(0); + const COLON = ':'.charCodeAt(0); + const AT = '@'.charCodeAt(0); + + const RE_AT_END = /[\t\n\f\r "#'()/;[\\\]{}]/g; + const RE_WORD_END = /[\t\n\f\r !"#'():;@[\\\]{}]|\/(?=\*)/g; + const RE_BAD_BRACKET = /.[\r\n"'(/\\]/; + const RE_HEX_ESCAPE = /[\da-f]/i; + + var tokenize = function tokenizer(input, options = {}) { + let css = input.css.valueOf(); + let ignore = options.ignoreErrors; + + let code, next, quote, content, escape; + let escaped, escapePos, prev, n, currentToken; + + let length = css.length; + let pos = 0; + let buffer = []; + let returned = []; + + function position() { + return pos + } + + function unclosed(what) { + throw input.error('Unclosed ' + what, pos) + } + + function endOfFile() { + return returned.length === 0 && pos >= length + } + + function nextToken(opts) { + if (returned.length) return returned.pop() + if (pos >= length) return + + let ignoreUnclosed = opts ? opts.ignoreUnclosed : false; + + code = css.charCodeAt(pos); + + switch (code) { + case NEWLINE: + case SPACE: + case TAB: + case CR: + case FEED: { + next = pos; + do { + next += 1; + code = css.charCodeAt(next); + } while ( + code === SPACE || + code === NEWLINE || + code === TAB || + code === CR || + code === FEED + ) + + currentToken = ['space', css.slice(pos, next)]; + pos = next - 1; + break + } + + case OPEN_SQUARE: + case CLOSE_SQUARE: + case OPEN_CURLY: + case CLOSE_CURLY: + case COLON: + case SEMICOLON: + case CLOSE_PARENTHESES: { + let controlChar = String.fromCharCode(code); + currentToken = [controlChar, controlChar, pos]; + break + } + + case OPEN_PARENTHESES: { + prev = buffer.length ? buffer.pop()[1] : ''; + n = css.charCodeAt(pos + 1); + if ( + prev === 'url' && + n !== SINGLE_QUOTE && + n !== DOUBLE_QUOTE && + n !== SPACE && + n !== NEWLINE && + n !== TAB && + n !== FEED && + n !== CR + ) { + next = pos; + do { + escaped = false; + next = css.indexOf(')', next + 1); + if (next === -1) { + if (ignore || ignoreUnclosed) { + next = pos; + break + } else { + unclosed('bracket'); + } + } + escapePos = next; + while (css.charCodeAt(escapePos - 1) === BACKSLASH) { + escapePos -= 1; + escaped = !escaped; + } + } while (escaped) + + currentToken = ['brackets', css.slice(pos, next + 1), pos, next]; + + pos = next; + } else { + next = css.indexOf(')', pos + 1); + content = css.slice(pos, next + 1); + + if (next === -1 || RE_BAD_BRACKET.test(content)) { + currentToken = ['(', '(', pos]; + } else { + currentToken = ['brackets', content, pos, next]; + pos = next; + } + } + + break + } + + case SINGLE_QUOTE: + case DOUBLE_QUOTE: { + quote = code === SINGLE_QUOTE ? "'" : '"'; + next = pos; + do { + escaped = false; + next = css.indexOf(quote, next + 1); + if (next === -1) { + if (ignore || ignoreUnclosed) { + next = pos + 1; + break + } else { + unclosed('string'); + } + } + escapePos = next; + while (css.charCodeAt(escapePos - 1) === BACKSLASH) { + escapePos -= 1; + escaped = !escaped; + } + } while (escaped) + + currentToken = ['string', css.slice(pos, next + 1), pos, next]; + pos = next; + break + } + + case AT: { + RE_AT_END.lastIndex = pos + 1; + RE_AT_END.test(css); + if (RE_AT_END.lastIndex === 0) { + next = css.length - 1; + } else { + next = RE_AT_END.lastIndex - 2; + } + + currentToken = ['at-word', css.slice(pos, next + 1), pos, next]; + + pos = next; + break + } + + case BACKSLASH: { + next = pos; + escape = true; + while (css.charCodeAt(next + 1) === BACKSLASH) { + next += 1; + escape = !escape; + } + code = css.charCodeAt(next + 1); + if ( + escape && + code !== SLASH && + code !== SPACE && + code !== NEWLINE && + code !== TAB && + code !== CR && + code !== FEED + ) { + next += 1; + if (RE_HEX_ESCAPE.test(css.charAt(next))) { + while (RE_HEX_ESCAPE.test(css.charAt(next + 1))) { + next += 1; + } + if (css.charCodeAt(next + 1) === SPACE) { + next += 1; + } + } + } + + currentToken = ['word', css.slice(pos, next + 1), pos, next]; + + pos = next; + break + } + + default: { + if (code === SLASH && css.charCodeAt(pos + 1) === ASTERISK) { + next = css.indexOf('*/', pos + 2) + 1; + if (next === 0) { + if (ignore || ignoreUnclosed) { + next = css.length; + } else { + unclosed('comment'); + } + } + + currentToken = ['comment', css.slice(pos, next + 1), pos, next]; + pos = next; + } else { + RE_WORD_END.lastIndex = pos + 1; + RE_WORD_END.test(css); + if (RE_WORD_END.lastIndex === 0) { + next = css.length - 1; + } else { + next = RE_WORD_END.lastIndex - 2; + } + + currentToken = ['word', css.slice(pos, next + 1), pos, next]; + buffer.push(currentToken); + pos = next; + } + + break + } + } + + pos++; + return currentToken + } + + function back(token) { + returned.push(token); + } + + return { + back, + endOfFile, + nextToken, + position + } + }; + + let pico$1 = picocolorsExports; + + let tokenizer$1 = tokenize; + + let Input$5; + + function registerInput(dependant) { + Input$5 = dependant; + } + + const HIGHLIGHT_THEME = { + ';': pico$1.yellow, + ':': pico$1.yellow, + '(': pico$1.cyan, + ')': pico$1.cyan, + '[': pico$1.yellow, + ']': pico$1.yellow, + '{': pico$1.yellow, + '}': pico$1.yellow, + 'at-word': pico$1.cyan, + 'brackets': pico$1.cyan, + 'call': pico$1.cyan, + 'class': pico$1.yellow, + 'comment': pico$1.gray, + 'hash': pico$1.magenta, + 'string': pico$1.green + }; + + function getTokenType([type, value], processor) { + if (type === 'word') { + if (value[0] === '.') { + return 'class' + } + if (value[0] === '#') { + return 'hash' + } + } + + if (!processor.endOfFile()) { + let next = processor.nextToken(); + processor.back(next); + if (next[0] === 'brackets' || next[0] === '(') return 'call' + } + + return type + } + + function terminalHighlight$2(css) { + let processor = tokenizer$1(new Input$5(css), { ignoreErrors: true }); + let result = ''; + while (!processor.endOfFile()) { + let token = processor.nextToken(); + let color = HIGHLIGHT_THEME[getTokenType(token, processor)]; + if (color) { + result += token[1] + .split(/\r?\n/) + .map(i => color(i)) + .join('\n'); + } else { + result += token[1]; + } + } + return result + } + + terminalHighlight$2.registerInput = registerInput; + + var terminalHighlight_1 = terminalHighlight$2; + + let pico = picocolorsExports; + + let terminalHighlight$1 = terminalHighlight_1; + + let CssSyntaxError$3 = class CssSyntaxError extends Error { + constructor(message, line, column, source, file, plugin) { + super(message); + this.name = 'CssSyntaxError'; + this.reason = message; + + if (file) { + this.file = file; + } + if (source) { + this.source = source; + } + if (plugin) { + this.plugin = plugin; + } + if (typeof line !== 'undefined' && typeof column !== 'undefined') { + if (typeof line === 'number') { + this.line = line; + this.column = column; + } else { + this.line = line.line; + this.column = line.column; + this.endLine = column.line; + this.endColumn = column.column; + } + } + + this.setMessage(); + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, CssSyntaxError); + } + } + + setMessage() { + this.message = this.plugin ? this.plugin + ': ' : ''; + this.message += this.file ? this.file : '<css input>'; + if (typeof this.line !== 'undefined') { + this.message += ':' + this.line + ':' + this.column; + } + this.message += ': ' + this.reason; + } + + showSourceCode(color) { + if (!this.source) return '' + + let css = this.source; + if (color == null) color = pico.isColorSupported; + if (terminalHighlight$1) { + if (color) css = terminalHighlight$1(css); + } + + let lines = css.split(/\r?\n/); + let start = Math.max(this.line - 3, 0); + let end = Math.min(this.line + 2, lines.length); + + let maxWidth = String(end).length; + + let mark, aside; + if (color) { + let { bold, gray, red } = pico.createColors(true); + mark = text => bold(red(text)); + aside = text => gray(text); + } else { + mark = aside = str => str; + } + + return lines + .slice(start, end) + .map((line, index) => { + let number = start + 1 + index; + let gutter = ' ' + (' ' + number).slice(-maxWidth) + ' | '; + if (number === this.line) { + let spacing = + aside(gutter.replace(/\d/g, ' ')) + + line.slice(0, this.column - 1).replace(/[^\t]/g, ' '); + return mark('>') + aside(gutter) + line + '\n ' + spacing + mark('^') + } + return ' ' + aside(gutter) + line + }) + .join('\n') + } + + toString() { + let code = this.showSourceCode(); + if (code) { + code = '\n\n' + code + '\n'; + } + return this.name + ': ' + this.message + code + } + }; + + var cssSyntaxError = CssSyntaxError$3; + CssSyntaxError$3.default = CssSyntaxError$3; + + var symbols = {}; + + symbols.isClean = Symbol('isClean'); + + symbols.my = Symbol('my'); + + const DEFAULT_RAW = { + after: '\n', + beforeClose: '\n', + beforeComment: '\n', + beforeDecl: '\n', + beforeOpen: ' ', + beforeRule: '\n', + colon: ': ', + commentLeft: ' ', + commentRight: ' ', + emptyBody: '', + indent: ' ', + semicolon: false + }; + + function capitalize(str) { + return str[0].toUpperCase() + str.slice(1) + } + + let Stringifier$2 = class Stringifier { + constructor(builder) { + this.builder = builder; + } + + atrule(node, semicolon) { + let name = '@' + node.name; + let params = node.params ? this.rawValue(node, 'params') : ''; + + if (typeof node.raws.afterName !== 'undefined') { + name += node.raws.afterName; + } else if (params) { + name += ' '; + } + + if (node.nodes) { + this.block(node, name + params); + } else { + let end = (node.raws.between || '') + (semicolon ? ';' : ''); + this.builder(name + params + end, node); + } + } + + beforeAfter(node, detect) { + let value; + if (node.type === 'decl') { + value = this.raw(node, null, 'beforeDecl'); + } else if (node.type === 'comment') { + value = this.raw(node, null, 'beforeComment'); + } else if (detect === 'before') { + value = this.raw(node, null, 'beforeRule'); + } else { + value = this.raw(node, null, 'beforeClose'); + } + + let buf = node.parent; + let depth = 0; + while (buf && buf.type !== 'root') { + depth += 1; + buf = buf.parent; + } + + if (value.includes('\n')) { + let indent = this.raw(node, null, 'indent'); + if (indent.length) { + for (let step = 0; step < depth; step++) value += indent; + } + } + + return value + } + + block(node, start) { + let between = this.raw(node, 'between', 'beforeOpen'); + this.builder(start + between + '{', node, 'start'); + + let after; + if (node.nodes && node.nodes.length) { + this.body(node); + after = this.raw(node, 'after'); + } else { + after = this.raw(node, 'after', 'emptyBody'); + } + + if (after) this.builder(after); + this.builder('}', node, 'end'); + } + + body(node) { + let last = node.nodes.length - 1; + while (last > 0) { + if (node.nodes[last].type !== 'comment') break + last -= 1; + } + + let semicolon = this.raw(node, 'semicolon'); + for (let i = 0; i < node.nodes.length; i++) { + let child = node.nodes[i]; + let before = this.raw(child, 'before'); + if (before) this.builder(before); + this.stringify(child, last !== i || semicolon); + } + } + + comment(node) { + let left = this.raw(node, 'left', 'commentLeft'); + let right = this.raw(node, 'right', 'commentRight'); + this.builder('/*' + left + node.text + right + '*/', node); + } + + decl(node, semicolon) { + let between = this.raw(node, 'between', 'colon'); + let string = node.prop + between + this.rawValue(node, 'value'); + + if (node.important) { + string += node.raws.important || ' !important'; + } + + if (semicolon) string += ';'; + this.builder(string, node); + } + + document(node) { + this.body(node); + } + + raw(node, own, detect) { + let value; + if (!detect) detect = own; + + // Already had + if (own) { + value = node.raws[own]; + if (typeof value !== 'undefined') return value + } + + let parent = node.parent; + + if (detect === 'before') { + // Hack for first rule in CSS + if (!parent || (parent.type === 'root' && parent.first === node)) { + return '' + } + + // `root` nodes in `document` should use only their own raws + if (parent && parent.type === 'document') { + return '' + } + } + + // Floating child without parent + if (!parent) return DEFAULT_RAW[detect] + + // Detect style by other nodes + let root = node.root(); + if (!root.rawCache) root.rawCache = {}; + if (typeof root.rawCache[detect] !== 'undefined') { + return root.rawCache[detect] + } + + if (detect === 'before' || detect === 'after') { + return this.beforeAfter(node, detect) + } else { + let method = 'raw' + capitalize(detect); + if (this[method]) { + value = this[method](root, node); + } else { + root.walk(i => { + value = i.raws[own]; + if (typeof value !== 'undefined') return false + }); + } + } + + if (typeof value === 'undefined') value = DEFAULT_RAW[detect]; + + root.rawCache[detect] = value; + return value + } + + rawBeforeClose(root) { + let value; + root.walk(i => { + if (i.nodes && i.nodes.length > 0) { + if (typeof i.raws.after !== 'undefined') { + value = i.raws.after; + if (value.includes('\n')) { + value = value.replace(/[^\n]+$/, ''); + } + return false + } + } + }); + if (value) value = value.replace(/\S/g, ''); + return value + } + + rawBeforeComment(root, node) { + let value; + root.walkComments(i => { + if (typeof i.raws.before !== 'undefined') { + value = i.raws.before; + if (value.includes('\n')) { + value = value.replace(/[^\n]+$/, ''); + } + return false + } + }); + if (typeof value === 'undefined') { + value = this.raw(node, null, 'beforeDecl'); + } else if (value) { + value = value.replace(/\S/g, ''); + } + return value + } + + rawBeforeDecl(root, node) { + let value; + root.walkDecls(i => { + if (typeof i.raws.before !== 'undefined') { + value = i.raws.before; + if (value.includes('\n')) { + value = value.replace(/[^\n]+$/, ''); + } + return false + } + }); + if (typeof value === 'undefined') { + value = this.raw(node, null, 'beforeRule'); + } else if (value) { + value = value.replace(/\S/g, ''); + } + return value + } + + rawBeforeOpen(root) { + let value; + root.walk(i => { + if (i.type !== 'decl') { + value = i.raws.between; + if (typeof value !== 'undefined') return false + } + }); + return value + } + + rawBeforeRule(root) { + let value; + root.walk(i => { + if (i.nodes && (i.parent !== root || root.first !== i)) { + if (typeof i.raws.before !== 'undefined') { + value = i.raws.before; + if (value.includes('\n')) { + value = value.replace(/[^\n]+$/, ''); + } + return false + } + } + }); + if (value) value = value.replace(/\S/g, ''); + return value + } + + rawColon(root) { + let value; + root.walkDecls(i => { + if (typeof i.raws.between !== 'undefined') { + value = i.raws.between.replace(/[^\s:]/g, ''); + return false + } + }); + return value + } + + rawEmptyBody(root) { + let value; + root.walk(i => { + if (i.nodes && i.nodes.length === 0) { + value = i.raws.after; + if (typeof value !== 'undefined') return false + } + }); + return value + } + + rawIndent(root) { + if (root.raws.indent) return root.raws.indent + let value; + root.walk(i => { + let p = i.parent; + if (p && p !== root && p.parent && p.parent === root) { + if (typeof i.raws.before !== 'undefined') { + let parts = i.raws.before.split('\n'); + value = parts[parts.length - 1]; + value = value.replace(/\S/g, ''); + return false + } + } + }); + return value + } + + rawSemicolon(root) { + let value; + root.walk(i => { + if (i.nodes && i.nodes.length && i.last.type === 'decl') { + value = i.raws.semicolon; + if (typeof value !== 'undefined') return false + } + }); + return value + } + + rawValue(node, prop) { + let value = node[prop]; + let raw = node.raws[prop]; + if (raw && raw.value === value) { + return raw.raw + } + + return value + } + + root(node) { + this.body(node); + if (node.raws.after) this.builder(node.raws.after); + } + + rule(node) { + this.block(node, this.rawValue(node, 'selector')); + if (node.raws.ownSemicolon) { + this.builder(node.raws.ownSemicolon, node, 'end'); + } + } + + stringify(node, semicolon) { + /* c8 ignore start */ + if (!this[node.type]) { + throw new Error( + 'Unknown AST node type ' + + node.type + + '. ' + + 'Maybe you need to change PostCSS stringifier.' + ) + } + /* c8 ignore stop */ + this[node.type](node, semicolon); + } + }; + + var stringifier = Stringifier$2; + Stringifier$2.default = Stringifier$2; + + let Stringifier$1 = stringifier; + + function stringify$5(node, builder) { + let str = new Stringifier$1(builder); + str.stringify(node); + } + + var stringify_1 = stringify$5; + stringify$5.default = stringify$5; + + let { isClean: isClean$2, my: my$2 } = symbols; + let CssSyntaxError$2 = cssSyntaxError; + let Stringifier = stringifier; + let stringify$4 = stringify_1; + + function cloneNode(obj, parent) { + let cloned = new obj.constructor(); + + for (let i in obj) { + if (!Object.prototype.hasOwnProperty.call(obj, i)) { + /* c8 ignore next 2 */ + continue + } + if (i === 'proxyCache') continue + let value = obj[i]; + let type = typeof value; + + if (i === 'parent' && type === 'object') { + if (parent) cloned[i] = parent; + } else if (i === 'source') { + cloned[i] = value; + } else if (Array.isArray(value)) { + cloned[i] = value.map(j => cloneNode(j, cloned)); + } else { + if (type === 'object' && value !== null) value = cloneNode(value); + cloned[i] = value; + } + } + + return cloned + } + + let Node$4 = class Node { + constructor(defaults = {}) { + this.raws = {}; + this[isClean$2] = false; + this[my$2] = true; + + for (let name in defaults) { + if (name === 'nodes') { + this.nodes = []; + for (let node of defaults[name]) { + if (typeof node.clone === 'function') { + this.append(node.clone()); + } else { + this.append(node); + } + } + } else { + this[name] = defaults[name]; + } + } + } + + addToError(error) { + error.postcssNode = this; + if (error.stack && this.source && /\n\s{4}at /.test(error.stack)) { + let s = this.source; + error.stack = error.stack.replace( + /\n\s{4}at /, + `$&${s.input.from}:${s.start.line}:${s.start.column}$&` + ); + } + return error + } + + after(add) { + this.parent.insertAfter(this, add); + return this + } + + assign(overrides = {}) { + for (let name in overrides) { + this[name] = overrides[name]; + } + return this + } + + before(add) { + this.parent.insertBefore(this, add); + return this + } + + cleanRaws(keepBetween) { + delete this.raws.before; + delete this.raws.after; + if (!keepBetween) delete this.raws.between; + } + + clone(overrides = {}) { + let cloned = cloneNode(this); + for (let name in overrides) { + cloned[name] = overrides[name]; + } + return cloned + } + + cloneAfter(overrides = {}) { + let cloned = this.clone(overrides); + this.parent.insertAfter(this, cloned); + return cloned + } + + cloneBefore(overrides = {}) { + let cloned = this.clone(overrides); + this.parent.insertBefore(this, cloned); + return cloned + } + + error(message, opts = {}) { + if (this.source) { + let { end, start } = this.rangeBy(opts); + return this.source.input.error( + message, + { column: start.column, line: start.line }, + { column: end.column, line: end.line }, + opts + ) + } + return new CssSyntaxError$2(message) + } + + getProxyProcessor() { + return { + get(node, prop) { + if (prop === 'proxyOf') { + return node + } else if (prop === 'root') { + return () => node.root().toProxy() + } else { + return node[prop] + } + }, + + set(node, prop, value) { + if (node[prop] === value) return true + node[prop] = value; + if ( + prop === 'prop' || + prop === 'value' || + prop === 'name' || + prop === 'params' || + prop === 'important' || + /* c8 ignore next */ + prop === 'text' + ) { + node.markDirty(); + } + return true + } + } + } + + markDirty() { + if (this[isClean$2]) { + this[isClean$2] = false; + let next = this; + while ((next = next.parent)) { + next[isClean$2] = false; + } + } + } + + next() { + if (!this.parent) return undefined + let index = this.parent.index(this); + return this.parent.nodes[index + 1] + } + + positionBy(opts, stringRepresentation) { + let pos = this.source.start; + if (opts.index) { + pos = this.positionInside(opts.index, stringRepresentation); + } else if (opts.word) { + stringRepresentation = this.toString(); + let index = stringRepresentation.indexOf(opts.word); + if (index !== -1) pos = this.positionInside(index, stringRepresentation); + } + return pos + } + + positionInside(index, stringRepresentation) { + let string = stringRepresentation || this.toString(); + let column = this.source.start.column; + let line = this.source.start.line; + + for (let i = 0; i < index; i++) { + if (string[i] === '\n') { + column = 1; + line += 1; + } else { + column += 1; + } + } + + return { column, line } + } + + prev() { + if (!this.parent) return undefined + let index = this.parent.index(this); + return this.parent.nodes[index - 1] + } + + rangeBy(opts) { + let start = { + column: this.source.start.column, + line: this.source.start.line + }; + let end = this.source.end + ? { + column: this.source.end.column + 1, + line: this.source.end.line + } + : { + column: start.column + 1, + line: start.line + }; + + if (opts.word) { + let stringRepresentation = this.toString(); + let index = stringRepresentation.indexOf(opts.word); + if (index !== -1) { + start = this.positionInside(index, stringRepresentation); + end = this.positionInside(index + opts.word.length, stringRepresentation); + } + } else { + if (opts.start) { + start = { + column: opts.start.column, + line: opts.start.line + }; + } else if (opts.index) { + start = this.positionInside(opts.index); + } + + if (opts.end) { + end = { + column: opts.end.column, + line: opts.end.line + }; + } else if (typeof opts.endIndex === 'number') { + end = this.positionInside(opts.endIndex); + } else if (opts.index) { + end = this.positionInside(opts.index + 1); + } + } + + if ( + end.line < start.line || + (end.line === start.line && end.column <= start.column) + ) { + end = { column: start.column + 1, line: start.line }; + } + + return { end, start } + } + + raw(prop, defaultType) { + let str = new Stringifier(); + return str.raw(this, prop, defaultType) + } + + remove() { + if (this.parent) { + this.parent.removeChild(this); + } + this.parent = undefined; + return this + } + + replaceWith(...nodes) { + if (this.parent) { + let bookmark = this; + let foundSelf = false; + for (let node of nodes) { + if (node === this) { + foundSelf = true; + } else if (foundSelf) { + this.parent.insertAfter(bookmark, node); + bookmark = node; + } else { + this.parent.insertBefore(bookmark, node); + } + } + + if (!foundSelf) { + this.remove(); + } + } + + return this + } + + root() { + let result = this; + while (result.parent && result.parent.type !== 'document') { + result = result.parent; + } + return result + } + + toJSON(_, inputs) { + let fixed = {}; + let emitInputs = inputs == null; + inputs = inputs || new Map(); + let inputsNextIndex = 0; + + for (let name in this) { + if (!Object.prototype.hasOwnProperty.call(this, name)) { + /* c8 ignore next 2 */ + continue + } + if (name === 'parent' || name === 'proxyCache') continue + let value = this[name]; + + if (Array.isArray(value)) { + fixed[name] = value.map(i => { + if (typeof i === 'object' && i.toJSON) { + return i.toJSON(null, inputs) + } else { + return i + } + }); + } else if (typeof value === 'object' && value.toJSON) { + fixed[name] = value.toJSON(null, inputs); + } else if (name === 'source') { + let inputId = inputs.get(value.input); + if (inputId == null) { + inputId = inputsNextIndex; + inputs.set(value.input, inputsNextIndex); + inputsNextIndex++; + } + fixed[name] = { + end: value.end, + inputId, + start: value.start + }; + } else { + fixed[name] = value; + } + } + + if (emitInputs) { + fixed.inputs = [...inputs.keys()].map(input => input.toJSON()); + } + + return fixed + } + + toProxy() { + if (!this.proxyCache) { + this.proxyCache = new Proxy(this, this.getProxyProcessor()); + } + return this.proxyCache + } + + toString(stringifier = stringify$4) { + if (stringifier.stringify) stringifier = stringifier.stringify; + let result = ''; + stringifier(this, i => { + result += i; + }); + return result + } + + warn(result, text, opts) { + let data = { node: this }; + for (let i in opts) data[i] = opts[i]; + return result.warn(text, data) + } + + get proxyOf() { + return this + } + }; + + var node = Node$4; + Node$4.default = Node$4; + + let Node$3 = node; + + let Declaration$4 = class Declaration extends Node$3 { + constructor(defaults) { + if ( + defaults && + typeof defaults.value !== 'undefined' && + typeof defaults.value !== 'string' + ) { + defaults = { ...defaults, value: String(defaults.value) }; + } + super(defaults); + this.type = 'decl'; + } + + get variable() { + return this.prop.startsWith('--') || this.prop[0] === '$' + } + }; + + var declaration = Declaration$4; + Declaration$4.default = Declaration$4; + + var lookup = []; + var revLookup = []; + var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array; + var inited = false; + function init () { + inited = true; + var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i]; + revLookup[code.charCodeAt(i)] = i; + } + + revLookup['-'.charCodeAt(0)] = 62; + revLookup['_'.charCodeAt(0)] = 63; + } + + function toByteArray (b64) { + if (!inited) { + init(); + } + var i, j, l, tmp, placeHolders, arr; + var len = b64.length; + + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + placeHolders = b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0; + + // base64 is 4/3 + up to two characters of the original data + arr = new Arr(len * 3 / 4 - placeHolders); + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? len - 4 : len; + + var L = 0; + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]; + arr[L++] = (tmp >> 16) & 0xFF; + arr[L++] = (tmp >> 8) & 0xFF; + arr[L++] = tmp & 0xFF; + } + + if (placeHolders === 2) { + tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4); + arr[L++] = tmp & 0xFF; + } else if (placeHolders === 1) { + tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2); + arr[L++] = (tmp >> 8) & 0xFF; + arr[L++] = tmp & 0xFF; + } + + return arr + } + + function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F] + } + + function encodeChunk (uint8, start, end) { + var tmp; + var output = []; + for (var i = start; i < end; i += 3) { + tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]); + output.push(tripletToBase64(tmp)); + } + return output.join('') + } + + function fromByteArray (uint8) { + if (!inited) { + init(); + } + var tmp; + var len = uint8.length; + var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes + var output = ''; + var parts = []; + var maxChunkLength = 16383; // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))); + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1]; + output += lookup[tmp >> 2]; + output += lookup[(tmp << 4) & 0x3F]; + output += '=='; + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + (uint8[len - 1]); + output += lookup[tmp >> 10]; + output += lookup[(tmp >> 4) & 0x3F]; + output += lookup[(tmp << 2) & 0x3F]; + output += '='; + } + + parts.push(output); + + return parts.join('') + } + + function read (buffer, offset, isLE, mLen, nBytes) { + var e, m; + var eLen = nBytes * 8 - mLen - 1; + var eMax = (1 << eLen) - 1; + var eBias = eMax >> 1; + var nBits = -7; + var i = isLE ? (nBytes - 1) : 0; + var d = isLE ? -1 : 1; + var s = buffer[offset + i]; + + i += d; + + e = s & ((1 << (-nBits)) - 1); + s >>= (-nBits); + nBits += eLen; + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} + + m = e & ((1 << (-nBits)) - 1); + e >>= (-nBits); + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} + + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity) + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen) + } + + function write (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c; + var eLen = nBytes * 8 - mLen - 1; + var eMax = (1 << eLen) - 1; + var eBias = eMax >> 1; + var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0); + var i = isLE ? 0 : (nBytes - 1); + var d = isLE ? 1 : -1; + var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; + + value = Math.abs(value); + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e + eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + + e = (e << mLen) | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + + buffer[offset + i - d] |= s * 128; + } + + var toString = {}.toString; + + var isArray$1 = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; + }; + + /*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org> + * @license MIT + */ + /* eslint-disable no-proto */ + + + var INSPECT_MAX_BYTES = 50; + + /** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Due to various browser bugs, sometimes the Object implementation will be used even + * when the browser supports typed arrays. + * + * Note: + * + * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they + * get the Object implementation, which is slower but behaves correctly. + */ + Buffer$1.TYPED_ARRAY_SUPPORT = global$1.TYPED_ARRAY_SUPPORT !== undefined + ? global$1.TYPED_ARRAY_SUPPORT + : true; + + /* + * Export kMaxLength after typed array support is determined. + */ + kMaxLength(); + + function kMaxLength () { + return Buffer$1.TYPED_ARRAY_SUPPORT + ? 0x7fffffff + : 0x3fffffff + } + + function createBuffer (that, length) { + if (kMaxLength() < length) { + throw new RangeError('Invalid typed array length') + } + if (Buffer$1.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + that = new Uint8Array(length); + that.__proto__ = Buffer$1.prototype; + } else { + // Fallback: Return an object instance of the Buffer class + if (that === null) { + that = new Buffer$1(length); + } + that.length = length; + } + + return that + } + + /** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ + + function Buffer$1 (arg, encodingOrOffset, length) { + if (!Buffer$1.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer$1)) { + return new Buffer$1(arg, encodingOrOffset, length) + } + + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new Error( + 'If encoding is specified then the first argument must be a string' + ) + } + return allocUnsafe(this, arg) + } + return from(this, arg, encodingOrOffset, length) + } + + Buffer$1.poolSize = 8192; // not used by this implementation + + // TODO: Legacy, not needed anymore. Remove in next major version. + Buffer$1._augment = function (arr) { + arr.__proto__ = Buffer$1.prototype; + return arr + }; + + function from (that, value, encodingOrOffset, length) { + if (typeof value === 'number') { + throw new TypeError('"value" argument must not be a number') + } + + if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { + return fromArrayBuffer(that, value, encodingOrOffset, length) + } + + if (typeof value === 'string') { + return fromString(that, value, encodingOrOffset) + } + + return fromObject(that, value) + } + + /** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ + Buffer$1.from = function (value, encodingOrOffset, length) { + return from(null, value, encodingOrOffset, length) + }; + + if (Buffer$1.TYPED_ARRAY_SUPPORT) { + Buffer$1.prototype.__proto__ = Uint8Array.prototype; + Buffer$1.__proto__ = Uint8Array; + if (typeof Symbol !== 'undefined' && Symbol.species && + Buffer$1[Symbol.species] === Buffer$1) ; + } + + function assertSize (size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be a number') + } else if (size < 0) { + throw new RangeError('"size" argument must not be negative') + } + } + + function alloc (that, size, fill, encoding) { + assertSize(size); + if (size <= 0) { + return createBuffer(that, size) + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpretted as a start offset. + return typeof encoding === 'string' + ? createBuffer(that, size).fill(fill, encoding) + : createBuffer(that, size).fill(fill) + } + return createBuffer(that, size) + } + + /** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ + Buffer$1.alloc = function (size, fill, encoding) { + return alloc(null, size, fill, encoding) + }; + + function allocUnsafe (that, size) { + assertSize(size); + that = createBuffer(that, size < 0 ? 0 : checked(size) | 0); + if (!Buffer$1.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < size; ++i) { + that[i] = 0; + } + } + return that + } + + /** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ + Buffer$1.allocUnsafe = function (size) { + return allocUnsafe(null, size) + }; + /** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ + Buffer$1.allocUnsafeSlow = function (size) { + return allocUnsafe(null, size) + }; + + function fromString (that, string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8'; + } + + if (!Buffer$1.isEncoding(encoding)) { + throw new TypeError('"encoding" must be a valid string encoding') + } + + var length = byteLength(string, encoding) | 0; + that = createBuffer(that, length); + + var actual = that.write(string, encoding); + + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + that = that.slice(0, actual); + } + + return that + } + + function fromArrayLike (that, array) { + var length = array.length < 0 ? 0 : checked(array.length) | 0; + that = createBuffer(that, length); + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255; + } + return that + } + + function fromArrayBuffer (that, array, byteOffset, length) { + array.byteLength; // this throws if `array` is not a valid ArrayBuffer + + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('\'offset\' is out of bounds') + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('\'length\' is out of bounds') + } + + if (byteOffset === undefined && length === undefined) { + array = new Uint8Array(array); + } else if (length === undefined) { + array = new Uint8Array(array, byteOffset); + } else { + array = new Uint8Array(array, byteOffset, length); + } + + if (Buffer$1.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + that = array; + that.__proto__ = Buffer$1.prototype; + } else { + // Fallback: Return an object instance of the Buffer class + that = fromArrayLike(that, array); + } + return that + } + + function fromObject (that, obj) { + if (internalIsBuffer(obj)) { + var len = checked(obj.length) | 0; + that = createBuffer(that, len); + + if (that.length === 0) { + return that + } + + obj.copy(that, 0, 0, len); + return that + } + + if (obj) { + if ((typeof ArrayBuffer !== 'undefined' && + obj.buffer instanceof ArrayBuffer) || 'length' in obj) { + if (typeof obj.length !== 'number' || isnan(obj.length)) { + return createBuffer(that, 0) + } + return fromArrayLike(that, obj) + } + + if (obj.type === 'Buffer' && isArray$1(obj.data)) { + return fromArrayLike(that, obj.data) + } + } + + throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.') + } + + function checked (length) { + // Note: cannot use `length < kMaxLength()` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= kMaxLength()) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength().toString(16) + ' bytes') + } + return length | 0 + } + Buffer$1.isBuffer = isBuffer; + function internalIsBuffer (b) { + return !!(b != null && b._isBuffer) + } + + Buffer$1.compare = function compare (a, b) { + if (!internalIsBuffer(a) || !internalIsBuffer(b)) { + throw new TypeError('Arguments must be Buffers') + } + + if (a === b) return 0 + + var x = a.length; + var y = b.length; + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i]; + y = b[i]; + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 + }; + + Buffer$1.isEncoding = function isEncoding (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } + }; + + Buffer$1.concat = function concat (list, length) { + if (!isArray$1(list)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + + if (list.length === 0) { + return Buffer$1.alloc(0) + } + + var i; + if (length === undefined) { + length = 0; + for (i = 0; i < list.length; ++i) { + length += list[i].length; + } + } + + var buffer = Buffer$1.allocUnsafe(length); + var pos = 0; + for (i = 0; i < list.length; ++i) { + var buf = list[i]; + if (!internalIsBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + buf.copy(buffer, pos); + pos += buf.length; + } + return buffer + }; + + function byteLength (string, encoding) { + if (internalIsBuffer(string)) { + return string.length + } + if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' && + (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) { + return string.byteLength + } + if (typeof string !== 'string') { + string = '' + string; + } + + var len = string.length; + if (len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false; + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + case undefined: + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) return utf8ToBytes(string).length // assume utf8 + encoding = ('' + encoding).toLowerCase(); + loweredCase = true; + } + } + } + Buffer$1.byteLength = byteLength; + + function slowToString (encoding, start, end) { + var loweredCase = false; + + // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + if (start === undefined || start < 0) { + start = 0; + } + // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + if (start > this.length) { + return '' + } + + if (end === undefined || end > this.length) { + end = this.length; + } + + if (end <= 0) { + return '' + } + + // Force coersion to uint32. This will also coerce falsey/NaN values to 0. + end >>>= 0; + start >>>= 0; + + if (end <= start) { + return '' + } + + if (!encoding) encoding = 'utf8'; + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'latin1': + case 'binary': + return latin1Slice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase(); + loweredCase = true; + } + } + } + + // The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect + // Buffer instances. + Buffer$1.prototype._isBuffer = true; + + function swap (b, n, m) { + var i = b[n]; + b[n] = b[m]; + b[m] = i; + } + + Buffer$1.prototype.swap16 = function swap16 () { + var len = this.length; + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (var i = 0; i < len; i += 2) { + swap(this, i, i + 1); + } + return this + }; + + Buffer$1.prototype.swap32 = function swap32 () { + var len = this.length; + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (var i = 0; i < len; i += 4) { + swap(this, i, i + 3); + swap(this, i + 1, i + 2); + } + return this + }; + + Buffer$1.prototype.swap64 = function swap64 () { + var len = this.length; + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (var i = 0; i < len; i += 8) { + swap(this, i, i + 7); + swap(this, i + 1, i + 6); + swap(this, i + 2, i + 5); + swap(this, i + 3, i + 4); + } + return this + }; + + Buffer$1.prototype.toString = function toString () { + var length = this.length | 0; + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) + }; + + Buffer$1.prototype.equals = function equals (b) { + if (!internalIsBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer$1.compare(this, b) === 0 + }; + + Buffer$1.prototype.inspect = function inspect () { + var str = ''; + var max = INSPECT_MAX_BYTES; + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' '); + if (this.length > max) str += ' ... '; + } + return '<Buffer ' + str + '>' + }; + + Buffer$1.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { + if (!internalIsBuffer(target)) { + throw new TypeError('Argument must be a Buffer') + } + + if (start === undefined) { + start = 0; + } + if (end === undefined) { + end = target ? target.length : 0; + } + if (thisStart === undefined) { + thisStart = 0; + } + if (thisEnd === undefined) { + thisEnd = this.length; + } + + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index') + } + + if (thisStart >= thisEnd && start >= end) { + return 0 + } + if (thisStart >= thisEnd) { + return -1 + } + if (start >= end) { + return 1 + } + + start >>>= 0; + end >>>= 0; + thisStart >>>= 0; + thisEnd >>>= 0; + + if (this === target) return 0 + + var x = thisEnd - thisStart; + var y = end - start; + var len = Math.min(x, y); + + var thisCopy = this.slice(thisStart, thisEnd); + var targetCopy = target.slice(start, end); + + for (var i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i]; + y = targetCopy[i]; + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 + }; + + // Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, + // OR the last index of `val` in `buffer` at offset <= `byteOffset`. + // + // Arguments: + // - buffer - a Buffer to search + // - val - a string, Buffer, or number + // - byteOffset - an index into `buffer`; will be clamped to an int32 + // - encoding - an optional encoding, relevant is val is a string + // - dir - true for indexOf, false for lastIndexOf + function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1 + + // Normalize byteOffset + if (typeof byteOffset === 'string') { + encoding = byteOffset; + byteOffset = 0; + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff; + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000; + } + byteOffset = +byteOffset; // Coerce to Number. + if (isNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : (buffer.length - 1); + } + + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset; + if (byteOffset >= buffer.length) { + if (dir) return -1 + else byteOffset = buffer.length - 1; + } else if (byteOffset < 0) { + if (dir) byteOffset = 0; + else return -1 + } + + // Normalize val + if (typeof val === 'string') { + val = Buffer$1.from(val, encoding); + } + + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (internalIsBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1 + } + return arrayIndexOf(buffer, val, byteOffset, encoding, dir) + } else if (typeof val === 'number') { + val = val & 0xFF; // Search for a byte value [0-255] + if (Buffer$1.TYPED_ARRAY_SUPPORT && + typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) + } + } + return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) + } + + throw new TypeError('val must be string, number or Buffer') + } + + function arrayIndexOf (arr, val, byteOffset, encoding, dir) { + var indexSize = 1; + var arrLength = arr.length; + var valLength = val.length; + + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase(); + if (encoding === 'ucs2' || encoding === 'ucs-2' || + encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1 + } + indexSize = 2; + arrLength /= 2; + valLength /= 2; + byteOffset /= 2; + } + } + + function read (buf, i) { + if (indexSize === 1) { + return buf[i] + } else { + return buf.readUInt16BE(i * indexSize) + } + } + + var i; + if (dir) { + var foundIndex = -1; + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i; + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize + } else { + if (foundIndex !== -1) i -= i - foundIndex; + foundIndex = -1; + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength; + for (i = byteOffset; i >= 0; i--) { + var found = true; + for (var j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false; + break + } + } + if (found) return i + } + } + + return -1 + } + + Buffer$1.prototype.includes = function includes (val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1 + }; + + Buffer$1.prototype.indexOf = function indexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true) + }; + + Buffer$1.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false) + }; + + function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0; + var remaining = buf.length - offset; + if (!length) { + length = remaining; + } else { + length = Number(length); + if (length > remaining) { + length = remaining; + } + } + + // must be an even number of digits + var strLen = string.length; + if (strLen % 2 !== 0) throw new TypeError('Invalid hex string') + + if (length > strLen / 2) { + length = strLen / 2; + } + for (var i = 0; i < length; ++i) { + var parsed = parseInt(string.substr(i * 2, 2), 16); + if (isNaN(parsed)) return i + buf[offset + i] = parsed; + } + return i + } + + function utf8Write (buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) + } + + function asciiWrite (buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) + } + + function latin1Write (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) + } + + function base64Write (buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) + } + + function ucs2Write (buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) + } + + Buffer$1.prototype.write = function write (string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8'; + length = this.length; + offset = 0; + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset; + length = this.length; + offset = 0; + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset | 0; + if (isFinite(length)) { + length = length | 0; + if (encoding === undefined) encoding = 'utf8'; + } else { + encoding = length; + length = undefined; + } + // legacy write(string, encoding, offset, length) - remove in v0.13 + } else { + throw new Error( + 'Buffer.write(string, encoding, offset[, length]) is no longer supported' + ) + } + + var remaining = this.length - offset; + if (length === undefined || length > remaining) length = remaining; + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8'; + + var loweredCase = false; + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + return asciiWrite(this, string, offset, length) + + case 'latin1': + case 'binary': + return latin1Write(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase(); + loweredCase = true; + } + } + }; + + Buffer$1.prototype.toJSON = function toJSON () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } + }; + + function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return fromByteArray(buf) + } else { + return fromByteArray(buf.slice(start, end)) + } + } + + function utf8Slice (buf, start, end) { + end = Math.min(buf.length, end); + var res = []; + + var i = start; + while (i < end) { + var firstByte = buf[i]; + var codePoint = null; + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1; + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint; + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte; + } + break + case 2: + secondByte = buf[i + 1]; + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F); + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint; + } + } + break + case 3: + secondByte = buf[i + 1]; + thirdByte = buf[i + 2]; + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F); + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint; + } + } + break + case 4: + secondByte = buf[i + 1]; + thirdByte = buf[i + 2]; + fourthByte = buf[i + 3]; + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F); + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint; + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD; + bytesPerSequence = 1; + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000; + res.push(codePoint >>> 10 & 0x3FF | 0xD800); + codePoint = 0xDC00 | codePoint & 0x3FF; + } + + res.push(codePoint); + i += bytesPerSequence; + } + + return decodeCodePointsArray(res) + } + + // Based on http://stackoverflow.com/a/22747272/680742, the browser with + // the lowest limit is Chrome, with 0x10000 args. + // We go 1 magnitude less, for safety + var MAX_ARGUMENTS_LENGTH = 0x1000; + + function decodeCodePointsArray (codePoints) { + var len = codePoints.length; + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + var res = ''; + var i = 0; + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ); + } + return res + } + + function asciiSlice (buf, start, end) { + var ret = ''; + end = Math.min(buf.length, end); + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F); + } + return ret + } + + function latin1Slice (buf, start, end) { + var ret = ''; + end = Math.min(buf.length, end); + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]); + } + return ret + } + + function hexSlice (buf, start, end) { + var len = buf.length; + + if (!start || start < 0) start = 0; + if (!end || end < 0 || end > len) end = len; + + var out = ''; + for (var i = start; i < end; ++i) { + out += toHex(buf[i]); + } + return out + } + + function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end); + var res = ''; + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256); + } + return res + } + + Buffer$1.prototype.slice = function slice (start, end) { + var len = this.length; + start = ~~start; + end = end === undefined ? len : ~~end; + + if (start < 0) { + start += len; + if (start < 0) start = 0; + } else if (start > len) { + start = len; + } + + if (end < 0) { + end += len; + if (end < 0) end = 0; + } else if (end > len) { + end = len; + } + + if (end < start) end = start; + + var newBuf; + if (Buffer$1.TYPED_ARRAY_SUPPORT) { + newBuf = this.subarray(start, end); + newBuf.__proto__ = Buffer$1.prototype; + } else { + var sliceLen = end - start; + newBuf = new Buffer$1(sliceLen, undefined); + for (var i = 0; i < sliceLen; ++i) { + newBuf[i] = this[i + start]; + } + } + + return newBuf + }; + + /* + * Need to make sure that buffer isn't trying to write out of bounds. + */ + function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') + } + + Buffer$1.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset | 0; + byteLength = byteLength | 0; + if (!noAssert) checkOffset(offset, byteLength, this.length); + + var val = this[offset]; + var mul = 1; + var i = 0; + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul; + } + + return val + }; + + Buffer$1.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset | 0; + byteLength = byteLength | 0; + if (!noAssert) { + checkOffset(offset, byteLength, this.length); + } + + var val = this[offset + --byteLength]; + var mul = 1; + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul; + } + + return val + }; + + Buffer$1.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length); + return this[offset] + }; + + Buffer$1.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length); + return this[offset] | (this[offset + 1] << 8) + }; + + Buffer$1.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length); + return (this[offset] << 8) | this[offset + 1] + }; + + Buffer$1.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length); + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) + }; + + Buffer$1.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length); + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) + }; + + Buffer$1.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset | 0; + byteLength = byteLength | 0; + if (!noAssert) checkOffset(offset, byteLength, this.length); + + var val = this[offset]; + var mul = 1; + var i = 0; + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul; + } + mul *= 0x80; + + if (val >= mul) val -= Math.pow(2, 8 * byteLength); + + return val + }; + + Buffer$1.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset | 0; + byteLength = byteLength | 0; + if (!noAssert) checkOffset(offset, byteLength, this.length); + + var i = byteLength; + var mul = 1; + var val = this[offset + --i]; + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul; + } + mul *= 0x80; + + if (val >= mul) val -= Math.pow(2, 8 * byteLength); + + return val + }; + + Buffer$1.prototype.readInt8 = function readInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length); + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) + }; + + Buffer$1.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length); + var val = this[offset] | (this[offset + 1] << 8); + return (val & 0x8000) ? val | 0xFFFF0000 : val + }; + + Buffer$1.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length); + var val = this[offset + 1] | (this[offset] << 8); + return (val & 0x8000) ? val | 0xFFFF0000 : val + }; + + Buffer$1.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length); + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) + }; + + Buffer$1.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length); + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) + }; + + Buffer$1.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length); + return read(this, offset, true, 23, 4) + }; + + Buffer$1.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length); + return read(this, offset, false, 23, 4) + }; + + Buffer$1.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length); + return read(this, offset, true, 52, 8) + }; + + Buffer$1.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length); + return read(this, offset, false, 52, 8) + }; + + function checkInt (buf, value, offset, ext, max, min) { + if (!internalIsBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') + if (offset + ext > buf.length) throw new RangeError('Index out of range') + } + + Buffer$1.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value; + offset = offset | 0; + byteLength = byteLength | 0; + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1; + checkInt(this, value, offset, byteLength, maxBytes, 0); + } + + var mul = 1; + var i = 0; + this[offset] = value & 0xFF; + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF; + } + + return offset + byteLength + }; + + Buffer$1.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value; + offset = offset | 0; + byteLength = byteLength | 0; + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1; + checkInt(this, value, offset, byteLength, maxBytes, 0); + } + + var i = byteLength - 1; + var mul = 1; + this[offset + i] = value & 0xFF; + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF; + } + + return offset + byteLength + }; + + Buffer$1.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0); + if (!Buffer$1.TYPED_ARRAY_SUPPORT) value = Math.floor(value); + this[offset] = (value & 0xff); + return offset + 1 + }; + + function objectWriteUInt16 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffff + value + 1; + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) { + buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8; + } + } + + Buffer$1.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); + if (Buffer$1.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff); + this[offset + 1] = (value >>> 8); + } else { + objectWriteUInt16(this, value, offset, true); + } + return offset + 2 + }; + + Buffer$1.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); + if (Buffer$1.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8); + this[offset + 1] = (value & 0xff); + } else { + objectWriteUInt16(this, value, offset, false); + } + return offset + 2 + }; + + function objectWriteUInt32 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffffffff + value + 1; + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) { + buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff; + } + } + + Buffer$1.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); + if (Buffer$1.TYPED_ARRAY_SUPPORT) { + this[offset + 3] = (value >>> 24); + this[offset + 2] = (value >>> 16); + this[offset + 1] = (value >>> 8); + this[offset] = (value & 0xff); + } else { + objectWriteUInt32(this, value, offset, true); + } + return offset + 4 + }; + + Buffer$1.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); + if (Buffer$1.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24); + this[offset + 1] = (value >>> 16); + this[offset + 2] = (value >>> 8); + this[offset + 3] = (value & 0xff); + } else { + objectWriteUInt32(this, value, offset, false); + } + return offset + 4 + }; + + Buffer$1.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value; + offset = offset | 0; + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1); + + checkInt(this, value, offset, byteLength, limit - 1, -limit); + } + + var i = 0; + var mul = 1; + var sub = 0; + this[offset] = value & 0xFF; + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1; + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF; + } + + return offset + byteLength + }; + + Buffer$1.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value; + offset = offset | 0; + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1); + + checkInt(this, value, offset, byteLength, limit - 1, -limit); + } + + var i = byteLength - 1; + var mul = 1; + var sub = 0; + this[offset + i] = value & 0xFF; + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1; + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF; + } + + return offset + byteLength + }; + + Buffer$1.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!Buffer$1.TYPED_ARRAY_SUPPORT) value = Math.floor(value); + if (value < 0) value = 0xff + value + 1; + this[offset] = (value & 0xff); + return offset + 1 + }; + + Buffer$1.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (Buffer$1.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff); + this[offset + 1] = (value >>> 8); + } else { + objectWriteUInt16(this, value, offset, true); + } + return offset + 2 + }; + + Buffer$1.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + if (Buffer$1.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8); + this[offset + 1] = (value & 0xff); + } else { + objectWriteUInt16(this, value, offset, false); + } + return offset + 2 + }; + + Buffer$1.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (Buffer$1.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff); + this[offset + 1] = (value >>> 8); + this[offset + 2] = (value >>> 16); + this[offset + 3] = (value >>> 24); + } else { + objectWriteUInt32(this, value, offset, true); + } + return offset + 4 + }; + + Buffer$1.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (value < 0) value = 0xffffffff + value + 1; + if (Buffer$1.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24); + this[offset + 1] = (value >>> 16); + this[offset + 2] = (value >>> 8); + this[offset + 3] = (value & 0xff); + } else { + objectWriteUInt32(this, value, offset, false); + } + return offset + 4 + }; + + function checkIEEE754 (buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range') + if (offset < 0) throw new RangeError('Index out of range') + } + + function writeFloat (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 4); + } + write(buf, value, offset, littleEndian, 23, 4); + return offset + 4 + } + + Buffer$1.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) + }; + + Buffer$1.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) + }; + + function writeDouble (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 8); + } + write(buf, value, offset, littleEndian, 52, 8); + return offset + 8 + } + + Buffer$1.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) + }; + + Buffer$1.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) + }; + + // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) + Buffer$1.prototype.copy = function copy (target, targetStart, start, end) { + if (!start) start = 0; + if (!end && end !== 0) end = this.length; + if (targetStart >= target.length) targetStart = target.length; + if (!targetStart) targetStart = 0; + if (end > 0 && end < start) end = start; + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length; + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start; + } + + var len = end - start; + var i; + + if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (i = len - 1; i >= 0; --i) { + target[i + targetStart] = this[i + start]; + } + } else if (len < 1000 || !Buffer$1.TYPED_ARRAY_SUPPORT) { + // ascending copy from start + for (i = 0; i < len; ++i) { + target[i + targetStart] = this[i + start]; + } + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, start + len), + targetStart + ); + } + + return len + }; + + // Usage: + // buffer.fill(number[, offset[, end]]) + // buffer.fill(buffer[, offset[, end]]) + // buffer.fill(string[, offset[, end]][, encoding]) + Buffer$1.prototype.fill = function fill (val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start; + start = 0; + end = this.length; + } else if (typeof end === 'string') { + encoding = end; + end = this.length; + } + if (val.length === 1) { + var code = val.charCodeAt(0); + if (code < 256) { + val = code; + } + } + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string') + } + if (typeof encoding === 'string' && !Buffer$1.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + } else if (typeof val === 'number') { + val = val & 255; + } + + // Invalid ranges are not set to a default, so can range check early. + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index') + } + + if (end <= start) { + return this + } + + start = start >>> 0; + end = end === undefined ? this.length : end >>> 0; + + if (!val) val = 0; + + var i; + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val; + } + } else { + var bytes = internalIsBuffer(val) + ? val + : utf8ToBytes(new Buffer$1(val, encoding).toString()); + var len = bytes.length; + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len]; + } + } + + return this + }; + + // HELPER FUNCTIONS + // ================ + + var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g; + + function base64clean (str) { + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = stringtrim(str).replace(INVALID_BASE64_RE, ''); + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '='; + } + return str + } + + function stringtrim (str) { + if (str.trim) return str.trim() + return str.replace(/^\s+|\s+$/g, '') + } + + function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) + } + + function utf8ToBytes (string, units) { + units = units || Infinity; + var codePoint; + var length = string.length; + var leadSurrogate = null; + var bytes = []; + + for (var i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i); + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); + continue + } + + // valid lead + leadSurrogate = codePoint; + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); + leadSurrogate = codePoint; + continue + } + + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000; + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); + } + + leadSurrogate = null; + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint); + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ); + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ); + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ); + } else { + throw new Error('Invalid code point') + } + } + + return bytes + } + + function asciiToBytes (str) { + var byteArray = []; + for (var i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF); + } + return byteArray + } + + function utf16leToBytes (str, units) { + var c, hi, lo; + var byteArray = []; + for (var i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i); + hi = c >> 8; + lo = c % 256; + byteArray.push(lo); + byteArray.push(hi); + } + + return byteArray + } + + + function base64ToBytes (str) { + return toByteArray(base64clean(str)) + } + + function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i]; + } + return i + } + + function isnan (val) { + return val !== val // eslint-disable-line no-self-compare + } + + + // the following is from is-buffer, also by Feross Aboukhadijeh and with same lisence + // The _isBuffer check is for Safari 5-7 support, because it's missing + // Object.prototype.constructor. Remove this eventually + function isBuffer(obj) { + return obj != null && (!!obj._isBuffer || isFastBuffer(obj) || isSlowBuffer(obj)) + } + + function isFastBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) + } + + // For Node v0.10 support. Remove this eventually. + function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isFastBuffer(obj.slice(0, 0)) + } + + var sourceMap = {}; + + var sourceMapGenerator = {}; + + var base64Vlq = {}; + + var base64$1 = {}; + + /* -*- Mode: js; js-indent-level: 2; -*- */ + + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + base64$1.encode = function (number) { + if (0 <= number && number < intToCharMap.length) { + return intToCharMap[number]; + } + throw new TypeError("Must be between 0 and 63: " + number); + }; + + /** + * Decode a single base 64 character code digit to an integer. Returns -1 on + * failure. + */ + base64$1.decode = function (charCode) { + var bigA = 65; // 'A' + var bigZ = 90; // 'Z' + + var littleA = 97; // 'a' + var littleZ = 122; // 'z' + + var zero = 48; // '0' + var nine = 57; // '9' + + var plus = 43; // '+' + var slash = 47; // '/' + + var littleOffset = 26; + var numberOffset = 52; + + // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ + if (bigA <= charCode && charCode <= bigZ) { + return (charCode - bigA); + } + + // 26 - 51: abcdefghijklmnopqrstuvwxyz + if (littleA <= charCode && charCode <= littleZ) { + return (charCode - littleA + littleOffset); + } + + // 52 - 61: 0123456789 + if (zero <= charCode && charCode <= nine) { + return (charCode - zero + numberOffset); + } + + // 62: + + if (charCode == plus) { + return 62; + } + + // 63: / + if (charCode == slash) { + return 63; + } + + // Invalid base64 digit. + return -1; + }; + + /* -*- Mode: js; js-indent-level: 2; -*- */ + + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + var base64 = base64$1; + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + base64Vlq.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string via the out parameter. + */ + base64Vlq.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) { + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (aIndex >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + + digit = base64.decode(aStr.charCodeAt(aIndex++)); + if (digit === -1) { + throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1)); + } + + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + aOutParam.value = fromVLQSigned(result); + aOutParam.rest = aIndex; + }; + + var util$5 = {}; + + /* -*- Mode: js; js-indent-level: 2; -*- */ + + (function (exports) { + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/; + var dataUrlRegexp = /^data:.+\,.+$/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[2], + host: match[3], + port: match[4], + path: match[5] + }; + } + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = ''; + if (aParsedUrl.scheme) { + url += aParsedUrl.scheme + ':'; + } + url += '//'; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + '@'; + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port; + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; + } + exports.urlGenerate = urlGenerate; + + var MAX_CACHED_INPUTS = 32; + + /** + * Takes some function `f(input) -> result` and returns a memoized version of + * `f`. + * + * We keep at most `MAX_CACHED_INPUTS` memoized results of `f` alive. The + * memoization is a dumb-simple, linear least-recently-used cache. + */ + function lruMemoize(f) { + var cache = []; + + return function(input) { + for (var i = 0; i < cache.length; i++) { + if (cache[i].input === input) { + var temp = cache[0]; + cache[0] = cache[i]; + cache[i] = temp; + return cache[0].result; + } + } + + var result = f(input); + + cache.unshift({ + input, + result, + }); + + if (cache.length > MAX_CACHED_INPUTS) { + cache.pop(); + } + + return result; + }; + } + + /** + * Normalizes a path, or the path portion of a URL: + * + * - Replaces consecutive slashes with one slash. + * - Removes unnecessary '.' parts. + * - Removes unnecessary '<dir>/..' parts. + * + * Based on code in the Node.js 'path' core module. + * + * @param aPath The path or url to normalize. + */ + var normalize = lruMemoize(function normalize(aPath) { + var path = aPath; + var url = urlParse(aPath); + if (url) { + if (!url.path) { + return aPath; + } + path = url.path; + } + var isAbsolute = exports.isAbsolute(path); + // Split the path into parts between `/` characters. This is much faster than + // using `.split(/\/+/g)`. + var parts = []; + var start = 0; + var i = 0; + while (true) { + start = i; + i = path.indexOf("/", start); + if (i === -1) { + parts.push(path.slice(start)); + break; + } else { + parts.push(path.slice(start, i)); + while (i < path.length && path[i] === "/") { + i++; + } + } + } + + for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { + part = parts[i]; + if (part === '.') { + parts.splice(i, 1); + } else if (part === '..') { + up++; + } else if (up > 0) { + if (part === '') { + // The first part is blank if the path is absolute. Trying to go + // above the root is a no-op. Therefore we can remove all '..' parts + // directly after the root. + parts.splice(i + 1, up); + up = 0; + } else { + parts.splice(i, 2); + up--; + } + } + } + path = parts.join('/'); + + if (path === '') { + path = isAbsolute ? '/' : '.'; + } + + if (url) { + url.path = path; + return urlGenerate(url); + } + return path; + }); + exports.normalize = normalize; + + /** + * Joins two paths/URLs. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be joined with the root. + * + * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a + * scheme-relative URL: Then the scheme of aRoot, if any, is prepended + * first. + * - Otherwise aPath is a path. If aRoot is a URL, then its path portion + * is updated with the result and aRoot is returned. Otherwise the result + * is returned. + * - If aPath is absolute, the result is aPath. + * - Otherwise the two paths are joined with a slash. + * - Joining for example 'http://' and 'www.example.com' is also supported. + */ + function join(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + if (aPath === "") { + aPath = "."; + } + var aPathUrl = urlParse(aPath); + var aRootUrl = urlParse(aRoot); + if (aRootUrl) { + aRoot = aRootUrl.path || '/'; + } + + // `join(foo, '//www.example.org')` + if (aPathUrl && !aPathUrl.scheme) { + if (aRootUrl) { + aPathUrl.scheme = aRootUrl.scheme; + } + return urlGenerate(aPathUrl); + } + + if (aPathUrl || aPath.match(dataUrlRegexp)) { + return aPath; + } + + // `join('http://', 'www.example.com')` + if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { + aRootUrl.host = aPath; + return urlGenerate(aRootUrl); + } + + var joined = aPath.charAt(0) === '/' + ? aPath + : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); + + if (aRootUrl) { + aRootUrl.path = joined; + return urlGenerate(aRootUrl); + } + return joined; + } + exports.join = join; + + exports.isAbsolute = function (aPath) { + return aPath.charAt(0) === '/' || urlRegexp.test(aPath); + }; + + /** + * Make a path relative to a URL or another path. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be made relative to aRoot. + */ + function relative(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + + aRoot = aRoot.replace(/\/$/, ''); + + // It is possible for the path to be above the root. In this case, simply + // checking whether the root is a prefix of the path won't work. Instead, we + // need to remove components from the root one by one, until either we find + // a prefix that fits, or we run out of components to remove. + var level = 0; + while (aPath.indexOf(aRoot + '/') !== 0) { + var index = aRoot.lastIndexOf("/"); + if (index < 0) { + return aPath; + } + + // If the only part of the root that is left is the scheme (i.e. http://, + // file:///, etc.), one or more slashes (/), or simply nothing at all, we + // have exhausted all components, so the path is not relative to the root. + aRoot = aRoot.slice(0, index); + if (aRoot.match(/^([^\/]+:\/)?\/*$/)) { + return aPath; + } + + ++level; + } + + // Make sure we add a "../" for each component we removed from the root. + return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1); + } + exports.relative = relative; + + var supportsNullProto = (function () { + var obj = Object.create(null); + return !('__proto__' in obj); + }()); + + function identity (s) { + return s; + } + + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + if (isProtoString(aStr)) { + return '$' + aStr; + } + + return aStr; + } + exports.toSetString = supportsNullProto ? identity : toSetString; + + function fromSetString(aStr) { + if (isProtoString(aStr)) { + return aStr.slice(1); + } + + return aStr; + } + exports.fromSetString = supportsNullProto ? identity : fromSetString; + + function isProtoString(s) { + if (!s) { + return false; + } + + var length = s.length; + + if (length < 9 /* "__proto__".length */) { + return false; + } + + if (s.charCodeAt(length - 1) !== 95 /* '_' */ || + s.charCodeAt(length - 2) !== 95 /* '_' */ || + s.charCodeAt(length - 3) !== 111 /* 'o' */ || + s.charCodeAt(length - 4) !== 116 /* 't' */ || + s.charCodeAt(length - 5) !== 111 /* 'o' */ || + s.charCodeAt(length - 6) !== 114 /* 'r' */ || + s.charCodeAt(length - 7) !== 112 /* 'p' */ || + s.charCodeAt(length - 8) !== 95 /* '_' */ || + s.charCodeAt(length - 9) !== 95 /* '_' */) { + return false; + } + + for (var i = length - 10; i >= 0; i--) { + if (s.charCodeAt(i) !== 36 /* '$' */) { + return false; + } + } + + return true; + } + + /** + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. + */ + function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp = strcmp(mappingA.source, mappingB.source); + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0 || onlyCompareOriginal) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + } + exports.compareByOriginalPositions = compareByOriginalPositions; + + function compareByOriginalPositionsNoSource(mappingA, mappingB, onlyCompareOriginal) { + var cmp; + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0 || onlyCompareOriginal) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + } + exports.compareByOriginalPositionsNoSource = compareByOriginalPositionsNoSource; + + /** + * Comparator between two mappings with deflated source and name indices where + * the generated positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. + */ + function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0 || onlyCompareGenerated) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + } + exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated; + + function compareByGeneratedPositionsDeflatedNoLine(mappingA, mappingB, onlyCompareGenerated) { + var cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0 || onlyCompareGenerated) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + } + exports.compareByGeneratedPositionsDeflatedNoLine = compareByGeneratedPositionsDeflatedNoLine; + + function strcmp(aStr1, aStr2) { + if (aStr1 === aStr2) { + return 0; + } + + if (aStr1 === null) { + return 1; // aStr2 !== null + } + + if (aStr2 === null) { + return -1; // aStr1 !== null + } + + if (aStr1 > aStr2) { + return 1; + } + + return -1; + } + + /** + * Comparator between two mappings with inflated source and name strings where + * the generated positions are compared. + */ + function compareByGeneratedPositionsInflated(mappingA, mappingB) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp !== 0) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp !== 0) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp !== 0) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + } + exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated; + + /** + * Strip any JSON XSSI avoidance prefix from the string (as documented + * in the source maps specification), and then parse the string as + * JSON. + */ + function parseSourceMapInput(str) { + return JSON.parse(str.replace(/^\)]}'[^\n]*\n/, '')); + } + exports.parseSourceMapInput = parseSourceMapInput; + + /** + * Compute the URL of a source given the the source root, the source's + * URL, and the source map's URL. + */ + function computeSourceURL(sourceRoot, sourceURL, sourceMapURL) { + sourceURL = sourceURL || ''; + + if (sourceRoot) { + // This follows what Chrome does. + if (sourceRoot[sourceRoot.length - 1] !== '/' && sourceURL[0] !== '/') { + sourceRoot += '/'; + } + // The spec says: + // Line 4: An optional source root, useful for relocating source + // files on a server or removing repeated values in the + // “sources” entry. This value is prepended to the individual + // entries in the “source” field. + sourceURL = sourceRoot + sourceURL; + } + + // Historically, SourceMapConsumer did not take the sourceMapURL as + // a parameter. This mode is still somewhat supported, which is why + // this code block is conditional. However, it's preferable to pass + // the source map URL to SourceMapConsumer, so that this function + // can implement the source URL resolution algorithm as outlined in + // the spec. This block is basically the equivalent of: + // new URL(sourceURL, sourceMapURL).toString() + // ... except it avoids using URL, which wasn't available in the + // older releases of node still supported by this library. + // + // The spec says: + // If the sources are not absolute URLs after prepending of the + // “sourceRoot”, the sources are resolved relative to the + // SourceMap (like resolving script src in a html document). + if (sourceMapURL) { + var parsed = urlParse(sourceMapURL); + if (!parsed) { + throw new Error("sourceMapURL could not be parsed"); + } + if (parsed.path) { + // Strip the last path component, but keep the "/". + var index = parsed.path.lastIndexOf('/'); + if (index >= 0) { + parsed.path = parsed.path.substring(0, index + 1); + } + } + sourceURL = join(urlGenerate(parsed), sourceURL); + } + + return normalize(sourceURL); + } + exports.computeSourceURL = computeSourceURL; + } (util$5)); + + var arraySet = {}; + + /* -*- Mode: js; js-indent-level: 2; -*- */ + + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var util$4 = util$5; + var has$1 = Object.prototype.hasOwnProperty; + var hasNativeMap = typeof Map !== "undefined"; + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet$2() { + this._array = []; + this._set = hasNativeMap ? new Map() : Object.create(null); + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet$2.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet$2(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); + } + return set; + }; + + /** + * Return how many unique items are in this ArraySet. If duplicates have been + * added, than those do not count towards the size. + * + * @returns Number + */ + ArraySet$2.prototype.size = function ArraySet_size() { + return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet$2.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var sStr = hasNativeMap ? aStr : util$4.toSetString(aStr); + var isDuplicate = hasNativeMap ? this.has(aStr) : has$1.call(this._set, sStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + if (hasNativeMap) { + this._set.set(aStr, idx); + } else { + this._set[sStr] = idx; + } + } + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet$2.prototype.has = function ArraySet_has(aStr) { + if (hasNativeMap) { + return this._set.has(aStr); + } else { + var sStr = util$4.toSetString(aStr); + return has$1.call(this._set, sStr); + } + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet$2.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (hasNativeMap) { + var idx = this._set.get(aStr); + if (idx >= 0) { + return idx; + } + } else { + var sStr = util$4.toSetString(aStr); + if (has$1.call(this._set, sStr)) { + return this._set[sStr]; + } + } + + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet$2.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet$2.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + arraySet.ArraySet = ArraySet$2; + + var mappingList = {}; + + /* -*- Mode: js; js-indent-level: 2; -*- */ + + /* + * Copyright 2014 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var util$3 = util$5; + + /** + * Determine whether mappingB is after mappingA with respect to generated + * position. + */ + function generatedPositionAfter(mappingA, mappingB) { + // Optimized for most common case + var lineA = mappingA.generatedLine; + var lineB = mappingB.generatedLine; + var columnA = mappingA.generatedColumn; + var columnB = mappingB.generatedColumn; + return lineB > lineA || lineB == lineA && columnB >= columnA || + util$3.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0; + } + + /** + * A data structure to provide a sorted view of accumulated mappings in a + * performance conscious manner. It trades a neglibable overhead in general + * case for a large speedup in case of mappings being added in order. + */ + function MappingList$1() { + this._array = []; + this._sorted = true; + // Serves as infimum + this._last = {generatedLine: -1, generatedColumn: 0}; + } + + /** + * Iterate through internal items. This method takes the same arguments that + * `Array.prototype.forEach` takes. + * + * NOTE: The order of the mappings is NOT guaranteed. + */ + MappingList$1.prototype.unsortedForEach = + function MappingList_forEach(aCallback, aThisArg) { + this._array.forEach(aCallback, aThisArg); + }; + + /** + * Add the given source mapping. + * + * @param Object aMapping + */ + MappingList$1.prototype.add = function MappingList_add(aMapping) { + if (generatedPositionAfter(this._last, aMapping)) { + this._last = aMapping; + this._array.push(aMapping); + } else { + this._sorted = false; + this._array.push(aMapping); + } + }; + + /** + * Returns the flat, sorted array of mappings. The mappings are sorted by + * generated position. + * + * WARNING: This method returns internal data without copying, for + * performance. The return value must NOT be mutated, and should be treated as + * an immutable borrow. If you want to take ownership, you must make your own + * copy. + */ + MappingList$1.prototype.toArray = function MappingList_toArray() { + if (!this._sorted) { + this._array.sort(util$3.compareByGeneratedPositionsInflated); + this._sorted = true; + } + return this._array; + }; + + mappingList.MappingList = MappingList$1; + + /* -*- Mode: js; js-indent-level: 2; -*- */ + + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var base64VLQ$1 = base64Vlq; + var util$2 = util$5; + var ArraySet$1 = arraySet.ArraySet; + var MappingList = mappingList.MappingList; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. You may pass an object with the following + * properties: + * + * - file: The filename of the generated source. + * - sourceRoot: A root for all relative URLs in this source map. + */ + function SourceMapGenerator$4(aArgs) { + if (!aArgs) { + aArgs = {}; + } + this._file = util$2.getArg(aArgs, 'file', null); + this._sourceRoot = util$2.getArg(aArgs, 'sourceRoot', null); + this._skipValidation = util$2.getArg(aArgs, 'skipValidation', false); + this._ignoreInvalidMapping = util$2.getArg(aArgs, 'ignoreInvalidMapping', false); + this._sources = new ArraySet$1(); + this._names = new ArraySet$1(); + this._mappings = new MappingList(); + this._sourcesContents = null; + } + + SourceMapGenerator$4.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator$4.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer, generatorOps) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator$4(Object.assign(generatorOps || {}, { + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + })); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source != null) { + newMapping.source = mapping.source; + if (sourceRoot != null) { + newMapping.source = util$2.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name != null) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var sourceRelative = sourceFile; + if (sourceRoot !== null) { + sourceRelative = util$2.relative(sourceRoot, sourceFile); + } + + if (!generator._sources.has(sourceRelative)) { + generator._sources.add(sourceRelative); + } + + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator$4.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util$2.getArg(aArgs, 'generated'); + var original = util$2.getArg(aArgs, 'original', null); + var source = util$2.getArg(aArgs, 'source', null); + var name = util$2.getArg(aArgs, 'name', null); + + if (!this._skipValidation) { + if (this._validateMapping(generated, original, source, name) === false) { + return; + } + } + + if (source != null) { + source = String(source); + if (!this._sources.has(source)) { + this._sources.add(source); + } + } + + if (name != null) { + name = String(name); + if (!this._names.has(name)) { + this._names.add(name); + } + } + + this._mappings.add({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator$4.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot != null) { + source = util$2.relative(this._sourceRoot, source); + } + + if (aSourceContent != null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = Object.create(null); + } + this._sourcesContents[util$2.toSetString(source)] = aSourceContent; + } else if (this._sourcesContents) { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util$2.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + * @param aSourceMapPath Optional. The dirname of the path to the source map + * to be applied. If relative, it is relative to the SourceMapConsumer. + * This parameter is needed when the two source maps aren't in the same + * directory, and the source map to be applied contains relative source + * paths. If so, those relative source paths need to be rewritten + * relative to the SourceMapGenerator. + */ + SourceMapGenerator$4.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { + var sourceFile = aSourceFile; + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (aSourceFile == null) { + if (aSourceMapConsumer.file == null) { + throw new Error( + 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + + 'or the source map\'s "file" property. Both were omitted.' + ); + } + sourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "sourceFile" relative if an absolute Url is passed. + if (sourceRoot != null) { + sourceFile = util$2.relative(sourceRoot, sourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet$1(); + var newNames = new ArraySet$1(); + + // Find mappings for the "sourceFile" + this._mappings.unsortedForEach(function (mapping) { + if (mapping.source === sourceFile && mapping.originalLine != null) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source != null) { + // Copy mapping + mapping.source = original.source; + if (aSourceMapPath != null) { + mapping.source = util$2.join(aSourceMapPath, mapping.source); + } + if (sourceRoot != null) { + mapping.source = util$2.relative(sourceRoot, mapping.source); + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name != null) { + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source != null && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name != null && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aSourceMapPath != null) { + sourceFile = util$2.join(aSourceMapPath, sourceFile); + } + if (sourceRoot != null) { + sourceFile = util$2.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator$4.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + // When aOriginal is truthy but has empty values for .line and .column, + // it is most likely a programmer error. In this case we throw a very + // specific error message to try to guide them the right way. + // For example: https://github.com/Polymer/polymer-bundler/pull/519 + if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') { + var message = 'original.line and original.column are not numbers -- you probably meant to omit ' + + 'the original mapping entirely and only map the generated position. If so, pass ' + + 'null for the original mapping instead of an object with empty or null values.'; + + if (this._ignoreInvalidMapping) { + if (typeof console !== 'undefined' && console.warn) { + console.warn(message); + } + return false; + } else { + throw new Error(message); + } + } + + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + var message = 'Invalid mapping: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + original: aOriginal, + name: aName + }); + + if (this._ignoreInvalidMapping) { + if (typeof console !== 'undefined' && console.warn) { + console.warn(message); + } + return false; + } else { + throw new Error(message) + } + } + }; + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator$4.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var next; + var mapping; + var nameIdx; + var sourceIdx; + + var mappings = this._mappings.toArray(); + for (var i = 0, len = mappings.length; i < len; i++) { + mapping = mappings[i]; + next = ''; + + if (mapping.generatedLine !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generatedLine !== previousGeneratedLine) { + next += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!util$2.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) { + continue; + } + next += ','; + } + } + + next += base64VLQ$1.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; + + if (mapping.source != null) { + sourceIdx = this._sources.indexOf(mapping.source); + next += base64VLQ$1.encode(sourceIdx - previousSource); + previousSource = sourceIdx; + + // lines are stored 0-based in SourceMap spec version 3 + next += base64VLQ$1.encode(mapping.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; + + next += base64VLQ$1.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; + + if (mapping.name != null) { + nameIdx = this._names.indexOf(mapping.name); + next += base64VLQ$1.encode(nameIdx - previousName); + previousName = nameIdx; + } + } + + result += next; + } + + return result; + }; + + SourceMapGenerator$4.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; + } + if (aSourceRoot != null) { + source = util$2.relative(aSourceRoot, source); + } + var key = util$2.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) + ? this._sourcesContents[key] + : null; + }, this); + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator$4.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._file != null) { + map.file = this._file; + } + if (this._sourceRoot != null) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + } + + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator$4.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this.toJSON()); + }; + + sourceMapGenerator.SourceMapGenerator = SourceMapGenerator$4; + + var sourceMapConsumer = {}; + + var binarySearch$1 = {}; + + /* -*- Mode: js; js-indent-level: 2; -*- */ + + (function (exports) { + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + exports.GREATEST_LOWER_BOUND = 1; + exports.LEAST_UPPER_BOUND = 2; + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the index of + // the next-closest element. + // + // 3. We did not find the exact element, and there is no next-closest + // element than the one we are searching for, so we return -1. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return mid; + } + else if (cmp > 0) { + // Our needle is greater than aHaystack[mid]. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias); + } + + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return aHigh < aHaystack.length ? aHigh : -1; + } else { + return mid; + } + } + else { + // Our needle is less than aHaystack[mid]. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias); + } + + // we are in termination case (3) or (2) and return the appropriate thing. + if (aBias == exports.LEAST_UPPER_BOUND) { + return mid; + } else { + return aLow < 0 ? -1 : aLow; + } + } + } + + /** + * This is an implementation of binary search which will always try and return + * the index of the closest element if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + * @param aBias Either 'binarySearch.GREATEST_LOWER_BOUND' or + * 'binarySearch.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'binarySearch.GREATEST_LOWER_BOUND'. + */ + exports.search = function search(aNeedle, aHaystack, aCompare, aBias) { + if (aHaystack.length === 0) { + return -1; + } + + var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, + aCompare, aBias || exports.GREATEST_LOWER_BOUND); + if (index < 0) { + return -1; + } + + // We have found either the exact element, or the next-closest element than + // the one we are searching for. However, there may be more than one such + // element. Make sure we always return the smallest of these. + while (index - 1 >= 0) { + if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) { + break; + } + --index; + } + + return index; + }; + } (binarySearch$1)); + + var quickSort$1 = {}; + + /* -*- Mode: js; js-indent-level: 2; -*- */ + + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + // It turns out that some (most?) JavaScript engines don't self-host + // `Array.prototype.sort`. This makes sense because C++ will likely remain + // faster than JS when doing raw CPU-intensive sorting. However, when using a + // custom comparator function, calling back and forth between the VM's C++ and + // JIT'd JS is rather slow *and* loses JIT type information, resulting in + // worse generated code for the comparator function than would be optimal. In + // fact, when sorting with a comparator, these costs outweigh the benefits of + // sorting in C++. By using our own JS-implemented Quick Sort (below), we get + // a ~3500ms mean speed-up in `bench/bench.html`. + + function SortTemplate(comparator) { + + /** + * Swap the elements indexed by `x` and `y` in the array `ary`. + * + * @param {Array} ary + * The array. + * @param {Number} x + * The index of the first item. + * @param {Number} y + * The index of the second item. + */ + function swap(ary, x, y) { + var temp = ary[x]; + ary[x] = ary[y]; + ary[y] = temp; + } + + /** + * Returns a random integer within the range `low .. high` inclusive. + * + * @param {Number} low + * The lower bound on the range. + * @param {Number} high + * The upper bound on the range. + */ + function randomIntInRange(low, high) { + return Math.round(low + (Math.random() * (high - low))); + } + + /** + * The Quick Sort algorithm. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + * @param {Number} p + * Start index of the array + * @param {Number} r + * End index of the array + */ + function doQuickSort(ary, comparator, p, r) { + // If our lower bound is less than our upper bound, we (1) partition the + // array into two pieces and (2) recurse on each half. If it is not, this is + // the empty array and our base case. + + if (p < r) { + // (1) Partitioning. + // + // The partitioning chooses a pivot between `p` and `r` and moves all + // elements that are less than or equal to the pivot to the before it, and + // all the elements that are greater than it after it. The effect is that + // once partition is done, the pivot is in the exact place it will be when + // the array is put in sorted order, and it will not need to be moved + // again. This runs in O(n) time. + + // Always choose a random pivot so that an input array which is reverse + // sorted does not cause O(n^2) running time. + var pivotIndex = randomIntInRange(p, r); + var i = p - 1; + + swap(ary, pivotIndex, r); + var pivot = ary[r]; + + // Immediately after `j` is incremented in this loop, the following hold + // true: + // + // * Every element in `ary[p .. i]` is less than or equal to the pivot. + // + // * Every element in `ary[i+1 .. j-1]` is greater than the pivot. + for (var j = p; j < r; j++) { + if (comparator(ary[j], pivot, false) <= 0) { + i += 1; + swap(ary, i, j); + } + } + + swap(ary, i + 1, j); + var q = i + 1; + + // (2) Recurse on each half. + + doQuickSort(ary, comparator, p, q - 1); + doQuickSort(ary, comparator, q + 1, r); + } + } + + return doQuickSort; + } + + function cloneSort(comparator) { + let template = SortTemplate.toString(); + let templateFn = new Function(`return ${template}`)(); + return templateFn(comparator); + } + + /** + * Sort the given array in-place with the given comparator function. + * + * @param {Array} ary + * An array to sort. + * @param {function} comparator + * Function to use to compare two items. + */ + + let sortCache = new WeakMap(); + quickSort$1.quickSort = function (ary, comparator, start = 0) { + let doQuickSort = sortCache.get(comparator); + if (doQuickSort === void 0) { + doQuickSort = cloneSort(comparator); + sortCache.set(comparator, doQuickSort); + } + doQuickSort(ary, comparator, start, ary.length - 1); + }; + + /* -*- Mode: js; js-indent-level: 2; -*- */ + + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var util$1 = util$5; + var binarySearch = binarySearch$1; + var ArraySet = arraySet.ArraySet; + var base64VLQ = base64Vlq; + var quickSort = quickSort$1.quickSort; + + function SourceMapConsumer$3(aSourceMap, aSourceMapURL) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = util$1.parseSourceMapInput(aSourceMap); + } + + return sourceMap.sections != null + ? new IndexedSourceMapConsumer(sourceMap, aSourceMapURL) + : new BasicSourceMapConsumer(sourceMap, aSourceMapURL); + } + + SourceMapConsumer$3.fromSourceMap = function(aSourceMap, aSourceMapURL) { + return BasicSourceMapConsumer.fromSourceMap(aSourceMap, aSourceMapURL); + }; + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer$3.prototype._version = 3; + + // `__generatedMappings` and `__originalMappings` are arrays that hold the + // parsed mapping coordinates from the source map's "mappings" attribute. They + // are lazily instantiated, accessed via the `_generatedMappings` and + // `_originalMappings` getters respectively, and we only parse the mappings + // and create these arrays once queried for a source location. We jump through + // these hoops because there can be many thousands of mappings, and parsing + // them is expensive, so we only want to do it if we must. + // + // Each object in the arrays is of the form: + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `_generatedMappings` is ordered by the generated positions. + // + // `_originalMappings` is ordered by the original positions. + + SourceMapConsumer$3.prototype.__generatedMappings = null; + Object.defineProperty(SourceMapConsumer$3.prototype, '_generatedMappings', { + configurable: true, + enumerable: true, + get: function () { + if (!this.__generatedMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__generatedMappings; + } + }); + + SourceMapConsumer$3.prototype.__originalMappings = null; + Object.defineProperty(SourceMapConsumer$3.prototype, '_originalMappings', { + configurable: true, + enumerable: true, + get: function () { + if (!this.__originalMappings) { + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; + } + }); + + SourceMapConsumer$3.prototype._charIsMappingSeparator = + function SourceMapConsumer_charIsMappingSeparator(aStr, index) { + var c = aStr.charAt(index); + return c === ";" || c === ","; + }; + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + SourceMapConsumer$3.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + throw new Error("Subclasses must implement _parseMappings"); + }; + + SourceMapConsumer$3.GENERATED_ORDER = 1; + SourceMapConsumer$3.ORIGINAL_ORDER = 2; + + SourceMapConsumer$3.GREATEST_LOWER_BOUND = 1; + SourceMapConsumer$3.LEAST_UPPER_BOUND = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer$3.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer$3.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer$3.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer$3.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + var boundCallback = aCallback.bind(context); + var names = this._names; + var sources = this._sources; + var sourceMapURL = this._sourceMapURL; + + for (var i = 0, n = mappings.length; i < n; i++) { + var mapping = mappings[i]; + var source = mapping.source === null ? null : sources.at(mapping.source); + source = util$1.computeSourceURL(sourceRoot, source, sourceMapURL); + boundCallback({ + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name === null ? null : names.at(mapping.name) + }); + } + }; + + /** + * Returns all generated line and column information for the original source, + * line, and column provided. If no column is provided, returns all mappings + * corresponding to a either the line we are searching for or the next + * closest line that has any mappings. Otherwise, returns all mappings + * corresponding to the given line and either the column we are searching for + * or the next closest column that has any offsets. + * + * The only argument is an object with the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. The line number is 1-based. + * - column: Optional. the column number in the original source. + * The column number is 0-based. + * + * and an array of objects is returned, each with the following properties: + * + * - line: The line number in the generated source, or null. The + * line number is 1-based. + * - column: The column number in the generated source, or null. + * The column number is 0-based. + */ + SourceMapConsumer$3.prototype.allGeneratedPositionsFor = + function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { + var line = util$1.getArg(aArgs, 'line'); + + // When there is no exact match, BasicSourceMapConsumer.prototype._findMapping + // returns the index of the closest mapping less than the needle. By + // setting needle.originalColumn to 0, we thus find the last mapping for + // the given line, provided such a mapping exists. + var needle = { + source: util$1.getArg(aArgs, 'source'), + originalLine: line, + originalColumn: util$1.getArg(aArgs, 'column', 0) + }; + + needle.source = this._findSourceIndex(needle.source); + if (needle.source < 0) { + return []; + } + + var mappings = []; + + var index = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util$1.compareByOriginalPositions, + binarySearch.LEAST_UPPER_BOUND); + if (index >= 0) { + var mapping = this._originalMappings[index]; + + if (aArgs.column === undefined) { + var originalLine = mapping.originalLine; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we found. Since + // mappings are sorted, this is guaranteed to find all mappings for + // the line we found. + while (mapping && mapping.originalLine === originalLine) { + mappings.push({ + line: util$1.getArg(mapping, 'generatedLine', null), + column: util$1.getArg(mapping, 'generatedColumn', null), + lastColumn: util$1.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[++index]; + } + } else { + var originalColumn = mapping.originalColumn; + + // Iterate until either we run out of mappings, or we run into + // a mapping for a different line than the one we were searching for. + // Since mappings are sorted, this is guaranteed to find all mappings for + // the line we are searching for. + while (mapping && + mapping.originalLine === line && + mapping.originalColumn == originalColumn) { + mappings.push({ + line: util$1.getArg(mapping, 'generatedLine', null), + column: util$1.getArg(mapping, 'generatedColumn', null), + lastColumn: util$1.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[++index]; + } + } + } + + return mappings; + }; + + sourceMapConsumer.SourceMapConsumer = SourceMapConsumer$3; + + /** + * A BasicSourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The first parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: Optional. The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * The second parameter, if given, is a string whose value is the URL + * at which the source map was found. This URL is used to compute the + * sources array. + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function BasicSourceMapConsumer(aSourceMap, aSourceMapURL) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = util$1.parseSourceMapInput(aSourceMap); + } + + var version = util$1.getArg(sourceMap, 'version'); + var sources = util$1.getArg(sourceMap, 'sources'); + // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which + // requires the array) to play nice here. + var names = util$1.getArg(sourceMap, 'names', []); + var sourceRoot = util$1.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util$1.getArg(sourceMap, 'sourcesContent', null); + var mappings = util$1.getArg(sourceMap, 'mappings'); + var file = util$1.getArg(sourceMap, 'file', null); + + // Once again, Sass deviates from the spec and supplies the version as a + // string rather than a number, so we use loose equality checking here. + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + if (sourceRoot) { + sourceRoot = util$1.normalize(sourceRoot); + } + + sources = sources + .map(String) + // Some source maps produce relative source paths like "./foo.js" instead of + // "foo.js". Normalize these first so that future comparisons will succeed. + // See bugzil.la/1090768. + .map(util$1.normalize) + // Always ensure that absolute sources are internally stored relative to + // the source root, if the source root is absolute. Not doing this would + // be particularly problematic when the source root is a prefix of the + // source (valid, but why??). See github issue #199 and bugzil.la/1188982. + .map(function (source) { + return sourceRoot && util$1.isAbsolute(sourceRoot) && util$1.isAbsolute(source) + ? util$1.relative(sourceRoot, source) + : source; + }); + + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names.map(String), true); + this._sources = ArraySet.fromArray(sources, true); + + this._absoluteSources = this._sources.toArray().map(function (s) { + return util$1.computeSourceURL(sourceRoot, s, aSourceMapURL); + }); + + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this._mappings = mappings; + this._sourceMapURL = aSourceMapURL; + this.file = file; + } + + BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer$3.prototype); + BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer$3; + + /** + * Utility function to find the index of a source. Returns -1 if not + * found. + */ + BasicSourceMapConsumer.prototype._findSourceIndex = function(aSource) { + var relativeSource = aSource; + if (this.sourceRoot != null) { + relativeSource = util$1.relative(this.sourceRoot, relativeSource); + } + + if (this._sources.has(relativeSource)) { + return this._sources.indexOf(relativeSource); + } + + // Maybe aSource is an absolute URL as returned by |sources|. In + // this case we can't simply undo the transform. + var i; + for (i = 0; i < this._absoluteSources.length; ++i) { + if (this._absoluteSources[i] == aSource) { + return i; + } + } + + return -1; + }; + + /** + * Create a BasicSourceMapConsumer from a SourceMapGenerator. + * + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @param String aSourceMapURL + * The URL at which the source map can be found (optional) + * @returns BasicSourceMapConsumer + */ + BasicSourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap, aSourceMapURL) { + var smc = Object.create(BasicSourceMapConsumer.prototype); + + var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + smc._sourceMapURL = aSourceMapURL; + smc._absoluteSources = smc._sources.toArray().map(function (s) { + return util$1.computeSourceURL(smc.sourceRoot, s, aSourceMapURL); + }); + + // Because we are modifying the entries (by converting string sources and + // names to indices into the sources and names ArraySets), we have to make + // a copy of the entry or else bad things happen. Shared mutable state + // strikes again! See github issue #191. + + var generatedMappings = aSourceMap._mappings.toArray().slice(); + var destGeneratedMappings = smc.__generatedMappings = []; + var destOriginalMappings = smc.__originalMappings = []; + + for (var i = 0, length = generatedMappings.length; i < length; i++) { + var srcMapping = generatedMappings[i]; + var destMapping = new Mapping; + destMapping.generatedLine = srcMapping.generatedLine; + destMapping.generatedColumn = srcMapping.generatedColumn; + + if (srcMapping.source) { + destMapping.source = sources.indexOf(srcMapping.source); + destMapping.originalLine = srcMapping.originalLine; + destMapping.originalColumn = srcMapping.originalColumn; + + if (srcMapping.name) { + destMapping.name = names.indexOf(srcMapping.name); + } + + destOriginalMappings.push(destMapping); + } + + destGeneratedMappings.push(destMapping); + } + + quickSort(smc.__originalMappings, util$1.compareByOriginalPositions); + + return smc; + }; + + /** + * The version of the source mapping spec that we are consuming. + */ + BasicSourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', { + get: function () { + return this._absoluteSources.slice(); + } + }); + + /** + * Provide the JIT with a nice shape / hidden class. + */ + function Mapping() { + this.generatedLine = 0; + this.generatedColumn = 0; + this.source = null; + this.originalLine = null; + this.originalColumn = null; + this.name = null; + } + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + + const compareGenerated = util$1.compareByGeneratedPositionsDeflatedNoLine; + function sortGenerated(array, start) { + let l = array.length; + let n = array.length - start; + if (n <= 1) { + return; + } else if (n == 2) { + let a = array[start]; + let b = array[start + 1]; + if (compareGenerated(a, b) > 0) { + array[start] = b; + array[start + 1] = a; + } + } else if (n < 20) { + for (let i = start; i < l; i++) { + for (let j = i; j > start; j--) { + let a = array[j - 1]; + let b = array[j]; + if (compareGenerated(a, b) <= 0) { + break; + } + array[j - 1] = b; + array[j] = a; + } + } + } else { + quickSort(array, compareGenerated, start); + } + } + BasicSourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var length = aStr.length; + var index = 0; + var temp = {}; + var originalMappings = []; + var generatedMappings = []; + var mapping, segment, end, value; + + let subarrayStart = 0; + while (index < length) { + if (aStr.charAt(index) === ';') { + generatedLine++; + index++; + previousGeneratedColumn = 0; + + sortGenerated(generatedMappings, subarrayStart); + subarrayStart = generatedMappings.length; + } + else if (aStr.charAt(index) === ',') { + index++; + } + else { + mapping = new Mapping(); + mapping.generatedLine = generatedLine; + + for (end = index; end < length; end++) { + if (this._charIsMappingSeparator(aStr, end)) { + break; + } + } + aStr.slice(index, end); + + segment = []; + while (index < end) { + base64VLQ.decode(aStr, index, temp); + value = temp.value; + index = temp.rest; + segment.push(value); + } + + if (segment.length === 2) { + throw new Error('Found a source, but no line and column'); + } + + if (segment.length === 3) { + throw new Error('Found a source and line, but no column'); + } + + // Generated column. + mapping.generatedColumn = previousGeneratedColumn + segment[0]; + previousGeneratedColumn = mapping.generatedColumn; + + if (segment.length > 1) { + // Original source. + mapping.source = previousSource + segment[1]; + previousSource += segment[1]; + + // Original line. + mapping.originalLine = previousOriginalLine + segment[2]; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + + // Original column. + mapping.originalColumn = previousOriginalColumn + segment[3]; + previousOriginalColumn = mapping.originalColumn; + + if (segment.length > 4) { + // Original name. + mapping.name = previousName + segment[4]; + previousName += segment[4]; + } + } + + generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + let currentSource = mapping.source; + while (originalMappings.length <= currentSource) { + originalMappings.push(null); + } + if (originalMappings[currentSource] === null) { + originalMappings[currentSource] = []; + } + originalMappings[currentSource].push(mapping); + } + } + } + + sortGenerated(generatedMappings, subarrayStart); + this.__generatedMappings = generatedMappings; + + for (var i = 0; i < originalMappings.length; i++) { + if (originalMappings[i] != null) { + quickSort(originalMappings[i], util$1.compareByOriginalPositionsNoSource); + } + } + this.__originalMappings = [].concat(...originalMappings); + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + BasicSourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator, aBias) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator, aBias); + }; + + /** + * Compute the last column for each generated mapping. The last column is + * inclusive. + */ + BasicSourceMapConsumer.prototype.computeColumnSpans = + function SourceMapConsumer_computeColumnSpans() { + for (var index = 0; index < this._generatedMappings.length; ++index) { + var mapping = this._generatedMappings[index]; + + // Mappings do not contain a field for the last generated columnt. We + // can come up with an optimistic estimate, however, by assuming that + // mappings are contiguous (i.e. given two consecutive mappings, the + // first mapping ends where the second one starts). + if (index + 1 < this._generatedMappings.length) { + var nextMapping = this._generatedMappings[index + 1]; + + if (mapping.generatedLine === nextMapping.generatedLine) { + mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; + continue; + } + } + + // The last mapping for each line spans the entire line. + mapping.lastGeneratedColumn = Infinity; + } + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. The line number + * is 1-based. + * - column: The column number in the generated source. The column + * number is 0-based. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. The + * line number is 1-based. + * - column: The column number in the original source, or null. The + * column number is 0-based. + * - name: The original identifier, or null. + */ + BasicSourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util$1.getArg(aArgs, 'line'), + generatedColumn: util$1.getArg(aArgs, 'column') + }; + + var index = this._findMapping( + needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util$1.compareByGeneratedPositionsDeflated, + util$1.getArg(aArgs, 'bias', SourceMapConsumer$3.GREATEST_LOWER_BOUND) + ); + + if (index >= 0) { + var mapping = this._generatedMappings[index]; + + if (mapping.generatedLine === needle.generatedLine) { + var source = util$1.getArg(mapping, 'source', null); + if (source !== null) { + source = this._sources.at(source); + source = util$1.computeSourceURL(this.sourceRoot, source, this._sourceMapURL); + } + var name = util$1.getArg(mapping, 'name', null); + if (name !== null) { + name = this._names.at(name); + } + return { + source: source, + line: util$1.getArg(mapping, 'originalLine', null), + column: util$1.getArg(mapping, 'originalColumn', null), + name: name + }; + } + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ + BasicSourceMapConsumer.prototype.hasContentsOfAllSources = + function BasicSourceMapConsumer_hasContentsOfAllSources() { + if (!this.sourcesContent) { + return false; + } + return this.sourcesContent.length >= this._sources.size() && + !this.sourcesContent.some(function (sc) { return sc == null; }); + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * available. + */ + BasicSourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + if (!this.sourcesContent) { + return null; + } + + var index = this._findSourceIndex(aSource); + if (index >= 0) { + return this.sourcesContent[index]; + } + + var relativeSource = aSource; + if (this.sourceRoot != null) { + relativeSource = util$1.relative(this.sourceRoot, relativeSource); + } + + var url; + if (this.sourceRoot != null + && (url = util$1.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = relativeSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + relativeSource)) { + return this.sourcesContent[this._sources.indexOf("/" + relativeSource)]; + } + } + + // This function is used recursively from + // IndexedSourceMapConsumer.prototype.sourceContentFor. In that case, we + // don't want to throw if we can't find the source - we just want to + // return null, so we provide a flag to exit gracefully. + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + relativeSource + '" is not in the SourceMap.'); + } + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. The line number + * is 1-based. + * - column: The column number in the original source. The column + * number is 0-based. + * - bias: Either 'SourceMapConsumer.GREATEST_LOWER_BOUND' or + * 'SourceMapConsumer.LEAST_UPPER_BOUND'. Specifies whether to return the + * closest element that is smaller than or greater than the one we are + * searching for, respectively, if the exact element cannot be found. + * Defaults to 'SourceMapConsumer.GREATEST_LOWER_BOUND'. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. The + * line number is 1-based. + * - column: The column number in the generated source, or null. + * The column number is 0-based. + */ + BasicSourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var source = util$1.getArg(aArgs, 'source'); + source = this._findSourceIndex(source); + if (source < 0) { + return { + line: null, + column: null, + lastColumn: null + }; + } + + var needle = { + source: source, + originalLine: util$1.getArg(aArgs, 'line'), + originalColumn: util$1.getArg(aArgs, 'column') + }; + + var index = this._findMapping( + needle, + this._originalMappings, + "originalLine", + "originalColumn", + util$1.compareByOriginalPositions, + util$1.getArg(aArgs, 'bias', SourceMapConsumer$3.GREATEST_LOWER_BOUND) + ); + + if (index >= 0) { + var mapping = this._originalMappings[index]; + + if (mapping.source === needle.source) { + return { + line: util$1.getArg(mapping, 'generatedLine', null), + column: util$1.getArg(mapping, 'generatedColumn', null), + lastColumn: util$1.getArg(mapping, 'lastGeneratedColumn', null) + }; + } + } + + return { + line: null, + column: null, + lastColumn: null + }; + }; + + sourceMapConsumer.BasicSourceMapConsumer = BasicSourceMapConsumer; + + /** + * An IndexedSourceMapConsumer instance represents a parsed source map which + * we can query for information. It differs from BasicSourceMapConsumer in + * that it takes "indexed" source maps (i.e. ones with a "sections" field) as + * input. + * + * The first parameter is a raw source map (either as a JSON string, or already + * parsed to an object). According to the spec for indexed source maps, they + * have the following attributes: + * + * - version: Which version of the source map spec this map is following. + * - file: Optional. The generated file this source map is associated with. + * - sections: A list of section definitions. + * + * Each value under the "sections" field has two fields: + * - offset: The offset into the original specified at which this section + * begins to apply, defined as an object with a "line" and "column" + * field. + * - map: A source map definition. This source map could also be indexed, + * but doesn't have to be. + * + * Instead of the "map" field, it's also possible to have a "url" field + * specifying a URL to retrieve a source map from, but that's currently + * unsupported. + * + * Here's an example source map, taken from the source map spec[0], but + * modified to omit a section which uses the "url" field. + * + * { + * version : 3, + * file: "app.js", + * sections: [{ + * offset: {line:100, column:10}, + * map: { + * version : 3, + * file: "section.js", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AAAA,E;;ABCDE;" + * } + * }], + * } + * + * The second parameter, if given, is a string whose value is the URL + * at which the source map was found. This URL is used to compute the + * sources array. + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit#heading=h.535es3xeprgt + */ + function IndexedSourceMapConsumer(aSourceMap, aSourceMapURL) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = util$1.parseSourceMapInput(aSourceMap); + } + + var version = util$1.getArg(sourceMap, 'version'); + var sections = util$1.getArg(sourceMap, 'sections'); + + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + this._sources = new ArraySet(); + this._names = new ArraySet(); + + var lastOffset = { + line: -1, + column: 0 + }; + this._sections = sections.map(function (s) { + if (s.url) { + // The url field will require support for asynchronicity. + // See https://github.com/mozilla/source-map/issues/16 + throw new Error('Support for url field in sections not implemented.'); + } + var offset = util$1.getArg(s, 'offset'); + var offsetLine = util$1.getArg(offset, 'line'); + var offsetColumn = util$1.getArg(offset, 'column'); + + if (offsetLine < lastOffset.line || + (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) { + throw new Error('Section offsets must be ordered and non-overlapping.'); + } + lastOffset = offset; + + return { + generatedOffset: { + // The offset fields are 0-based, but we use 1-based indices when + // encoding/decoding from VLQ. + generatedLine: offsetLine + 1, + generatedColumn: offsetColumn + 1 + }, + consumer: new SourceMapConsumer$3(util$1.getArg(s, 'map'), aSourceMapURL) + } + }); + } + + IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer$3.prototype); + IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer$3; + + /** + * The version of the source mapping spec that we are consuming. + */ + IndexedSourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', { + get: function () { + var sources = []; + for (var i = 0; i < this._sections.length; i++) { + for (var j = 0; j < this._sections[i].consumer.sources.length; j++) { + sources.push(this._sections[i].consumer.sources[j]); + } + } + return sources; + } + }); + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. The line number + * is 1-based. + * - column: The column number in the generated source. The column + * number is 0-based. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. The + * line number is 1-based. + * - column: The column number in the original source, or null. The + * column number is 0-based. + * - name: The original identifier, or null. + */ + IndexedSourceMapConsumer.prototype.originalPositionFor = + function IndexedSourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util$1.getArg(aArgs, 'line'), + generatedColumn: util$1.getArg(aArgs, 'column') + }; + + // Find the section containing the generated position we're trying to map + // to an original position. + var sectionIndex = binarySearch.search(needle, this._sections, + function(needle, section) { + var cmp = needle.generatedLine - section.generatedOffset.generatedLine; + if (cmp) { + return cmp; + } + + return (needle.generatedColumn - + section.generatedOffset.generatedColumn); + }); + var section = this._sections[sectionIndex]; + + if (!section) { + return { + source: null, + line: null, + column: null, + name: null + }; + } + + return section.consumer.originalPositionFor({ + line: needle.generatedLine - + (section.generatedOffset.generatedLine - 1), + column: needle.generatedColumn - + (section.generatedOffset.generatedLine === needle.generatedLine + ? section.generatedOffset.generatedColumn - 1 + : 0), + bias: aArgs.bias + }); + }; + + /** + * Return true if we have the source content for every source in the source + * map, false otherwise. + */ + IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = + function IndexedSourceMapConsumer_hasContentsOfAllSources() { + return this._sections.every(function (s) { + return s.consumer.hasContentsOfAllSources(); + }); + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * available. + */ + IndexedSourceMapConsumer.prototype.sourceContentFor = + function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + + var content = section.consumer.sourceContentFor(aSource, true); + if (content || content === '') { + return content; + } + } + if (nullOnMissing) { + return null; + } + else { + throw new Error('"' + aSource + '" is not in the SourceMap.'); + } + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. The line number + * is 1-based. + * - column: The column number in the original source. The column + * number is 0-based. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. The + * line number is 1-based. + * - column: The column number in the generated source, or null. + * The column number is 0-based. + */ + IndexedSourceMapConsumer.prototype.generatedPositionFor = + function IndexedSourceMapConsumer_generatedPositionFor(aArgs) { + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + + // Only consider this section if the requested source is in the list of + // sources of the consumer. + if (section.consumer._findSourceIndex(util$1.getArg(aArgs, 'source')) === -1) { + continue; + } + var generatedPosition = section.consumer.generatedPositionFor(aArgs); + if (generatedPosition) { + var ret = { + line: generatedPosition.line + + (section.generatedOffset.generatedLine - 1), + column: generatedPosition.column + + (section.generatedOffset.generatedLine === generatedPosition.line + ? section.generatedOffset.generatedColumn - 1 + : 0) + }; + return ret; + } + } + + return { + line: null, + column: null + }; + }; + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + IndexedSourceMapConsumer.prototype._parseMappings = + function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) { + this.__generatedMappings = []; + this.__originalMappings = []; + for (var i = 0; i < this._sections.length; i++) { + var section = this._sections[i]; + var sectionMappings = section.consumer._generatedMappings; + for (var j = 0; j < sectionMappings.length; j++) { + var mapping = sectionMappings[j]; + + var source = section.consumer._sources.at(mapping.source); + source = util$1.computeSourceURL(section.consumer.sourceRoot, source, this._sourceMapURL); + this._sources.add(source); + source = this._sources.indexOf(source); + + var name = null; + if (mapping.name) { + name = section.consumer._names.at(mapping.name); + this._names.add(name); + name = this._names.indexOf(name); + } + + // The mappings coming from the consumer for the section have + // generated positions relative to the start of the section, so we + // need to offset them to be relative to the start of the concatenated + // generated file. + var adjustedMapping = { + source: source, + generatedLine: mapping.generatedLine + + (section.generatedOffset.generatedLine - 1), + generatedColumn: mapping.generatedColumn + + (section.generatedOffset.generatedLine === mapping.generatedLine + ? section.generatedOffset.generatedColumn - 1 + : 0), + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: name + }; + + this.__generatedMappings.push(adjustedMapping); + if (typeof adjustedMapping.originalLine === 'number') { + this.__originalMappings.push(adjustedMapping); + } + } + } + + quickSort(this.__generatedMappings, util$1.compareByGeneratedPositionsDeflated); + quickSort(this.__originalMappings, util$1.compareByOriginalPositions); + }; + + sourceMapConsumer.IndexedSourceMapConsumer = IndexedSourceMapConsumer; + + var sourceNode = {}; + + /* -*- Mode: js; js-indent-level: 2; -*- */ + + /* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + var SourceMapGenerator$3 = sourceMapGenerator.SourceMapGenerator; + var util = util$5; + + // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other + // operating systems these days (capturing the result). + var REGEX_NEWLINE = /(\r?\n)/; + + // Newline character code for charCodeAt() comparisons + var NEWLINE_CODE = 10; + + // Private symbol for identifying `SourceNode`s when multiple versions of + // the source-map library are loaded. This MUST NOT CHANGE across + // versions! + var isSourceNode = "$$$isSourceNode$$$"; + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine == null ? null : aLine; + this.column = aColumn == null ? null : aColumn; + this.source = aSource == null ? null : aSource; + this.name = aName == null ? null : aName; + this[isSourceNode] = true; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + * @param aRelativePath Optional. The path that relative sources in the + * SourceMapConsumer should be relative to. + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // All even indices of this array are one line of the generated code, + // while all odd indices are the newlines between two adjacent lines + // (since `REGEX_NEWLINE` captures its match). + // Processed fragments are accessed by calling `shiftNextLine`. + var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); + var remainingLinesIndex = 0; + var shiftNextLine = function() { + var lineContents = getNextLine(); + // The last line of a file might not have a newline. + var newLine = getNextLine() || ""; + return lineContents + newLine; + + function getNextLine() { + return remainingLinesIndex < remainingLines.length ? + remainingLines[remainingLinesIndex++] : undefined; + } + }; + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping !== null) { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + // Associate first line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + lastGeneratedLine++; + lastGeneratedColumn = 0; + // The remaining code is added without mapping + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[remainingLinesIndex] || ''; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + // No more remaining code, continue + lastMapping = mapping; + return; + } + } + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(shiftNextLine()); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[remainingLinesIndex] || ''; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + if (remainingLinesIndex < remainingLines.length) { + if (lastMapping) { + // Associate the remaining code in the current line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + } + // and add the remaining lines without any mapping + node.add(remainingLines.splice(remainingLinesIndex).join("")); + } + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aRelativePath != null) { + sourceFile = util.join(aRelativePath, sourceFile); + } + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + var source = aRelativePath + ? util.join(aRelativePath, mapping.source) + : mapping.source; + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk[isSourceNode]) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + } + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild[isSourceNode]) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i][isSourceNode]) { + this.children[i].walkSourceContents(aFn); + } + } + + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + } + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator$3(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if(lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; + } + for (var idx = 0, length = chunk.length; idx < length; idx++) { + if (chunk.charCodeAt(idx) === NEWLINE_CODE) { + generated.line++; + generated.column = 0; + // Mappings end at eol + if (idx + 1 === length) { + lastOriginalSource = null; + sourceMappingActive = false; + } else if (sourceMappingActive) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + } else { + generated.column++; + } + } + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + sourceNode.SourceNode = SourceNode; + + /* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ + + sourceMap.SourceMapGenerator = sourceMapGenerator.SourceMapGenerator; + sourceMap.SourceMapConsumer = sourceMapConsumer.SourceMapConsumer; + sourceMap.SourceNode = sourceNode.SourceNode; + + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + // resolves . and .. elements in a path array with directory names there + // must be no slashes, empty elements, or device names (c:\) in the array + // (so also no leading and trailing slashes - it does not distinguish + // relative and absolute paths) + function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; + } + + // Split a filename into [root, dir, basename, ext], unix version + // 'root' is just a slash, or nothing. + var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; + var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); + }; + + // path.resolve([from ...], to) + // posix version + function resolve$2() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : '/'; + + // Skip empty and invalid entries + if (typeof path !== 'string') { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(filter$1(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; + } + // path.normalize(path) + // posix version + function normalize$1(path) { + var isPathAbsolute = isAbsolute$1(path), + trailingSlash = substr(path, -1) === '/'; + + // Normalize the path + path = normalizeArray(filter$1(path.split('/'), function(p) { + return !!p; + }), !isPathAbsolute).join('/'); + + if (!path && !isPathAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isPathAbsolute ? '/' : '') + path; + } + // posix version + function isAbsolute$1(path) { + return path.charAt(0) === '/'; + } + + // posix version + function join$1() { + var paths = Array.prototype.slice.call(arguments, 0); + return normalize$1(filter$1(paths, function(p, index) { + if (typeof p !== 'string') { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + }).join('/')); + } + + + // path.relative(from, to) + // posix version + function relative$1(from, to) { + from = resolve$2(from).substr(1); + to = resolve$2(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); + } + + var sep$1 = '/'; + var delimiter$1 = ':'; + + function dirname$2(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; + } + + function basename(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; + } + + + function extname(path) { + return splitPath(path)[3]; + } + var _polyfillNode_path = { + extname: extname, + basename: basename, + dirname: dirname$2, + sep: sep$1, + delimiter: delimiter$1, + relative: relative$1, + join: join$1, + isAbsolute: isAbsolute$1, + normalize: normalize$1, + resolve: resolve$2 + }; + function filter$1 (xs, f) { + if (xs.filter) return xs.filter(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (f(xs[i], i, xs)) res.push(xs[i]); + } + return res; + } + + // String.prototype.substr - negative index don't work in IE8 + var substr = 'ab'.substr(-1) === 'b' ? + function (str, start, len) { return str.substr(start, len) } : + function (str, start, len) { + if (start < 0) start = str.length + start; + return str.substr(start, len); + } + ; + + var _polyfillNode_path$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + basename: basename, + default: _polyfillNode_path, + delimiter: delimiter$1, + dirname: dirname$2, + extname: extname, + isAbsolute: isAbsolute$1, + join: join$1, + normalize: normalize$1, + relative: relative$1, + resolve: resolve$2, + sep: sep$1 + }); + + var require$$1$1 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_path$1); + + /*! https://mths.be/punycode v1.4.1 by @mathias */ + + + /** Highest positive signed 32-bit float value */ + var maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + var base = 36; + var tMin = 1; + var tMax = 26; + var skew = 38; + var damp = 700; + var initialBias = 72; + var initialN = 128; // 0x80 + var delimiter = '-'; // '\x2D' + var regexNonASCII = /[^\x20-\x7E]/; // unprintable ASCII chars + non-ASCII chars + var regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g; // RFC 3490 separators + + /** Error messages */ + var errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }; + + /** Convenience shortcuts */ + var baseMinusTMin = base - tMin; + var floor = Math.floor; + var stringFromCharCode = String.fromCharCode; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw new RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map$1(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map$1(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see <https://mathiasbynens.be/notes/javascript-encoding> + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * https://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for ( /* no initialization */ ; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>, + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */ ; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) ? + 'xn--' + encode(string) : + string; + }); + } + + function isNull(arg) { + return arg === null; + } + + function isNullOrUndefined(arg) { + return arg == null; + } + + function isString(arg) { + return typeof arg === 'string'; + } + + function isObject(arg) { + return typeof arg === 'object' && arg !== null; + } + + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + + // If obj.hasOwnProperty has been overridden, then calling + // obj.hasOwnProperty(prop) will break. + // See: https://github.com/joyent/node/issues/1707 + function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); + } + var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; + }; + function stringifyPrimitive(v) { + switch (typeof v) { + case 'string': + return v; + + case 'boolean': + return v ? 'true' : 'false'; + + case 'number': + return isFinite(v) ? v : ''; + + default: + return ''; + } + } + + function stringify$3 (obj, sep, eq, name) { + sep = sep || '&'; + eq = eq || '='; + if (obj === null) { + obj = undefined; + } + + if (typeof obj === 'object') { + return map(objectKeys(obj), function(k) { + var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; + if (isArray(obj[k])) { + return map(obj[k], function(v) { + return ks + encodeURIComponent(stringifyPrimitive(v)); + }).join(sep); + } else { + return ks + encodeURIComponent(stringifyPrimitive(obj[k])); + } + }).join(sep); + + } + + if (!name) return ''; + return encodeURIComponent(stringifyPrimitive(name)) + eq + + encodeURIComponent(stringifyPrimitive(obj)); + } + function map (xs, f) { + if (xs.map) return xs.map(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + res.push(f(xs[i], i)); + } + return res; + } + + var objectKeys = Object.keys || function (obj) { + var res = []; + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); + } + return res; + }; + + function parse$6(qs, sep, eq, options) { + sep = sep || '&'; + eq = eq || '='; + var obj = {}; + + if (typeof qs !== 'string' || qs.length === 0) { + return obj; + } + + var regexp = /\+/g; + qs = qs.split(sep); + + var maxKeys = 1000; + if (options && typeof options.maxKeys === 'number') { + maxKeys = options.maxKeys; + } + + var len = qs.length; + // maxKeys <= 0 means that we should not limit keys count + if (maxKeys > 0 && len > maxKeys) { + len = maxKeys; + } + + for (var i = 0; i < len; ++i) { + var x = qs[i].replace(regexp, '%20'), + idx = x.indexOf(eq), + kstr, vstr, k, v; + + if (idx >= 0) { + kstr = x.substr(0, idx); + vstr = x.substr(idx + 1); + } else { + kstr = x; + vstr = ''; + } + + k = decodeURIComponent(kstr); + v = decodeURIComponent(vstr); + + if (!hasOwnProperty(obj, k)) { + obj[k] = v; + } else if (isArray(obj[k])) { + obj[k].push(v); + } else { + obj[k] = [obj[k], v]; + } + } + + return obj; + } + + // WHATWG API + const URL$1 = global$1.URL; + const URLSearchParams = global$1.URLSearchParams; + var _polyfillNode_url = { + parse: urlParse, + resolve: urlResolve, + resolveObject: urlResolveObject, + fileURLToPath: urlFileURLToPath, + format: urlFormat, + Url: Url, + + // WHATWG API + URL: URL$1, + URLSearchParams, + }; + function Url() { + this.protocol = null; + this.slashes = null; + this.auth = null; + this.host = null; + this.port = null; + this.hostname = null; + this.hash = null; + this.search = null; + this.query = null; + this.pathname = null; + this.path = null; + this.href = null; + } + + // Reference: RFC 3986, RFC 1808, RFC 2396 + + // define these here so at least they only have to be + // compiled once on the first module load. + var protocolPattern = /^([a-z0-9.+-]+:)/i, + portPattern = /:[0-9]*$/, + + // Special case for a simple path URL + simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/, + + // RFC 2396: characters reserved for delimiting URLs. + // We actually just auto-escape these. + delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], + + // RFC 2396: characters not allowed for various reasons. + unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), + + // Allowed by RFCs, but cause of XSS attacks. Always escape these. + autoEscape = ['\''].concat(unwise), + // Characters that are never ever allowed in a hostname. + // Note that any invalid chars are also handled, but these + // are the ones that are *expected* to be seen, so we fast-path + // them. + nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), + hostEndingChars = ['/', '?', '#'], + hostnameMaxLen = 255, + hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/, + hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/, + // protocols that can allow "unsafe" and "unwise" chars. + unsafeProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that never have a hostname. + hostlessProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that always contain a // bit. + slashedProtocol = { + 'http': true, + 'https': true, + 'ftp': true, + 'gopher': true, + 'file': true, + 'http:': true, + 'https:': true, + 'ftp:': true, + 'gopher:': true, + 'file:': true + }; + + function urlParse(url, parseQueryString, slashesDenoteHost) { + if (url && isObject(url) && url instanceof Url) return url; + + var u = new Url; + u.parse(url, parseQueryString, slashesDenoteHost); + return u; + } + Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { + return parse$5(this, url, parseQueryString, slashesDenoteHost); + }; + + function parse$5(self, url, parseQueryString, slashesDenoteHost) { + if (!isString(url)) { + throw new TypeError('Parameter \'url\' must be a string, not ' + typeof url); + } + + // Copy chrome, IE, opera backslash-handling behavior. + // Back slashes before the query string get converted to forward slashes + // See: https://code.google.com/p/chromium/issues/detail?id=25916 + var queryIndex = url.indexOf('?'), + splitter = + (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#', + uSplit = url.split(splitter), + slashRegex = /\\/g; + uSplit[0] = uSplit[0].replace(slashRegex, '/'); + url = uSplit.join(splitter); + + var rest = url; + + // trim before proceeding. + // This is to support parse stuff like " http://foo.com \n" + rest = rest.trim(); + + if (!slashesDenoteHost && url.split('#').length === 1) { + // Try fast path regexp + var simplePath = simplePathPattern.exec(rest); + if (simplePath) { + self.path = rest; + self.href = rest; + self.pathname = simplePath[1]; + if (simplePath[2]) { + self.search = simplePath[2]; + if (parseQueryString) { + self.query = parse$6(self.search.substr(1)); + } else { + self.query = self.search.substr(1); + } + } else if (parseQueryString) { + self.search = ''; + self.query = {}; + } + return self; + } + } + + var proto = protocolPattern.exec(rest); + if (proto) { + proto = proto[0]; + var lowerProto = proto.toLowerCase(); + self.protocol = lowerProto; + rest = rest.substr(proto.length); + } + + // figure out if it's got a host + // user@server is *always* interpreted as a hostname, and url + // resolution will treat //foo/bar as host=foo,path=bar because that's + // how the browser resolves relative URLs. + if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { + var slashes = rest.substr(0, 2) === '//'; + if (slashes && !(proto && hostlessProtocol[proto])) { + rest = rest.substr(2); + self.slashes = true; + } + } + var i, hec, l, p; + if (!hostlessProtocol[proto] && + (slashes || (proto && !slashedProtocol[proto]))) { + + // there's a hostname. + // the first instance of /, ?, ;, or # ends the host. + // + // If there is an @ in the hostname, then non-host chars *are* allowed + // to the left of the last @ sign, unless some host-ending character + // comes *before* the @-sign. + // URLs are obnoxious. + // + // ex: + // http://a@b@c/ => user:a@b host:c + // http://a@b?@c => user:a host:c path:/?@c + + // v0.12 TODO(isaacs): This is not quite how Chrome does things. + // Review our test case against browsers more comprehensively. + + // find the first instance of any hostEndingChars + var hostEnd = -1; + for (i = 0; i < hostEndingChars.length; i++) { + hec = rest.indexOf(hostEndingChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + + // at this point, either we have an explicit point where the + // auth portion cannot go past, or the last @ char is the decider. + var auth, atSign; + if (hostEnd === -1) { + // atSign can be anywhere. + atSign = rest.lastIndexOf('@'); + } else { + // atSign must be in auth portion. + // http://a@b/c@d => host:b auth:a path:/c@d + atSign = rest.lastIndexOf('@', hostEnd); + } + + // Now we have a portion which is definitely the auth. + // Pull that off. + if (atSign !== -1) { + auth = rest.slice(0, atSign); + rest = rest.slice(atSign + 1); + self.auth = decodeURIComponent(auth); + } + + // the host is the remaining to the left of the first non-host char + hostEnd = -1; + for (i = 0; i < nonHostChars.length; i++) { + hec = rest.indexOf(nonHostChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + // if we still have not hit it, then the entire thing is a host. + if (hostEnd === -1) + hostEnd = rest.length; + + self.host = rest.slice(0, hostEnd); + rest = rest.slice(hostEnd); + + // pull out port. + parseHost(self); + + // we've indicated that there is a hostname, + // so even if it's empty, it has to be present. + self.hostname = self.hostname || ''; + + // if hostname begins with [ and ends with ] + // assume that it's an IPv6 address. + var ipv6Hostname = self.hostname[0] === '[' && + self.hostname[self.hostname.length - 1] === ']'; + + // validate a little. + if (!ipv6Hostname) { + var hostparts = self.hostname.split(/\./); + for (i = 0, l = hostparts.length; i < l; i++) { + var part = hostparts[i]; + if (!part) continue; + if (!part.match(hostnamePartPattern)) { + var newpart = ''; + for (var j = 0, k = part.length; j < k; j++) { + if (part.charCodeAt(j) > 127) { + // we replace non-ASCII char with a temporary placeholder + // we need this to make sure size of hostname is not + // broken by replacing non-ASCII by nothing + newpart += 'x'; + } else { + newpart += part[j]; + } + } + // we test again with ASCII char only + if (!newpart.match(hostnamePartPattern)) { + var validParts = hostparts.slice(0, i); + var notHost = hostparts.slice(i + 1); + var bit = part.match(hostnamePartStart); + if (bit) { + validParts.push(bit[1]); + notHost.unshift(bit[2]); + } + if (notHost.length) { + rest = '/' + notHost.join('.') + rest; + } + self.hostname = validParts.join('.'); + break; + } + } + } + } + + if (self.hostname.length > hostnameMaxLen) { + self.hostname = ''; + } else { + // hostnames are always lower case. + self.hostname = self.hostname.toLowerCase(); + } + + if (!ipv6Hostname) { + // IDNA Support: Returns a punycoded representation of "domain". + // It only converts parts of the domain name that + // have non-ASCII characters, i.e. it doesn't matter if + // you call it with a domain that already is ASCII-only. + self.hostname = toASCII(self.hostname); + } + + p = self.port ? ':' + self.port : ''; + var h = self.hostname || ''; + self.host = h + p; + self.href += self.host; + + // strip [ and ] from the hostname + // the host field still retains them, though + if (ipv6Hostname) { + self.hostname = self.hostname.substr(1, self.hostname.length - 2); + if (rest[0] !== '/') { + rest = '/' + rest; + } + } + } + + // now rest is set to the post-host stuff. + // chop off any delim chars. + if (!unsafeProtocol[lowerProto]) { + + // First, make 100% sure that any "autoEscape" chars get + // escaped, even if encodeURIComponent doesn't think they + // need to be. + for (i = 0, l = autoEscape.length; i < l; i++) { + var ae = autoEscape[i]; + if (rest.indexOf(ae) === -1) + continue; + var esc = encodeURIComponent(ae); + if (esc === ae) { + esc = escape(ae); + } + rest = rest.split(ae).join(esc); + } + } + + + // chop off from the tail first. + var hash = rest.indexOf('#'); + if (hash !== -1) { + // got a fragment string. + self.hash = rest.substr(hash); + rest = rest.slice(0, hash); + } + var qm = rest.indexOf('?'); + if (qm !== -1) { + self.search = rest.substr(qm); + self.query = rest.substr(qm + 1); + if (parseQueryString) { + self.query = parse$6(self.query); + } + rest = rest.slice(0, qm); + } else if (parseQueryString) { + // no query string, but parseQueryString still requested + self.search = ''; + self.query = {}; + } + if (rest) self.pathname = rest; + if (slashedProtocol[lowerProto] && + self.hostname && !self.pathname) { + self.pathname = '/'; + } + + //to support http.request + if (self.pathname || self.search) { + p = self.pathname || ''; + var s = self.search || ''; + self.path = p + s; + } + + // finally, reconstruct the href based on what has been validated. + self.href = format(self); + return self; + } + + function urlFileURLToPath(path) { + if (typeof path === 'string') + path = new Url().parse(path); + else if (!(path instanceof Url)) + throw new TypeError('The "path" argument must be of type string or an instance of URL. Received type ' + (typeof path) + String(path)); + if (path.protocol !== 'file:') + throw new TypeError('The URL must be of scheme file'); + return getPathFromURLPosix(path); + } + + function getPathFromURLPosix(url) { + const pathname = url.pathname; + for (let n = 0; n < pathname.length; n++) { + if (pathname[n] === '%') { + const third = pathname.codePointAt(n + 2) | 0x20; + if (pathname[n + 1] === '2' && third === 102) { + throw new TypeError( + 'must not include encoded / characters' + ); + } + } + } + return decodeURIComponent(pathname); + } + + // format a parsed object into a url string + function urlFormat(obj) { + // ensure it's an object, and not a string url. + // If it's an obj, this is a no-op. + // this way, you can call url_format() on strings + // to clean up potentially wonky urls. + if (isString(obj)) obj = parse$5({}, obj); + return format(obj); + } + + function format(self) { + var auth = self.auth || ''; + if (auth) { + auth = encodeURIComponent(auth); + auth = auth.replace(/%3A/i, ':'); + auth += '@'; + } + + var protocol = self.protocol || '', + pathname = self.pathname || '', + hash = self.hash || '', + host = false, + query = ''; + + if (self.host) { + host = auth + self.host; + } else if (self.hostname) { + host = auth + (self.hostname.indexOf(':') === -1 ? + self.hostname : + '[' + this.hostname + ']'); + if (self.port) { + host += ':' + self.port; + } + } + + if (self.query && + isObject(self.query) && + Object.keys(self.query).length) { + query = stringify$3(self.query); + } + + var search = self.search || (query && ('?' + query)) || ''; + + if (protocol && protocol.substr(-1) !== ':') protocol += ':'; + + // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. + // unless they had them to begin with. + if (self.slashes || + (!protocol || slashedProtocol[protocol]) && host !== false) { + host = '//' + (host || ''); + if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; + } else if (!host) { + host = ''; + } + + if (hash && hash.charAt(0) !== '#') hash = '#' + hash; + if (search && search.charAt(0) !== '?') search = '?' + search; + + pathname = pathname.replace(/[?#]/g, function(match) { + return encodeURIComponent(match); + }); + search = search.replace('#', '%23'); + + return protocol + host + pathname + search + hash; + } + + Url.prototype.format = function() { + return format(this); + }; + + function urlResolve(source, relative) { + return urlParse(source, false, true).resolve(relative); + } + + Url.prototype.resolve = function(relative) { + return this.resolveObject(urlParse(relative, false, true)).format(); + }; + + function urlResolveObject(source, relative) { + if (!source) return relative; + return urlParse(source, false, true).resolveObject(relative); + } + + Url.prototype.resolveObject = function(relative) { + if (isString(relative)) { + var rel = new Url(); + rel.parse(relative, false, true); + relative = rel; + } + + var result = new Url(); + var tkeys = Object.keys(this); + for (var tk = 0; tk < tkeys.length; tk++) { + var tkey = tkeys[tk]; + result[tkey] = this[tkey]; + } + + // hash is always overridden, no matter what. + // even href="" will remove it. + result.hash = relative.hash; + + // if the relative url is empty, then there's nothing left to do here. + if (relative.href === '') { + result.href = result.format(); + return result; + } + + // hrefs like //foo/bar always cut to the protocol. + if (relative.slashes && !relative.protocol) { + // take everything except the protocol from relative + var rkeys = Object.keys(relative); + for (var rk = 0; rk < rkeys.length; rk++) { + var rkey = rkeys[rk]; + if (rkey !== 'protocol') + result[rkey] = relative[rkey]; + } + + //urlParse appends trailing / to urls like http://www.example.com + if (slashedProtocol[result.protocol] && + result.hostname && !result.pathname) { + result.path = result.pathname = '/'; + } + + result.href = result.format(); + return result; + } + var relPath; + if (relative.protocol && relative.protocol !== result.protocol) { + // if it's a known url protocol, then changing + // the protocol does weird things + // first, if it's not file:, then we MUST have a host, + // and if there was a path + // to begin with, then we MUST have a path. + // if it is file:, then the host is dropped, + // because that's known to be hostless. + // anything else is assumed to be absolute. + if (!slashedProtocol[relative.protocol]) { + var keys = Object.keys(relative); + for (var v = 0; v < keys.length; v++) { + var k = keys[v]; + result[k] = relative[k]; + } + result.href = result.format(); + return result; + } + + result.protocol = relative.protocol; + if (!relative.host && !hostlessProtocol[relative.protocol]) { + relPath = (relative.pathname || '').split('/'); + while (relPath.length && !(relative.host = relPath.shift())); + if (!relative.host) relative.host = ''; + if (!relative.hostname) relative.hostname = ''; + if (relPath[0] !== '') relPath.unshift(''); + if (relPath.length < 2) relPath.unshift(''); + result.pathname = relPath.join('/'); + } else { + result.pathname = relative.pathname; + } + result.search = relative.search; + result.query = relative.query; + result.host = relative.host || ''; + result.auth = relative.auth; + result.hostname = relative.hostname || relative.host; + result.port = relative.port; + // to support http.request + if (result.pathname || result.search) { + var p = result.pathname || ''; + var s = result.search || ''; + result.path = p + s; + } + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + } + + var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), + isRelAbs = ( + relative.host || + relative.pathname && relative.pathname.charAt(0) === '/' + ), + mustEndAbs = (isRelAbs || isSourceAbs || + (result.host && relative.pathname)), + removeAllDots = mustEndAbs, + srcPath = result.pathname && result.pathname.split('/') || [], + psychotic = result.protocol && !slashedProtocol[result.protocol]; + relPath = relative.pathname && relative.pathname.split('/') || []; + // if the url is a non-slashed url, then relative + // links like ../.. should be able + // to crawl up to the hostname, as well. This is strange. + // result.protocol has already been set by now. + // Later on, put the first path part into the host field. + if (psychotic) { + result.hostname = ''; + result.port = null; + if (result.host) { + if (srcPath[0] === '') srcPath[0] = result.host; + else srcPath.unshift(result.host); + } + result.host = ''; + if (relative.protocol) { + relative.hostname = null; + relative.port = null; + if (relative.host) { + if (relPath[0] === '') relPath[0] = relative.host; + else relPath.unshift(relative.host); + } + relative.host = null; + } + mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); + } + var authInHost; + if (isRelAbs) { + // it's absolute. + result.host = (relative.host || relative.host === '') ? + relative.host : result.host; + result.hostname = (relative.hostname || relative.hostname === '') ? + relative.hostname : result.hostname; + result.search = relative.search; + result.query = relative.query; + srcPath = relPath; + // fall through to the dot-handling below. + } else if (relPath.length) { + // it's relative + // throw away the existing file, and take the new path instead. + if (!srcPath) srcPath = []; + srcPath.pop(); + srcPath = srcPath.concat(relPath); + result.search = relative.search; + result.query = relative.query; + } else if (!isNullOrUndefined(relative.search)) { + // just pull out the search. + // like href='?foo'. + // Put this after the other two cases because it simplifies the booleans + if (psychotic) { + result.hostname = result.host = srcPath.shift(); + //occationaly the auth can get stuck only in host + //this especially happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + result.search = relative.search; + result.query = relative.query; + //to support http.request + if (!isNull(result.pathname) || !isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.href = result.format(); + return result; + } + + if (!srcPath.length) { + // no path at all. easy. + // we've already handled the other stuff above. + result.pathname = null; + //to support http.request + if (result.search) { + result.path = '/' + result.search; + } else { + result.path = null; + } + result.href = result.format(); + return result; + } + + // if a url ENDs in . or .., then it must get a trailing slash. + // however, if it ends in anything else non-slashy, + // then it must NOT get a trailing slash. + var last = srcPath.slice(-1)[0]; + var hasTrailingSlash = ( + (result.host || relative.host || srcPath.length > 1) && + (last === '.' || last === '..') || last === ''); + + // strip single dots, resolve double dots to parent dir + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = srcPath.length; i >= 0; i--) { + last = srcPath[i]; + if (last === '.') { + srcPath.splice(i, 1); + } else if (last === '..') { + srcPath.splice(i, 1); + up++; + } else if (up) { + srcPath.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (!mustEndAbs && !removeAllDots) { + for (; up--; up) { + srcPath.unshift('..'); + } + } + + if (mustEndAbs && srcPath[0] !== '' && + (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { + srcPath.unshift(''); + } + + if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { + srcPath.push(''); + } + + var isAbsolute = srcPath[0] === '' || + (srcPath[0] && srcPath[0].charAt(0) === '/'); + + // put the host back + if (psychotic) { + result.hostname = result.host = isAbsolute ? '' : + srcPath.length ? srcPath.shift() : ''; + //occationaly the auth can get stuck only in host + //this especially happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + + mustEndAbs = mustEndAbs || (result.host && srcPath.length); + + if (mustEndAbs && !isAbsolute) { + srcPath.unshift(''); + } + + if (!srcPath.length) { + result.pathname = null; + result.path = null; + } else { + result.pathname = srcPath.join('/'); + } + + //to support request.http + if (!isNull(result.pathname) || !isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.auth = relative.auth || result.auth; + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + }; + + Url.prototype.parseHost = function() { + return parseHost(this); + }; + + function parseHost(self) { + var host = self.host; + var port = portPattern.exec(host); + if (port) { + port = port[0]; + if (port !== ':') { + self.port = port.substr(1); + } + host = host.substr(0, host.length - port.length); + } + if (host) self.hostname = host; + } + + var _polyfillNode_url$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + URL: URL$1, + URLSearchParams: URLSearchParams, + Url: Url, + default: _polyfillNode_url, + fileURLToPath: urlFileURLToPath, + format: urlFormat, + parse: urlParse, + resolve: urlResolve, + resolveObject: urlResolveObject + }); + + var require$$2 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_url$1); + + let urlAlphabet = + 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'; + let customAlphabet = (alphabet, defaultSize = 21) => { + return (size = defaultSize) => { + let id = ''; + let i = size; + while (i--) { + id += alphabet[(Math.random() * alphabet.length) | 0]; + } + return id + } + }; + let nanoid$1 = (size = 21) => { + let id = ''; + let i = size; + while (i--) { + id += urlAlphabet[(Math.random() * 64) | 0]; + } + return id + }; + var nonSecure = { nanoid: nanoid$1, customAlphabet }; + + var _polyfillNode_fs = {}; + + var _polyfillNode_fs$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + default: _polyfillNode_fs + }); + + var require$$1 = /*@__PURE__*/getAugmentedNamespace(_polyfillNode_fs$1); + + let { SourceMapConsumer: SourceMapConsumer$2, SourceMapGenerator: SourceMapGenerator$2 } = sourceMap; + let { existsSync, readFileSync } = require$$1; + let { dirname: dirname$1, join } = require$$1$1; + + function fromBase64(str) { + if (Buffer$1) { + return Buffer$1.from(str, 'base64').toString() + } else { + /* c8 ignore next 2 */ + return window.atob(str) + } + } + + let PreviousMap$2 = class PreviousMap { + constructor(css, opts) { + if (opts.map === false) return + this.loadAnnotation(css); + this.inline = this.startWith(this.annotation, 'data:'); + + let prev = opts.map ? opts.map.prev : undefined; + let text = this.loadMap(opts.from, prev); + if (!this.mapFile && opts.from) { + this.mapFile = opts.from; + } + if (this.mapFile) this.root = dirname$1(this.mapFile); + if (text) this.text = text; + } + + consumer() { + if (!this.consumerCache) { + this.consumerCache = new SourceMapConsumer$2(this.text); + } + return this.consumerCache + } + + decodeInline(text) { + let baseCharsetUri = /^data:application\/json;charset=utf-?8;base64,/; + let baseUri = /^data:application\/json;base64,/; + let charsetUri = /^data:application\/json;charset=utf-?8,/; + let uri = /^data:application\/json,/; + + if (charsetUri.test(text) || uri.test(text)) { + return decodeURIComponent(text.substr(RegExp.lastMatch.length)) + } + + if (baseCharsetUri.test(text) || baseUri.test(text)) { + return fromBase64(text.substr(RegExp.lastMatch.length)) + } + + let encoding = text.match(/data:application\/json;([^,]+),/)[1]; + throw new Error('Unsupported source map encoding ' + encoding) + } + + getAnnotationURL(sourceMapString) { + return sourceMapString.replace(/^\/\*\s*# sourceMappingURL=/, '').trim() + } + + isMap(map) { + if (typeof map !== 'object') return false + return ( + typeof map.mappings === 'string' || + typeof map._mappings === 'string' || + Array.isArray(map.sections) + ) + } + + loadAnnotation(css) { + let comments = css.match(/\/\*\s*# sourceMappingURL=/gm); + if (!comments) return + + // sourceMappingURLs from comments, strings, etc. + let start = css.lastIndexOf(comments.pop()); + let end = css.indexOf('*/', start); + + if (start > -1 && end > -1) { + // Locate the last sourceMappingURL to avoid pickin + this.annotation = this.getAnnotationURL(css.substring(start, end)); + } + } + + loadFile(path) { + this.root = dirname$1(path); + if (existsSync(path)) { + this.mapFile = path; + return readFileSync(path, 'utf-8').toString().trim() + } + } + + loadMap(file, prev) { + if (prev === false) return false + + if (prev) { + if (typeof prev === 'string') { + return prev + } else if (typeof prev === 'function') { + let prevPath = prev(file); + if (prevPath) { + let map = this.loadFile(prevPath); + if (!map) { + throw new Error( + 'Unable to load previous source map: ' + prevPath.toString() + ) + } + return map + } + } else if (prev instanceof SourceMapConsumer$2) { + return SourceMapGenerator$2.fromSourceMap(prev).toString() + } else if (prev instanceof SourceMapGenerator$2) { + return prev.toString() + } else if (this.isMap(prev)) { + return JSON.stringify(prev) + } else { + throw new Error( + 'Unsupported previous source map format: ' + prev.toString() + ) + } + } else if (this.inline) { + return this.decodeInline(this.annotation) + } else if (this.annotation) { + let map = this.annotation; + if (file) map = join(dirname$1(file), map); + return this.loadFile(map) + } + } + + startWith(string, start) { + if (!string) return false + return string.substr(0, start.length) === start + } + + withContent() { + return !!( + this.consumer().sourcesContent && + this.consumer().sourcesContent.length > 0 + ) + } + }; + + var previousMap = PreviousMap$2; + PreviousMap$2.default = PreviousMap$2; + + let { SourceMapConsumer: SourceMapConsumer$1, SourceMapGenerator: SourceMapGenerator$1 } = sourceMap; + let { fileURLToPath, pathToFileURL: pathToFileURL$1 } = require$$2; + let { isAbsolute, resolve: resolve$1 } = require$$1$1; + let { nanoid } = nonSecure; + + let terminalHighlight = terminalHighlight_1; + let CssSyntaxError$1 = cssSyntaxError; + let PreviousMap$1 = previousMap; + + let fromOffsetCache = Symbol('fromOffsetCache'); + + let sourceMapAvailable$1 = Boolean(SourceMapConsumer$1 && SourceMapGenerator$1); + let pathAvailable$1 = Boolean(resolve$1 && isAbsolute); + + let Input$4 = class Input { + constructor(css, opts = {}) { + if ( + css === null || + typeof css === 'undefined' || + (typeof css === 'object' && !css.toString) + ) { + throw new Error(`PostCSS received ${css} instead of CSS string`) + } + + this.css = css.toString(); + + if (this.css[0] === '\uFEFF' || this.css[0] === '\uFFFE') { + this.hasBOM = true; + this.css = this.css.slice(1); + } else { + this.hasBOM = false; + } + + if (opts.from) { + if ( + !pathAvailable$1 || + /^\w+:\/\//.test(opts.from) || + isAbsolute(opts.from) + ) { + this.file = opts.from; + } else { + this.file = resolve$1(opts.from); + } + } + + if (pathAvailable$1 && sourceMapAvailable$1) { + let map = new PreviousMap$1(this.css, opts); + if (map.text) { + this.map = map; + let file = map.consumer().file; + if (!this.file && file) this.file = this.mapResolve(file); + } + } + + if (!this.file) { + this.id = '<input css ' + nanoid(6) + '>'; + } + if (this.map) this.map.file = this.from; + } + + error(message, line, column, opts = {}) { + let result, endLine, endColumn; + + if (line && typeof line === 'object') { + let start = line; + let end = column; + if (typeof start.offset === 'number') { + let pos = this.fromOffset(start.offset); + line = pos.line; + column = pos.col; + } else { + line = start.line; + column = start.column; + } + if (typeof end.offset === 'number') { + let pos = this.fromOffset(end.offset); + endLine = pos.line; + endColumn = pos.col; + } else { + endLine = end.line; + endColumn = end.column; + } + } else if (!column) { + let pos = this.fromOffset(line); + line = pos.line; + column = pos.col; + } + + let origin = this.origin(line, column, endLine, endColumn); + if (origin) { + result = new CssSyntaxError$1( + message, + origin.endLine === undefined + ? origin.line + : { column: origin.column, line: origin.line }, + origin.endLine === undefined + ? origin.column + : { column: origin.endColumn, line: origin.endLine }, + origin.source, + origin.file, + opts.plugin + ); + } else { + result = new CssSyntaxError$1( + message, + endLine === undefined ? line : { column, line }, + endLine === undefined ? column : { column: endColumn, line: endLine }, + this.css, + this.file, + opts.plugin + ); + } + + result.input = { column, endColumn, endLine, line, source: this.css }; + if (this.file) { + if (pathToFileURL$1) { + result.input.url = pathToFileURL$1(this.file).toString(); + } + result.input.file = this.file; + } + + return result + } + + fromOffset(offset) { + let lastLine, lineToIndex; + if (!this[fromOffsetCache]) { + let lines = this.css.split('\n'); + lineToIndex = new Array(lines.length); + let prevIndex = 0; + + for (let i = 0, l = lines.length; i < l; i++) { + lineToIndex[i] = prevIndex; + prevIndex += lines[i].length + 1; + } + + this[fromOffsetCache] = lineToIndex; + } else { + lineToIndex = this[fromOffsetCache]; + } + lastLine = lineToIndex[lineToIndex.length - 1]; + + let min = 0; + if (offset >= lastLine) { + min = lineToIndex.length - 1; + } else { + let max = lineToIndex.length - 2; + let mid; + while (min < max) { + mid = min + ((max - min) >> 1); + if (offset < lineToIndex[mid]) { + max = mid - 1; + } else if (offset >= lineToIndex[mid + 1]) { + min = mid + 1; + } else { + min = mid; + break + } + } + } + return { + col: offset - lineToIndex[min] + 1, + line: min + 1 + } + } + + mapResolve(file) { + if (/^\w+:\/\//.test(file)) { + return file + } + return resolve$1(this.map.consumer().sourceRoot || this.map.root || '.', file) + } + + origin(line, column, endLine, endColumn) { + if (!this.map) return false + let consumer = this.map.consumer(); + + let from = consumer.originalPositionFor({ column, line }); + if (!from.source) return false + + let to; + if (typeof endLine === 'number') { + to = consumer.originalPositionFor({ column: endColumn, line: endLine }); + } + + let fromUrl; + + if (isAbsolute(from.source)) { + fromUrl = pathToFileURL$1(from.source); + } else { + fromUrl = new URL( + from.source, + this.map.consumer().sourceRoot || pathToFileURL$1(this.map.mapFile) + ); + } + + let result = { + column: from.column, + endColumn: to && to.column, + endLine: to && to.line, + line: from.line, + url: fromUrl.toString() + }; + + if (fromUrl.protocol === 'file:') { + if (fileURLToPath) { + result.file = fileURLToPath(fromUrl); + } else { + /* c8 ignore next 2 */ + throw new Error(`file: protocol is not available in this PostCSS build`) + } + } + + let source = consumer.sourceContentFor(from.source); + if (source) result.source = source; + + return result + } + + toJSON() { + let json = {}; + for (let name of ['hasBOM', 'css', 'file', 'id']) { + if (this[name] != null) { + json[name] = this[name]; + } + } + if (this.map) { + json.map = { ...this.map }; + if (json.map.consumerCache) { + json.map.consumerCache = undefined; + } + } + return json + } + + get from() { + return this.file || this.id + } + }; + + var input = Input$4; + Input$4.default = Input$4; + + if (terminalHighlight && terminalHighlight.registerInput) { + terminalHighlight.registerInput(Input$4); + } + + let { SourceMapConsumer, SourceMapGenerator } = sourceMap; + let { dirname, relative, resolve, sep } = require$$1$1; + let { pathToFileURL } = require$$2; + + let Input$3 = input; + + let sourceMapAvailable = Boolean(SourceMapConsumer && SourceMapGenerator); + let pathAvailable = Boolean(dirname && resolve && relative && sep); + + let MapGenerator$2 = class MapGenerator { + constructor(stringify, root, opts, cssString) { + this.stringify = stringify; + this.mapOpts = opts.map || {}; + this.root = root; + this.opts = opts; + this.css = cssString; + this.originalCSS = cssString; + this.usesFileUrls = !this.mapOpts.from && this.mapOpts.absolute; + + this.memoizedFileURLs = new Map(); + this.memoizedPaths = new Map(); + this.memoizedURLs = new Map(); + } + + addAnnotation() { + let content; + + if (this.isInline()) { + content = + 'data:application/json;base64,' + this.toBase64(this.map.toString()); + } else if (typeof this.mapOpts.annotation === 'string') { + content = this.mapOpts.annotation; + } else if (typeof this.mapOpts.annotation === 'function') { + content = this.mapOpts.annotation(this.opts.to, this.root); + } else { + content = this.outputFile() + '.map'; + } + let eol = '\n'; + if (this.css.includes('\r\n')) eol = '\r\n'; + + this.css += eol + '/*# sourceMappingURL=' + content + ' */'; + } + + applyPrevMaps() { + for (let prev of this.previous()) { + let from = this.toUrl(this.path(prev.file)); + let root = prev.root || dirname(prev.file); + let map; + + if (this.mapOpts.sourcesContent === false) { + map = new SourceMapConsumer(prev.text); + if (map.sourcesContent) { + map.sourcesContent = null; + } + } else { + map = prev.consumer(); + } + + this.map.applySourceMap(map, from, this.toUrl(this.path(root))); + } + } + + clearAnnotation() { + if (this.mapOpts.annotation === false) return + + if (this.root) { + let node; + for (let i = this.root.nodes.length - 1; i >= 0; i--) { + node = this.root.nodes[i]; + if (node.type !== 'comment') continue + if (node.text.indexOf('# sourceMappingURL=') === 0) { + this.root.removeChild(i); + } + } + } else if (this.css) { + this.css = this.css.replace(/\n*?\/\*#[\S\s]*?\*\/$/gm, ''); + } + } + + generate() { + this.clearAnnotation(); + if (pathAvailable && sourceMapAvailable && this.isMap()) { + return this.generateMap() + } else { + let result = ''; + this.stringify(this.root, i => { + result += i; + }); + return [result] + } + } + + generateMap() { + if (this.root) { + this.generateString(); + } else if (this.previous().length === 1) { + let prev = this.previous()[0].consumer(); + prev.file = this.outputFile(); + this.map = SourceMapGenerator.fromSourceMap(prev, { + ignoreInvalidMapping: true + }); + } else { + this.map = new SourceMapGenerator({ + file: this.outputFile(), + ignoreInvalidMapping: true + }); + this.map.addMapping({ + generated: { column: 0, line: 1 }, + original: { column: 0, line: 1 }, + source: this.opts.from + ? this.toUrl(this.path(this.opts.from)) + : '<no source>' + }); + } + + if (this.isSourcesContent()) this.setSourcesContent(); + if (this.root && this.previous().length > 0) this.applyPrevMaps(); + if (this.isAnnotation()) this.addAnnotation(); + + if (this.isInline()) { + return [this.css] + } else { + return [this.css, this.map] + } + } + + generateString() { + this.css = ''; + this.map = new SourceMapGenerator({ + file: this.outputFile(), + ignoreInvalidMapping: true + }); + + let line = 1; + let column = 1; + + let noSource = '<no source>'; + let mapping = { + generated: { column: 0, line: 0 }, + original: { column: 0, line: 0 }, + source: '' + }; + + let lines, last; + this.stringify(this.root, (str, node, type) => { + this.css += str; + + if (node && type !== 'end') { + mapping.generated.line = line; + mapping.generated.column = column - 1; + if (node.source && node.source.start) { + mapping.source = this.sourcePath(node); + mapping.original.line = node.source.start.line; + mapping.original.column = node.source.start.column - 1; + this.map.addMapping(mapping); + } else { + mapping.source = noSource; + mapping.original.line = 1; + mapping.original.column = 0; + this.map.addMapping(mapping); + } + } + + lines = str.match(/\n/g); + if (lines) { + line += lines.length; + last = str.lastIndexOf('\n'); + column = str.length - last; + } else { + column += str.length; + } + + if (node && type !== 'start') { + let p = node.parent || { raws: {} }; + let childless = + node.type === 'decl' || (node.type === 'atrule' && !node.nodes); + if (!childless || node !== p.last || p.raws.semicolon) { + if (node.source && node.source.end) { + mapping.source = this.sourcePath(node); + mapping.original.line = node.source.end.line; + mapping.original.column = node.source.end.column - 1; + mapping.generated.line = line; + mapping.generated.column = column - 2; + this.map.addMapping(mapping); + } else { + mapping.source = noSource; + mapping.original.line = 1; + mapping.original.column = 0; + mapping.generated.line = line; + mapping.generated.column = column - 1; + this.map.addMapping(mapping); + } + } + } + }); + } + + isAnnotation() { + if (this.isInline()) { + return true + } + if (typeof this.mapOpts.annotation !== 'undefined') { + return this.mapOpts.annotation + } + if (this.previous().length) { + return this.previous().some(i => i.annotation) + } + return true + } + + isInline() { + if (typeof this.mapOpts.inline !== 'undefined') { + return this.mapOpts.inline + } + + let annotation = this.mapOpts.annotation; + if (typeof annotation !== 'undefined' && annotation !== true) { + return false + } + + if (this.previous().length) { + return this.previous().some(i => i.inline) + } + return true + } + + isMap() { + if (typeof this.opts.map !== 'undefined') { + return !!this.opts.map + } + return this.previous().length > 0 + } + + isSourcesContent() { + if (typeof this.mapOpts.sourcesContent !== 'undefined') { + return this.mapOpts.sourcesContent + } + if (this.previous().length) { + return this.previous().some(i => i.withContent()) + } + return true + } + + outputFile() { + if (this.opts.to) { + return this.path(this.opts.to) + } else if (this.opts.from) { + return this.path(this.opts.from) + } else { + return 'to.css' + } + } + + path(file) { + if (this.mapOpts.absolute) return file + if (file.charCodeAt(0) === 60 /* `<` */) return file + if (/^\w+:\/\//.test(file)) return file + let cached = this.memoizedPaths.get(file); + if (cached) return cached + + let from = this.opts.to ? dirname(this.opts.to) : '.'; + + if (typeof this.mapOpts.annotation === 'string') { + from = dirname(resolve(from, this.mapOpts.annotation)); + } + + let path = relative(from, file); + this.memoizedPaths.set(file, path); + + return path + } + + previous() { + if (!this.previousMaps) { + this.previousMaps = []; + if (this.root) { + this.root.walk(node => { + if (node.source && node.source.input.map) { + let map = node.source.input.map; + if (!this.previousMaps.includes(map)) { + this.previousMaps.push(map); + } + } + }); + } else { + let input = new Input$3(this.originalCSS, this.opts); + if (input.map) this.previousMaps.push(input.map); + } + } + + return this.previousMaps + } + + setSourcesContent() { + let already = {}; + if (this.root) { + this.root.walk(node => { + if (node.source) { + let from = node.source.input.from; + if (from && !already[from]) { + already[from] = true; + let fromUrl = this.usesFileUrls + ? this.toFileUrl(from) + : this.toUrl(this.path(from)); + this.map.setSourceContent(fromUrl, node.source.input.css); + } + } + }); + } else if (this.css) { + let from = this.opts.from + ? this.toUrl(this.path(this.opts.from)) + : '<no source>'; + this.map.setSourceContent(from, this.css); + } + } + + sourcePath(node) { + if (this.mapOpts.from) { + return this.toUrl(this.mapOpts.from) + } else if (this.usesFileUrls) { + return this.toFileUrl(node.source.input.from) + } else { + return this.toUrl(this.path(node.source.input.from)) + } + } + + toBase64(str) { + if (Buffer$1) { + return Buffer$1.from(str).toString('base64') + } else { + return window.btoa(unescape(encodeURIComponent(str))) + } + } + + toFileUrl(path) { + let cached = this.memoizedFileURLs.get(path); + if (cached) return cached + + if (pathToFileURL) { + let fileURL = pathToFileURL(path).toString(); + this.memoizedFileURLs.set(path, fileURL); + + return fileURL + } else { + throw new Error( + '`map.absolute` option is not available in this PostCSS build' + ) + } + } + + toUrl(path) { + let cached = this.memoizedURLs.get(path); + if (cached) return cached + + if (sep === '\\') { + path = path.replace(/\\/g, '/'); + } + + let url = encodeURI(path).replace(/[#?]/g, encodeURIComponent); + this.memoizedURLs.set(path, url); + + return url + } + }; + + var mapGenerator = MapGenerator$2; + + let Node$2 = node; + + let Comment$4 = class Comment extends Node$2 { + constructor(defaults) { + super(defaults); + this.type = 'comment'; + } + }; + + var comment = Comment$4; + Comment$4.default = Comment$4; + + let { isClean: isClean$1, my: my$1 } = symbols; + let Declaration$3 = declaration; + let Comment$3 = comment; + let Node$1 = node; + + let parse$4, Rule$4, AtRule$4, Root$6; + + function cleanSource(nodes) { + return nodes.map(i => { + if (i.nodes) i.nodes = cleanSource(i.nodes); + delete i.source; + return i + }) + } + + function markDirtyUp(node) { + node[isClean$1] = false; + if (node.proxyOf.nodes) { + for (let i of node.proxyOf.nodes) { + markDirtyUp(i); + } + } + } + + let Container$7 = class Container extends Node$1 { + append(...children) { + for (let child of children) { + let nodes = this.normalize(child, this.last); + for (let node of nodes) this.proxyOf.nodes.push(node); + } + + this.markDirty(); + + return this + } + + cleanRaws(keepBetween) { + super.cleanRaws(keepBetween); + if (this.nodes) { + for (let node of this.nodes) node.cleanRaws(keepBetween); + } + } + + each(callback) { + if (!this.proxyOf.nodes) return undefined + let iterator = this.getIterator(); + + let index, result; + while (this.indexes[iterator] < this.proxyOf.nodes.length) { + index = this.indexes[iterator]; + result = callback(this.proxyOf.nodes[index], index); + if (result === false) break + + this.indexes[iterator] += 1; + } + + delete this.indexes[iterator]; + return result + } + + every(condition) { + return this.nodes.every(condition) + } + + getIterator() { + if (!this.lastEach) this.lastEach = 0; + if (!this.indexes) this.indexes = {}; + + this.lastEach += 1; + let iterator = this.lastEach; + this.indexes[iterator] = 0; + + return iterator + } + + getProxyProcessor() { + return { + get(node, prop) { + if (prop === 'proxyOf') { + return node + } else if (!node[prop]) { + return node[prop] + } else if ( + prop === 'each' || + (typeof prop === 'string' && prop.startsWith('walk')) + ) { + return (...args) => { + return node[prop]( + ...args.map(i => { + if (typeof i === 'function') { + return (child, index) => i(child.toProxy(), index) + } else { + return i + } + }) + ) + } + } else if (prop === 'every' || prop === 'some') { + return cb => { + return node[prop]((child, ...other) => + cb(child.toProxy(), ...other) + ) + } + } else if (prop === 'root') { + return () => node.root().toProxy() + } else if (prop === 'nodes') { + return node.nodes.map(i => i.toProxy()) + } else if (prop === 'first' || prop === 'last') { + return node[prop].toProxy() + } else { + return node[prop] + } + }, + + set(node, prop, value) { + if (node[prop] === value) return true + node[prop] = value; + if (prop === 'name' || prop === 'params' || prop === 'selector') { + node.markDirty(); + } + return true + } + } + } + + index(child) { + if (typeof child === 'number') return child + if (child.proxyOf) child = child.proxyOf; + return this.proxyOf.nodes.indexOf(child) + } + + insertAfter(exist, add) { + let existIndex = this.index(exist); + let nodes = this.normalize(add, this.proxyOf.nodes[existIndex]).reverse(); + existIndex = this.index(exist); + for (let node of nodes) this.proxyOf.nodes.splice(existIndex + 1, 0, node); + + let index; + for (let id in this.indexes) { + index = this.indexes[id]; + if (existIndex < index) { + this.indexes[id] = index + nodes.length; + } + } + + this.markDirty(); + + return this + } + + insertBefore(exist, add) { + let existIndex = this.index(exist); + let type = existIndex === 0 ? 'prepend' : false; + let nodes = this.normalize(add, this.proxyOf.nodes[existIndex], type).reverse(); + existIndex = this.index(exist); + for (let node of nodes) this.proxyOf.nodes.splice(existIndex, 0, node); + + let index; + for (let id in this.indexes) { + index = this.indexes[id]; + if (existIndex <= index) { + this.indexes[id] = index + nodes.length; + } + } + + this.markDirty(); + + return this + } + + normalize(nodes, sample) { + if (typeof nodes === 'string') { + nodes = cleanSource(parse$4(nodes).nodes); + } else if (typeof nodes === 'undefined') { + nodes = []; + } else if (Array.isArray(nodes)) { + nodes = nodes.slice(0); + for (let i of nodes) { + if (i.parent) i.parent.removeChild(i, 'ignore'); + } + } else if (nodes.type === 'root' && this.type !== 'document') { + nodes = nodes.nodes.slice(0); + for (let i of nodes) { + if (i.parent) i.parent.removeChild(i, 'ignore'); + } + } else if (nodes.type) { + nodes = [nodes]; + } else if (nodes.prop) { + if (typeof nodes.value === 'undefined') { + throw new Error('Value field is missed in node creation') + } else if (typeof nodes.value !== 'string') { + nodes.value = String(nodes.value); + } + nodes = [new Declaration$3(nodes)]; + } else if (nodes.selector) { + nodes = [new Rule$4(nodes)]; + } else if (nodes.name) { + nodes = [new AtRule$4(nodes)]; + } else if (nodes.text) { + nodes = [new Comment$3(nodes)]; + } else { + throw new Error('Unknown node type in node creation') + } + + let processed = nodes.map(i => { + /* c8 ignore next */ + if (!i[my$1]) Container.rebuild(i); + i = i.proxyOf; + if (i.parent) i.parent.removeChild(i); + if (i[isClean$1]) markDirtyUp(i); + if (typeof i.raws.before === 'undefined') { + if (sample && typeof sample.raws.before !== 'undefined') { + i.raws.before = sample.raws.before.replace(/\S/g, ''); + } + } + i.parent = this.proxyOf; + return i + }); + + return processed + } + + prepend(...children) { + children = children.reverse(); + for (let child of children) { + let nodes = this.normalize(child, this.first, 'prepend').reverse(); + for (let node of nodes) this.proxyOf.nodes.unshift(node); + for (let id in this.indexes) { + this.indexes[id] = this.indexes[id] + nodes.length; + } + } + + this.markDirty(); + + return this + } + + push(child) { + child.parent = this; + this.proxyOf.nodes.push(child); + return this + } + + removeAll() { + for (let node of this.proxyOf.nodes) node.parent = undefined; + this.proxyOf.nodes = []; + + this.markDirty(); + + return this + } + + removeChild(child) { + child = this.index(child); + this.proxyOf.nodes[child].parent = undefined; + this.proxyOf.nodes.splice(child, 1); + + let index; + for (let id in this.indexes) { + index = this.indexes[id]; + if (index >= child) { + this.indexes[id] = index - 1; + } + } + + this.markDirty(); + + return this + } + + replaceValues(pattern, opts, callback) { + if (!callback) { + callback = opts; + opts = {}; + } + + this.walkDecls(decl => { + if (opts.props && !opts.props.includes(decl.prop)) return + if (opts.fast && !decl.value.includes(opts.fast)) return + + decl.value = decl.value.replace(pattern, callback); + }); + + this.markDirty(); + + return this + } + + some(condition) { + return this.nodes.some(condition) + } + + walk(callback) { + return this.each((child, i) => { + let result; + try { + result = callback(child, i); + } catch (e) { + throw child.addToError(e) + } + if (result !== false && child.walk) { + result = child.walk(callback); + } + + return result + }) + } + + walkAtRules(name, callback) { + if (!callback) { + callback = name; + return this.walk((child, i) => { + if (child.type === 'atrule') { + return callback(child, i) + } + }) + } + if (name instanceof RegExp) { + return this.walk((child, i) => { + if (child.type === 'atrule' && name.test(child.name)) { + return callback(child, i) + } + }) + } + return this.walk((child, i) => { + if (child.type === 'atrule' && child.name === name) { + return callback(child, i) + } + }) + } + + walkComments(callback) { + return this.walk((child, i) => { + if (child.type === 'comment') { + return callback(child, i) + } + }) + } + + walkDecls(prop, callback) { + if (!callback) { + callback = prop; + return this.walk((child, i) => { + if (child.type === 'decl') { + return callback(child, i) + } + }) + } + if (prop instanceof RegExp) { + return this.walk((child, i) => { + if (child.type === 'decl' && prop.test(child.prop)) { + return callback(child, i) + } + }) + } + return this.walk((child, i) => { + if (child.type === 'decl' && child.prop === prop) { + return callback(child, i) + } + }) + } + + walkRules(selector, callback) { + if (!callback) { + callback = selector; + + return this.walk((child, i) => { + if (child.type === 'rule') { + return callback(child, i) + } + }) + } + if (selector instanceof RegExp) { + return this.walk((child, i) => { + if (child.type === 'rule' && selector.test(child.selector)) { + return callback(child, i) + } + }) + } + return this.walk((child, i) => { + if (child.type === 'rule' && child.selector === selector) { + return callback(child, i) + } + }) + } + + get first() { + if (!this.proxyOf.nodes) return undefined + return this.proxyOf.nodes[0] + } + + get last() { + if (!this.proxyOf.nodes) return undefined + return this.proxyOf.nodes[this.proxyOf.nodes.length - 1] + } + }; + + Container$7.registerParse = dependant => { + parse$4 = dependant; + }; + + Container$7.registerRule = dependant => { + Rule$4 = dependant; + }; + + Container$7.registerAtRule = dependant => { + AtRule$4 = dependant; + }; + + Container$7.registerRoot = dependant => { + Root$6 = dependant; + }; + + var container = Container$7; + Container$7.default = Container$7; + + /* c8 ignore start */ + Container$7.rebuild = node => { + if (node.type === 'atrule') { + Object.setPrototypeOf(node, AtRule$4.prototype); + } else if (node.type === 'rule') { + Object.setPrototypeOf(node, Rule$4.prototype); + } else if (node.type === 'decl') { + Object.setPrototypeOf(node, Declaration$3.prototype); + } else if (node.type === 'comment') { + Object.setPrototypeOf(node, Comment$3.prototype); + } else if (node.type === 'root') { + Object.setPrototypeOf(node, Root$6.prototype); + } + + node[my$1] = true; + + if (node.nodes) { + node.nodes.forEach(child => { + Container$7.rebuild(child); + }); + } + }; + + let Container$6 = container; + + let LazyResult$4, Processor$3; + + let Document$3 = class Document extends Container$6 { + constructor(defaults) { + // type needs to be passed to super, otherwise child roots won't be normalized correctly + super({ type: 'document', ...defaults }); + + if (!this.nodes) { + this.nodes = []; + } + } + + toResult(opts = {}) { + let lazy = new LazyResult$4(new Processor$3(), this, opts); + + return lazy.stringify() + } + }; + + Document$3.registerLazyResult = dependant => { + LazyResult$4 = dependant; + }; + + Document$3.registerProcessor = dependant => { + Processor$3 = dependant; + }; + + var document = Document$3; + Document$3.default = Document$3; + + /* eslint-disable no-console */ + + let printed = {}; + + var warnOnce$2 = function warnOnce(message) { + if (printed[message]) return + printed[message] = true; + + if (typeof console !== 'undefined' && console.warn) { + console.warn(message); + } + }; + + let Warning$2 = class Warning { + constructor(text, opts = {}) { + this.type = 'warning'; + this.text = text; + + if (opts.node && opts.node.source) { + let range = opts.node.rangeBy(opts); + this.line = range.start.line; + this.column = range.start.column; + this.endLine = range.end.line; + this.endColumn = range.end.column; + } + + for (let opt in opts) this[opt] = opts[opt]; + } + + toString() { + if (this.node) { + return this.node.error(this.text, { + index: this.index, + plugin: this.plugin, + word: this.word + }).message + } + + if (this.plugin) { + return this.plugin + ': ' + this.text + } + + return this.text + } + }; + + var warning = Warning$2; + Warning$2.default = Warning$2; + + let Warning$1 = warning; + + let Result$3 = class Result { + constructor(processor, root, opts) { + this.processor = processor; + this.messages = []; + this.root = root; + this.opts = opts; + this.css = undefined; + this.map = undefined; + } + + toString() { + return this.css + } + + warn(text, opts = {}) { + if (!opts.plugin) { + if (this.lastPlugin && this.lastPlugin.postcssPlugin) { + opts.plugin = this.lastPlugin.postcssPlugin; + } + } + + let warning = new Warning$1(text, opts); + this.messages.push(warning); + + return warning + } + + warnings() { + return this.messages.filter(i => i.type === 'warning') + } + + get content() { + return this.css + } + }; + + var result = Result$3; + Result$3.default = Result$3; + + let Container$5 = container; + + let AtRule$3 = class AtRule extends Container$5 { + constructor(defaults) { + super(defaults); + this.type = 'atrule'; + } + + append(...children) { + if (!this.proxyOf.nodes) this.nodes = []; + return super.append(...children) + } + + prepend(...children) { + if (!this.proxyOf.nodes) this.nodes = []; + return super.prepend(...children) + } + }; + + var atRule = AtRule$3; + AtRule$3.default = AtRule$3; + + Container$5.registerAtRule(AtRule$3); + + let Container$4 = container; + + let LazyResult$3, Processor$2; + + let Root$5 = class Root extends Container$4 { + constructor(defaults) { + super(defaults); + this.type = 'root'; + if (!this.nodes) this.nodes = []; + } + + normalize(child, sample, type) { + let nodes = super.normalize(child); + + if (sample) { + if (type === 'prepend') { + if (this.nodes.length > 1) { + sample.raws.before = this.nodes[1].raws.before; + } else { + delete sample.raws.before; + } + } else if (this.first !== sample) { + for (let node of nodes) { + node.raws.before = sample.raws.before; + } + } + } + + return nodes + } + + removeChild(child, ignore) { + let index = this.index(child); + + if (!ignore && index === 0 && this.nodes.length > 1) { + this.nodes[1].raws.before = this.nodes[index].raws.before; + } + + return super.removeChild(child) + } + + toResult(opts = {}) { + let lazy = new LazyResult$3(new Processor$2(), this, opts); + return lazy.stringify() + } + }; + + Root$5.registerLazyResult = dependant => { + LazyResult$3 = dependant; + }; + + Root$5.registerProcessor = dependant => { + Processor$2 = dependant; + }; + + var root = Root$5; + Root$5.default = Root$5; + + Container$4.registerRoot(Root$5); + + let list$2 = { + comma(string) { + return list$2.split(string, [','], true) + }, + + space(string) { + let spaces = [' ', '\n', '\t']; + return list$2.split(string, spaces) + }, + + split(string, separators, last) { + let array = []; + let current = ''; + let split = false; + + let func = 0; + let inQuote = false; + let prevQuote = ''; + let escape = false; + + for (let letter of string) { + if (escape) { + escape = false; + } else if (letter === '\\') { + escape = true; + } else if (inQuote) { + if (letter === prevQuote) { + inQuote = false; + } + } else if (letter === '"' || letter === "'") { + inQuote = true; + prevQuote = letter; + } else if (letter === '(') { + func += 1; + } else if (letter === ')') { + if (func > 0) func -= 1; + } else if (func === 0) { + if (separators.includes(letter)) split = true; + } + + if (split) { + if (current !== '') array.push(current.trim()); + current = ''; + split = false; + } else { + current += letter; + } + } + + if (last || current !== '') array.push(current.trim()); + return array + } + }; + + var list_1 = list$2; + list$2.default = list$2; + + let Container$3 = container; + let list$1 = list_1; + + let Rule$3 = class Rule extends Container$3 { + constructor(defaults) { + super(defaults); + this.type = 'rule'; + if (!this.nodes) this.nodes = []; + } + + get selectors() { + return list$1.comma(this.selector) + } + + set selectors(values) { + let match = this.selector ? this.selector.match(/,\s*/) : null; + let sep = match ? match[0] : ',' + this.raw('between', 'beforeOpen'); + this.selector = values.join(sep); + } + }; + + var rule = Rule$3; + Rule$3.default = Rule$3; + + Container$3.registerRule(Rule$3); + + let Declaration$2 = declaration; + let tokenizer = tokenize; + let Comment$2 = comment; + let AtRule$2 = atRule; + let Root$4 = root; + let Rule$2 = rule; + + const SAFE_COMMENT_NEIGHBOR = { + empty: true, + space: true + }; + + function findLastWithPosition(tokens) { + for (let i = tokens.length - 1; i >= 0; i--) { + let token = tokens[i]; + let pos = token[3] || token[2]; + if (pos) return pos + } + } + + let Parser$1 = class Parser { + constructor(input) { + this.input = input; + + this.root = new Root$4(); + this.current = this.root; + this.spaces = ''; + this.semicolon = false; + + this.createTokenizer(); + this.root.source = { input, start: { column: 1, line: 1, offset: 0 } }; + } + + atrule(token) { + let node = new AtRule$2(); + node.name = token[1].slice(1); + if (node.name === '') { + this.unnamedAtrule(node, token); + } + this.init(node, token[2]); + + let type; + let prev; + let shift; + let last = false; + let open = false; + let params = []; + let brackets = []; + + while (!this.tokenizer.endOfFile()) { + token = this.tokenizer.nextToken(); + type = token[0]; + + if (type === '(' || type === '[') { + brackets.push(type === '(' ? ')' : ']'); + } else if (type === '{' && brackets.length > 0) { + brackets.push('}'); + } else if (type === brackets[brackets.length - 1]) { + brackets.pop(); + } + + if (brackets.length === 0) { + if (type === ';') { + node.source.end = this.getPosition(token[2]); + node.source.end.offset++; + this.semicolon = true; + break + } else if (type === '{') { + open = true; + break + } else if (type === '}') { + if (params.length > 0) { + shift = params.length - 1; + prev = params[shift]; + while (prev && prev[0] === 'space') { + prev = params[--shift]; + } + if (prev) { + node.source.end = this.getPosition(prev[3] || prev[2]); + node.source.end.offset++; + } + } + this.end(token); + break + } else { + params.push(token); + } + } else { + params.push(token); + } + + if (this.tokenizer.endOfFile()) { + last = true; + break + } + } + + node.raws.between = this.spacesAndCommentsFromEnd(params); + if (params.length) { + node.raws.afterName = this.spacesAndCommentsFromStart(params); + this.raw(node, 'params', params); + if (last) { + token = params[params.length - 1]; + node.source.end = this.getPosition(token[3] || token[2]); + node.source.end.offset++; + this.spaces = node.raws.between; + node.raws.between = ''; + } + } else { + node.raws.afterName = ''; + node.params = ''; + } + + if (open) { + node.nodes = []; + this.current = node; + } + } + + checkMissedSemicolon(tokens) { + let colon = this.colon(tokens); + if (colon === false) return + + let founded = 0; + let token; + for (let j = colon - 1; j >= 0; j--) { + token = tokens[j]; + if (token[0] !== 'space') { + founded += 1; + if (founded === 2) break + } + } + // If the token is a word, e.g. `!important`, `red` or any other valid property's value. + // Then we need to return the colon after that word token. [3] is the "end" colon of that word. + // And because we need it after that one we do +1 to get the next one. + throw this.input.error( + 'Missed semicolon', + token[0] === 'word' ? token[3] + 1 : token[2] + ) + } + + colon(tokens) { + let brackets = 0; + let token, type, prev; + for (let [i, element] of tokens.entries()) { + token = element; + type = token[0]; + + if (type === '(') { + brackets += 1; + } + if (type === ')') { + brackets -= 1; + } + if (brackets === 0 && type === ':') { + if (!prev) { + this.doubleColon(token); + } else if (prev[0] === 'word' && prev[1] === 'progid') { + continue + } else { + return i + } + } + + prev = token; + } + return false + } + + comment(token) { + let node = new Comment$2(); + this.init(node, token[2]); + node.source.end = this.getPosition(token[3] || token[2]); + node.source.end.offset++; + + let text = token[1].slice(2, -2); + if (/^\s*$/.test(text)) { + node.text = ''; + node.raws.left = text; + node.raws.right = ''; + } else { + let match = text.match(/^(\s*)([^]*\S)(\s*)$/); + node.text = match[2]; + node.raws.left = match[1]; + node.raws.right = match[3]; + } + } + + createTokenizer() { + this.tokenizer = tokenizer(this.input); + } + + decl(tokens, customProperty) { + let node = new Declaration$2(); + this.init(node, tokens[0][2]); + + let last = tokens[tokens.length - 1]; + if (last[0] === ';') { + this.semicolon = true; + tokens.pop(); + } + + node.source.end = this.getPosition( + last[3] || last[2] || findLastWithPosition(tokens) + ); + node.source.end.offset++; + + while (tokens[0][0] !== 'word') { + if (tokens.length === 1) this.unknownWord(tokens); + node.raws.before += tokens.shift()[1]; + } + node.source.start = this.getPosition(tokens[0][2]); + + node.prop = ''; + while (tokens.length) { + let type = tokens[0][0]; + if (type === ':' || type === 'space' || type === 'comment') { + break + } + node.prop += tokens.shift()[1]; + } + + node.raws.between = ''; + + let token; + while (tokens.length) { + token = tokens.shift(); + + if (token[0] === ':') { + node.raws.between += token[1]; + break + } else { + if (token[0] === 'word' && /\w/.test(token[1])) { + this.unknownWord([token]); + } + node.raws.between += token[1]; + } + } + + if (node.prop[0] === '_' || node.prop[0] === '*') { + node.raws.before += node.prop[0]; + node.prop = node.prop.slice(1); + } + + let firstSpaces = []; + let next; + while (tokens.length) { + next = tokens[0][0]; + if (next !== 'space' && next !== 'comment') break + firstSpaces.push(tokens.shift()); + } + + this.precheckMissedSemicolon(tokens); + + for (let i = tokens.length - 1; i >= 0; i--) { + token = tokens[i]; + if (token[1].toLowerCase() === '!important') { + node.important = true; + let string = this.stringFrom(tokens, i); + string = this.spacesFromEnd(tokens) + string; + if (string !== ' !important') node.raws.important = string; + break + } else if (token[1].toLowerCase() === 'important') { + let cache = tokens.slice(0); + let str = ''; + for (let j = i; j > 0; j--) { + let type = cache[j][0]; + if (str.trim().indexOf('!') === 0 && type !== 'space') { + break + } + str = cache.pop()[1] + str; + } + if (str.trim().indexOf('!') === 0) { + node.important = true; + node.raws.important = str; + tokens = cache; + } + } + + if (token[0] !== 'space' && token[0] !== 'comment') { + break + } + } + + let hasWord = tokens.some(i => i[0] !== 'space' && i[0] !== 'comment'); + + if (hasWord) { + node.raws.between += firstSpaces.map(i => i[1]).join(''); + firstSpaces = []; + } + this.raw(node, 'value', firstSpaces.concat(tokens), customProperty); + + if (node.value.includes(':') && !customProperty) { + this.checkMissedSemicolon(tokens); + } + } + + doubleColon(token) { + throw this.input.error( + 'Double colon', + { offset: token[2] }, + { offset: token[2] + token[1].length } + ) + } + + emptyRule(token) { + let node = new Rule$2(); + this.init(node, token[2]); + node.selector = ''; + node.raws.between = ''; + this.current = node; + } + + end(token) { + if (this.current.nodes && this.current.nodes.length) { + this.current.raws.semicolon = this.semicolon; + } + this.semicolon = false; + + this.current.raws.after = (this.current.raws.after || '') + this.spaces; + this.spaces = ''; + + if (this.current.parent) { + this.current.source.end = this.getPosition(token[2]); + this.current.source.end.offset++; + this.current = this.current.parent; + } else { + this.unexpectedClose(token); + } + } + + endFile() { + if (this.current.parent) this.unclosedBlock(); + if (this.current.nodes && this.current.nodes.length) { + this.current.raws.semicolon = this.semicolon; + } + this.current.raws.after = (this.current.raws.after || '') + this.spaces; + this.root.source.end = this.getPosition(this.tokenizer.position()); + } + + freeSemicolon(token) { + this.spaces += token[1]; + if (this.current.nodes) { + let prev = this.current.nodes[this.current.nodes.length - 1]; + if (prev && prev.type === 'rule' && !prev.raws.ownSemicolon) { + prev.raws.ownSemicolon = this.spaces; + this.spaces = ''; + } + } + } + + // Helpers + + getPosition(offset) { + let pos = this.input.fromOffset(offset); + return { + column: pos.col, + line: pos.line, + offset + } + } + + init(node, offset) { + this.current.push(node); + node.source = { + input: this.input, + start: this.getPosition(offset) + }; + node.raws.before = this.spaces; + this.spaces = ''; + if (node.type !== 'comment') this.semicolon = false; + } + + other(start) { + let end = false; + let type = null; + let colon = false; + let bracket = null; + let brackets = []; + let customProperty = start[1].startsWith('--'); + + let tokens = []; + let token = start; + while (token) { + type = token[0]; + tokens.push(token); + + if (type === '(' || type === '[') { + if (!bracket) bracket = token; + brackets.push(type === '(' ? ')' : ']'); + } else if (customProperty && colon && type === '{') { + if (!bracket) bracket = token; + brackets.push('}'); + } else if (brackets.length === 0) { + if (type === ';') { + if (colon) { + this.decl(tokens, customProperty); + return + } else { + break + } + } else if (type === '{') { + this.rule(tokens); + return + } else if (type === '}') { + this.tokenizer.back(tokens.pop()); + end = true; + break + } else if (type === ':') { + colon = true; + } + } else if (type === brackets[brackets.length - 1]) { + brackets.pop(); + if (brackets.length === 0) bracket = null; + } + + token = this.tokenizer.nextToken(); + } + + if (this.tokenizer.endOfFile()) end = true; + if (brackets.length > 0) this.unclosedBracket(bracket); + + if (end && colon) { + if (!customProperty) { + while (tokens.length) { + token = tokens[tokens.length - 1][0]; + if (token !== 'space' && token !== 'comment') break + this.tokenizer.back(tokens.pop()); + } + } + this.decl(tokens, customProperty); + } else { + this.unknownWord(tokens); + } + } + + parse() { + let token; + while (!this.tokenizer.endOfFile()) { + token = this.tokenizer.nextToken(); + + switch (token[0]) { + case 'space': + this.spaces += token[1]; + break + + case ';': + this.freeSemicolon(token); + break + + case '}': + this.end(token); + break + + case 'comment': + this.comment(token); + break + + case 'at-word': + this.atrule(token); + break + + case '{': + this.emptyRule(token); + break + + default: + this.other(token); + break + } + } + this.endFile(); + } + + precheckMissedSemicolon(/* tokens */) { + // Hook for Safe Parser + } + + raw(node, prop, tokens, customProperty) { + let token, type; + let length = tokens.length; + let value = ''; + let clean = true; + let next, prev; + + for (let i = 0; i < length; i += 1) { + token = tokens[i]; + type = token[0]; + if (type === 'space' && i === length - 1 && !customProperty) { + clean = false; + } else if (type === 'comment') { + prev = tokens[i - 1] ? tokens[i - 1][0] : 'empty'; + next = tokens[i + 1] ? tokens[i + 1][0] : 'empty'; + if (!SAFE_COMMENT_NEIGHBOR[prev] && !SAFE_COMMENT_NEIGHBOR[next]) { + if (value.slice(-1) === ',') { + clean = false; + } else { + value += token[1]; + } + } else { + clean = false; + } + } else { + value += token[1]; + } + } + if (!clean) { + let raw = tokens.reduce((all, i) => all + i[1], ''); + node.raws[prop] = { raw, value }; + } + node[prop] = value; + } + + rule(tokens) { + tokens.pop(); + + let node = new Rule$2(); + this.init(node, tokens[0][2]); + + node.raws.between = this.spacesAndCommentsFromEnd(tokens); + this.raw(node, 'selector', tokens); + this.current = node; + } + + spacesAndCommentsFromEnd(tokens) { + let lastTokenType; + let spaces = ''; + while (tokens.length) { + lastTokenType = tokens[tokens.length - 1][0]; + if (lastTokenType !== 'space' && lastTokenType !== 'comment') break + spaces = tokens.pop()[1] + spaces; + } + return spaces + } + + // Errors + + spacesAndCommentsFromStart(tokens) { + let next; + let spaces = ''; + while (tokens.length) { + next = tokens[0][0]; + if (next !== 'space' && next !== 'comment') break + spaces += tokens.shift()[1]; + } + return spaces + } + + spacesFromEnd(tokens) { + let lastTokenType; + let spaces = ''; + while (tokens.length) { + lastTokenType = tokens[tokens.length - 1][0]; + if (lastTokenType !== 'space') break + spaces = tokens.pop()[1] + spaces; + } + return spaces + } + + stringFrom(tokens, from) { + let result = ''; + for (let i = from; i < tokens.length; i++) { + result += tokens[i][1]; + } + tokens.splice(from, tokens.length - from); + return result + } + + unclosedBlock() { + let pos = this.current.source.start; + throw this.input.error('Unclosed block', pos.line, pos.column) + } + + unclosedBracket(bracket) { + throw this.input.error( + 'Unclosed bracket', + { offset: bracket[2] }, + { offset: bracket[2] + 1 } + ) + } + + unexpectedClose(token) { + throw this.input.error( + 'Unexpected }', + { offset: token[2] }, + { offset: token[2] + 1 } + ) + } + + unknownWord(tokens) { + throw this.input.error( + 'Unknown word', + { offset: tokens[0][2] }, + { offset: tokens[0][2] + tokens[0][1].length } + ) + } + + unnamedAtrule(node, token) { + throw this.input.error( + 'At-rule without name', + { offset: token[2] }, + { offset: token[2] + token[1].length } + ) + } + }; + + var parser = Parser$1; + + let Container$2 = container; + let Parser = parser; + let Input$2 = input; + + function parse$3(css, opts) { + let input = new Input$2(css, opts); + let parser = new Parser(input); + try { + parser.parse(); + } catch (e) { + if (browser$1.env.NODE_ENV !== 'production') { + if (e.name === 'CssSyntaxError' && opts && opts.from) { + if (/\.scss$/i.test(opts.from)) { + e.message += + '\nYou tried to parse SCSS with ' + + 'the standard CSS parser; ' + + 'try again with the postcss-scss parser'; + } else if (/\.sass/i.test(opts.from)) { + e.message += + '\nYou tried to parse Sass with ' + + 'the standard CSS parser; ' + + 'try again with the postcss-sass parser'; + } else if (/\.less$/i.test(opts.from)) { + e.message += + '\nYou tried to parse Less with ' + + 'the standard CSS parser; ' + + 'try again with the postcss-less parser'; + } + } + } + throw e + } + + return parser.root + } + + var parse_1 = parse$3; + parse$3.default = parse$3; + + Container$2.registerParse(parse$3); + + let { isClean, my } = symbols; + let MapGenerator$1 = mapGenerator; + let stringify$2 = stringify_1; + let Container$1 = container; + let Document$2 = document; + let warnOnce$1 = warnOnce$2; + let Result$2 = result; + let parse$2 = parse_1; + let Root$3 = root; + + const TYPE_TO_CLASS_NAME = { + atrule: 'AtRule', + comment: 'Comment', + decl: 'Declaration', + document: 'Document', + root: 'Root', + rule: 'Rule' + }; + + const PLUGIN_PROPS = { + AtRule: true, + AtRuleExit: true, + Comment: true, + CommentExit: true, + Declaration: true, + DeclarationExit: true, + Document: true, + DocumentExit: true, + Once: true, + OnceExit: true, + postcssPlugin: true, + prepare: true, + Root: true, + RootExit: true, + Rule: true, + RuleExit: true + }; + + const NOT_VISITORS = { + Once: true, + postcssPlugin: true, + prepare: true + }; + + const CHILDREN = 0; + + function isPromise(obj) { + return typeof obj === 'object' && typeof obj.then === 'function' + } + + function getEvents(node) { + let key = false; + let type = TYPE_TO_CLASS_NAME[node.type]; + if (node.type === 'decl') { + key = node.prop.toLowerCase(); + } else if (node.type === 'atrule') { + key = node.name.toLowerCase(); + } + + if (key && node.append) { + return [ + type, + type + '-' + key, + CHILDREN, + type + 'Exit', + type + 'Exit-' + key + ] + } else if (key) { + return [type, type + '-' + key, type + 'Exit', type + 'Exit-' + key] + } else if (node.append) { + return [type, CHILDREN, type + 'Exit'] + } else { + return [type, type + 'Exit'] + } + } + + function toStack(node) { + let events; + if (node.type === 'document') { + events = ['Document', CHILDREN, 'DocumentExit']; + } else if (node.type === 'root') { + events = ['Root', CHILDREN, 'RootExit']; + } else { + events = getEvents(node); + } + + return { + eventIndex: 0, + events, + iterator: 0, + node, + visitorIndex: 0, + visitors: [] + } + } + + function cleanMarks(node) { + node[isClean] = false; + if (node.nodes) node.nodes.forEach(i => cleanMarks(i)); + return node + } + + let postcss$1 = {}; + + let LazyResult$2 = class LazyResult { + constructor(processor, css, opts) { + this.stringified = false; + this.processed = false; + + let root; + if ( + typeof css === 'object' && + css !== null && + (css.type === 'root' || css.type === 'document') + ) { + root = cleanMarks(css); + } else if (css instanceof LazyResult || css instanceof Result$2) { + root = cleanMarks(css.root); + if (css.map) { + if (typeof opts.map === 'undefined') opts.map = {}; + if (!opts.map.inline) opts.map.inline = false; + opts.map.prev = css.map; + } + } else { + let parser = parse$2; + if (opts.syntax) parser = opts.syntax.parse; + if (opts.parser) parser = opts.parser; + if (parser.parse) parser = parser.parse; + + try { + root = parser(css, opts); + } catch (error) { + this.processed = true; + this.error = error; + } + + if (root && !root[my]) { + /* c8 ignore next 2 */ + Container$1.rebuild(root); + } + } + + this.result = new Result$2(processor, root, opts); + this.helpers = { ...postcss$1, postcss: postcss$1, result: this.result }; + this.plugins = this.processor.plugins.map(plugin => { + if (typeof plugin === 'object' && plugin.prepare) { + return { ...plugin, ...plugin.prepare(this.result) } + } else { + return plugin + } + }); + } + + async() { + if (this.error) return Promise.reject(this.error) + if (this.processed) return Promise.resolve(this.result) + if (!this.processing) { + this.processing = this.runAsync(); + } + return this.processing + } + + catch(onRejected) { + return this.async().catch(onRejected) + } + + finally(onFinally) { + return this.async().then(onFinally, onFinally) + } + + getAsyncError() { + throw new Error('Use process(css).then(cb) to work with async plugins') + } + + handleError(error, node) { + let plugin = this.result.lastPlugin; + try { + if (node) node.addToError(error); + this.error = error; + if (error.name === 'CssSyntaxError' && !error.plugin) { + error.plugin = plugin.postcssPlugin; + error.setMessage(); + } else if (plugin.postcssVersion) { + if (browser$1.env.NODE_ENV !== 'production') { + let pluginName = plugin.postcssPlugin; + let pluginVer = plugin.postcssVersion; + let runtimeVer = this.result.processor.version; + let a = pluginVer.split('.'); + let b = runtimeVer.split('.'); + + if (a[0] !== b[0] || parseInt(a[1]) > parseInt(b[1])) { + // eslint-disable-next-line no-console + console.error( + 'Unknown error from PostCSS plugin. Your current PostCSS ' + + 'version is ' + + runtimeVer + + ', but ' + + pluginName + + ' uses ' + + pluginVer + + '. Perhaps this is the source of the error below.' + ); + } + } + } + } catch (err) { + /* c8 ignore next 3 */ + // eslint-disable-next-line no-console + if (console && console.error) console.error(err); + } + return error + } + + prepareVisitors() { + this.listeners = {}; + let add = (plugin, type, cb) => { + if (!this.listeners[type]) this.listeners[type] = []; + this.listeners[type].push([plugin, cb]); + }; + for (let plugin of this.plugins) { + if (typeof plugin === 'object') { + for (let event in plugin) { + if (!PLUGIN_PROPS[event] && /^[A-Z]/.test(event)) { + throw new Error( + `Unknown event ${event} in ${plugin.postcssPlugin}. ` + + `Try to update PostCSS (${this.processor.version} now).` + ) + } + if (!NOT_VISITORS[event]) { + if (typeof plugin[event] === 'object') { + for (let filter in plugin[event]) { + if (filter === '*') { + add(plugin, event, plugin[event][filter]); + } else { + add( + plugin, + event + '-' + filter.toLowerCase(), + plugin[event][filter] + ); + } + } + } else if (typeof plugin[event] === 'function') { + add(plugin, event, plugin[event]); + } + } + } + } + } + this.hasListener = Object.keys(this.listeners).length > 0; + } + + async runAsync() { + this.plugin = 0; + for (let i = 0; i < this.plugins.length; i++) { + let plugin = this.plugins[i]; + let promise = this.runOnRoot(plugin); + if (isPromise(promise)) { + try { + await promise; + } catch (error) { + throw this.handleError(error) + } + } + } + + this.prepareVisitors(); + if (this.hasListener) { + let root = this.result.root; + while (!root[isClean]) { + root[isClean] = true; + let stack = [toStack(root)]; + while (stack.length > 0) { + let promise = this.visitTick(stack); + if (isPromise(promise)) { + try { + await promise; + } catch (e) { + let node = stack[stack.length - 1].node; + throw this.handleError(e, node) + } + } + } + } + + if (this.listeners.OnceExit) { + for (let [plugin, visitor] of this.listeners.OnceExit) { + this.result.lastPlugin = plugin; + try { + if (root.type === 'document') { + let roots = root.nodes.map(subRoot => + visitor(subRoot, this.helpers) + ); + + await Promise.all(roots); + } else { + await visitor(root, this.helpers); + } + } catch (e) { + throw this.handleError(e) + } + } + } + } + + this.processed = true; + return this.stringify() + } + + runOnRoot(plugin) { + this.result.lastPlugin = plugin; + try { + if (typeof plugin === 'object' && plugin.Once) { + if (this.result.root.type === 'document') { + let roots = this.result.root.nodes.map(root => + plugin.Once(root, this.helpers) + ); + + if (isPromise(roots[0])) { + return Promise.all(roots) + } + + return roots + } + + return plugin.Once(this.result.root, this.helpers) + } else if (typeof plugin === 'function') { + return plugin(this.result.root, this.result) + } + } catch (error) { + throw this.handleError(error) + } + } + + stringify() { + if (this.error) throw this.error + if (this.stringified) return this.result + this.stringified = true; + + this.sync(); + + let opts = this.result.opts; + let str = stringify$2; + if (opts.syntax) str = opts.syntax.stringify; + if (opts.stringifier) str = opts.stringifier; + if (str.stringify) str = str.stringify; + + let map = new MapGenerator$1(str, this.result.root, this.result.opts); + let data = map.generate(); + this.result.css = data[0]; + this.result.map = data[1]; + + return this.result + } + + sync() { + if (this.error) throw this.error + if (this.processed) return this.result + this.processed = true; + + if (this.processing) { + throw this.getAsyncError() + } + + for (let plugin of this.plugins) { + let promise = this.runOnRoot(plugin); + if (isPromise(promise)) { + throw this.getAsyncError() + } + } + + this.prepareVisitors(); + if (this.hasListener) { + let root = this.result.root; + while (!root[isClean]) { + root[isClean] = true; + this.walkSync(root); + } + if (this.listeners.OnceExit) { + if (root.type === 'document') { + for (let subRoot of root.nodes) { + this.visitSync(this.listeners.OnceExit, subRoot); + } + } else { + this.visitSync(this.listeners.OnceExit, root); + } + } + } + + return this.result + } + + then(onFulfilled, onRejected) { + if (browser$1.env.NODE_ENV !== 'production') { + if (!('from' in this.opts)) { + warnOnce$1( + 'Without `from` option PostCSS could generate wrong source map ' + + 'and will not find Browserslist config. Set it to CSS file path ' + + 'or to `undefined` to prevent this warning.' + ); + } + } + return this.async().then(onFulfilled, onRejected) + } + + toString() { + return this.css + } + + visitSync(visitors, node) { + for (let [plugin, visitor] of visitors) { + this.result.lastPlugin = plugin; + let promise; + try { + promise = visitor(node, this.helpers); + } catch (e) { + throw this.handleError(e, node.proxyOf) + } + if (node.type !== 'root' && node.type !== 'document' && !node.parent) { + return true + } + if (isPromise(promise)) { + throw this.getAsyncError() + } + } + } + + visitTick(stack) { + let visit = stack[stack.length - 1]; + let { node, visitors } = visit; + + if (node.type !== 'root' && node.type !== 'document' && !node.parent) { + stack.pop(); + return + } + + if (visitors.length > 0 && visit.visitorIndex < visitors.length) { + let [plugin, visitor] = visitors[visit.visitorIndex]; + visit.visitorIndex += 1; + if (visit.visitorIndex === visitors.length) { + visit.visitors = []; + visit.visitorIndex = 0; + } + this.result.lastPlugin = plugin; + try { + return visitor(node.toProxy(), this.helpers) + } catch (e) { + throw this.handleError(e, node) + } + } + + if (visit.iterator !== 0) { + let iterator = visit.iterator; + let child; + while ((child = node.nodes[node.indexes[iterator]])) { + node.indexes[iterator] += 1; + if (!child[isClean]) { + child[isClean] = true; + stack.push(toStack(child)); + return + } + } + visit.iterator = 0; + delete node.indexes[iterator]; + } + + let events = visit.events; + while (visit.eventIndex < events.length) { + let event = events[visit.eventIndex]; + visit.eventIndex += 1; + if (event === CHILDREN) { + if (node.nodes && node.nodes.length) { + node[isClean] = true; + visit.iterator = node.getIterator(); + } + return + } else if (this.listeners[event]) { + visit.visitors = this.listeners[event]; + return + } + } + stack.pop(); + } + + walkSync(node) { + node[isClean] = true; + let events = getEvents(node); + for (let event of events) { + if (event === CHILDREN) { + if (node.nodes) { + node.each(child => { + if (!child[isClean]) this.walkSync(child); + }); + } + } else { + let visitors = this.listeners[event]; + if (visitors) { + if (this.visitSync(visitors, node.toProxy())) return + } + } + } + } + + warnings() { + return this.sync().warnings() + } + + get content() { + return this.stringify().content + } + + get css() { + return this.stringify().css + } + + get map() { + return this.stringify().map + } + + get messages() { + return this.sync().messages + } + + get opts() { + return this.result.opts + } + + get processor() { + return this.result.processor + } + + get root() { + return this.sync().root + } + + get [Symbol.toStringTag]() { + return 'LazyResult' + } + }; + + LazyResult$2.registerPostcss = dependant => { + postcss$1 = dependant; + }; + + var lazyResult = LazyResult$2; + LazyResult$2.default = LazyResult$2; + + Root$3.registerLazyResult(LazyResult$2); + Document$2.registerLazyResult(LazyResult$2); + + let MapGenerator = mapGenerator; + let stringify$1 = stringify_1; + let warnOnce = warnOnce$2; + let parse$1 = parse_1; + const Result$1 = result; + + let NoWorkResult$1 = class NoWorkResult { + constructor(processor, css, opts) { + css = css.toString(); + this.stringified = false; + + this._processor = processor; + this._css = css; + this._opts = opts; + this._map = undefined; + let root; + + let str = stringify$1; + this.result = new Result$1(this._processor, root, this._opts); + this.result.css = css; + + let self = this; + Object.defineProperty(this.result, 'root', { + get() { + return self.root + } + }); + + let map = new MapGenerator(str, root, this._opts, css); + if (map.isMap()) { + let [generatedCSS, generatedMap] = map.generate(); + if (generatedCSS) { + this.result.css = generatedCSS; + } + if (generatedMap) { + this.result.map = generatedMap; + } + } else { + map.clearAnnotation(); + this.result.css = map.css; + } + } + + async() { + if (this.error) return Promise.reject(this.error) + return Promise.resolve(this.result) + } + + catch(onRejected) { + return this.async().catch(onRejected) + } + + finally(onFinally) { + return this.async().then(onFinally, onFinally) + } + + sync() { + if (this.error) throw this.error + return this.result + } + + then(onFulfilled, onRejected) { + if (browser$1.env.NODE_ENV !== 'production') { + if (!('from' in this._opts)) { + warnOnce( + 'Without `from` option PostCSS could generate wrong source map ' + + 'and will not find Browserslist config. Set it to CSS file path ' + + 'or to `undefined` to prevent this warning.' + ); + } + } + + return this.async().then(onFulfilled, onRejected) + } + + toString() { + return this._css + } + + warnings() { + return [] + } + + get content() { + return this.result.css + } + + get css() { + return this.result.css + } + + get map() { + return this.result.map + } + + get messages() { + return [] + } + + get opts() { + return this.result.opts + } + + get processor() { + return this.result.processor + } + + get root() { + if (this._root) { + return this._root + } + + let root; + let parser = parse$1; + + try { + root = parser(this._css, this._opts); + } catch (error) { + this.error = error; + } + + if (this.error) { + throw this.error + } else { + this._root = root; + return root + } + } + + get [Symbol.toStringTag]() { + return 'NoWorkResult' + } + }; + + var noWorkResult = NoWorkResult$1; + NoWorkResult$1.default = NoWorkResult$1; + + let NoWorkResult = noWorkResult; + let LazyResult$1 = lazyResult; + let Document$1 = document; + let Root$2 = root; + + let Processor$1 = class Processor { + constructor(plugins = []) { + this.version = '8.4.38'; + this.plugins = this.normalize(plugins); + } + + normalize(plugins) { + let normalized = []; + for (let i of plugins) { + if (i.postcss === true) { + i = i(); + } else if (i.postcss) { + i = i.postcss; + } + + if (typeof i === 'object' && Array.isArray(i.plugins)) { + normalized = normalized.concat(i.plugins); + } else if (typeof i === 'object' && i.postcssPlugin) { + normalized.push(i); + } else if (typeof i === 'function') { + normalized.push(i); + } else if (typeof i === 'object' && (i.parse || i.stringify)) { + if (browser$1.env.NODE_ENV !== 'production') { + throw new Error( + 'PostCSS syntaxes cannot be used as plugins. Instead, please use ' + + 'one of the syntax/parser/stringifier options as outlined ' + + 'in your PostCSS runner documentation.' + ) + } + } else { + throw new Error(i + ' is not a PostCSS plugin') + } + } + return normalized + } + + process(css, opts = {}) { + if ( + !this.plugins.length && + !opts.parser && + !opts.stringifier && + !opts.syntax + ) { + return new NoWorkResult(this, css, opts) + } else { + return new LazyResult$1(this, css, opts) + } + } + + use(plugin) { + this.plugins = this.plugins.concat(this.normalize([plugin])); + return this + } + }; + + var processor = Processor$1; + Processor$1.default = Processor$1; + + Root$2.registerProcessor(Processor$1); + Document$1.registerProcessor(Processor$1); + + let Declaration$1 = declaration; + let PreviousMap = previousMap; + let Comment$1 = comment; + let AtRule$1 = atRule; + let Input$1 = input; + let Root$1 = root; + let Rule$1 = rule; + + function fromJSON$1(json, inputs) { + if (Array.isArray(json)) return json.map(n => fromJSON$1(n)) + + let { inputs: ownInputs, ...defaults } = json; + if (ownInputs) { + inputs = []; + for (let input of ownInputs) { + let inputHydrated = { ...input, __proto__: Input$1.prototype }; + if (inputHydrated.map) { + inputHydrated.map = { + ...inputHydrated.map, + __proto__: PreviousMap.prototype + }; + } + inputs.push(inputHydrated); + } + } + if (defaults.nodes) { + defaults.nodes = json.nodes.map(n => fromJSON$1(n, inputs)); + } + if (defaults.source) { + let { inputId, ...source } = defaults.source; + defaults.source = source; + if (inputId != null) { + defaults.source.input = inputs[inputId]; + } + } + if (defaults.type === 'root') { + return new Root$1(defaults) + } else if (defaults.type === 'decl') { + return new Declaration$1(defaults) + } else if (defaults.type === 'rule') { + return new Rule$1(defaults) + } else if (defaults.type === 'comment') { + return new Comment$1(defaults) + } else if (defaults.type === 'atrule') { + return new AtRule$1(defaults) + } else { + throw new Error('Unknown node type: ' + json.type) + } + } + + var fromJSON_1 = fromJSON$1; + fromJSON$1.default = fromJSON$1; + + let CssSyntaxError = cssSyntaxError; + let Declaration = declaration; + let LazyResult = lazyResult; + let Container = container; + let Processor = processor; + let stringify = stringify_1; + let fromJSON = fromJSON_1; + let Document = document; + let Warning = warning; + let Comment = comment; + let AtRule = atRule; + let Result = result; + let Input = input; + let parse = parse_1; + let list = list_1; + let Rule = rule; + let Root = root; + let Node = node; + + function postcss(...plugins) { + if (plugins.length === 1 && Array.isArray(plugins[0])) { + plugins = plugins[0]; + } + return new Processor(plugins) + } + + postcss.plugin = function plugin(name, initializer) { + let warningPrinted = false; + function creator(...args) { + // eslint-disable-next-line no-console + if (console && console.warn && !warningPrinted) { + warningPrinted = true; + // eslint-disable-next-line no-console + console.warn( + name + + ': postcss.plugin was deprecated. Migration guide:\n' + + 'https://evilmartians.com/chronicles/postcss-8-plugin-migration' + ); + if (browser$1.env.LANG && browser$1.env.LANG.startsWith('cn')) { + /* c8 ignore next 7 */ + // eslint-disable-next-line no-console + console.warn( + name + + ': 里面 postcss.plugin 被弃用. 迁移指南:\n' + + 'https://www.w3ctech.com/topic/2226' + ); + } + } + let transformer = initializer(...args); + transformer.postcssPlugin = name; + transformer.postcssVersion = new Processor().version; + return transformer + } + + let cache; + Object.defineProperty(creator, 'postcss', { + get() { + if (!cache) cache = creator(); + return cache + } + }); + + creator.process = function (css, processOpts, pluginOpts) { + return postcss([creator(pluginOpts)]).process(css, processOpts) + }; + + return creator + }; + + postcss.stringify = stringify; + postcss.parse = parse; + postcss.fromJSON = fromJSON; + postcss.list = list; + + postcss.comment = defaults => new Comment(defaults); + postcss.atRule = defaults => new AtRule(defaults); + postcss.decl = defaults => new Declaration(defaults); + postcss.rule = defaults => new Rule(defaults); + postcss.root = defaults => new Root(defaults); + postcss.document = defaults => new Document(defaults); + + postcss.CssSyntaxError = CssSyntaxError; + postcss.Declaration = Declaration; + postcss.Container = Container; + postcss.Processor = Processor; + postcss.Document = Document; + postcss.Comment = Comment; + postcss.Warning = Warning; + postcss.AtRule = AtRule; + postcss.Result = Result; + postcss.Input = Input; + postcss.Rule = Rule; + postcss.Root = Root; + postcss.Node = Node; + + LazyResult.registerPostcss(postcss); + + var postcss_1 = postcss; + postcss.default = postcss; + + const htmlparser = lib$5; + const escapeStringRegexp = escapeStringRegexp$1; + const { isPlainObject } = isPlainObject$2; + const deepmerge = cjs; + const parseSrcset = parseSrcsetExports; + const { parse: postcssParse } = postcss_1; + // Tags that can conceivably represent stand-alone media. + const mediaTags = [ + 'img', 'audio', 'video', 'picture', 'svg', + 'object', 'map', 'iframe', 'embed' + ]; + // Tags that are inherently vulnerable to being used in XSS attacks. + const vulnerableTags = [ 'script', 'style' ]; + + function each(obj, cb) { + if (obj) { + Object.keys(obj).forEach(function (key) { + cb(obj[key], key); + }); + } + } + + // Avoid false positives with .__proto__, .hasOwnProperty, etc. + function has(obj, key) { + return ({}).hasOwnProperty.call(obj, key); + } + + // Returns those elements of `a` for which `cb(a)` returns truthy + function filter(a, cb) { + const n = []; + each(a, function(v) { + if (cb(v)) { + n.push(v); + } + }); + return n; + } + + function isEmptyObject(obj) { + for (const key in obj) { + if (has(obj, key)) { + return false; + } + } + return true; + } + + function stringifySrcset(parsedSrcset) { + return parsedSrcset.map(function(part) { + if (!part.url) { + throw new Error('URL missing'); + } + + return ( + part.url + + (part.w ? ` ${part.w}w` : '') + + (part.h ? ` ${part.h}h` : '') + + (part.d ? ` ${part.d}x` : '') + ); + }).join(', '); + } + + var sanitizeHtml_1 = sanitizeHtml; + + // A valid attribute name. + // We use a tolerant definition based on the set of strings defined by + // html.spec.whatwg.org/multipage/parsing.html#before-attribute-name-state + // and html.spec.whatwg.org/multipage/parsing.html#attribute-name-state . + // The characters accepted are ones which can be appended to the attribute + // name buffer without triggering a parse error: + // * unexpected-equals-sign-before-attribute-name + // * unexpected-null-character + // * unexpected-character-in-attribute-name + // We exclude the empty string because it's impossible to get to the after + // attribute name state with an empty attribute name buffer. + const VALID_HTML_ATTRIBUTE_NAME = /^[^\0\t\n\f\r /<=>]+$/; + + // Ignore the _recursing flag; it's there for recursive + // invocation as a guard against this exploit: + // https://github.com/fb55/htmlparser2/issues/105 + + function sanitizeHtml(html, options, _recursing) { + if (html == null) { + return ''; + } + if (typeof html === 'number') { + html = html.toString(); + } + + let result = ''; + // Used for hot swapping the result variable with an empty string in order to "capture" the text written to it. + let tempResult = ''; + + function Frame(tag, attribs) { + const that = this; + this.tag = tag; + this.attribs = attribs || {}; + this.tagPosition = result.length; + this.text = ''; // Node inner text + this.mediaChildren = []; + + this.updateParentNodeText = function() { + if (stack.length) { + const parentFrame = stack[stack.length - 1]; + parentFrame.text += that.text; + } + }; + + this.updateParentNodeMediaChildren = function() { + if (stack.length && mediaTags.includes(this.tag)) { + const parentFrame = stack[stack.length - 1]; + parentFrame.mediaChildren.push(this.tag); + } + }; + } + + options = Object.assign({}, sanitizeHtml.defaults, options); + options.parser = Object.assign({}, htmlParserDefaults, options.parser); + + const tagAllowed = function (name) { + return options.allowedTags === false || (options.allowedTags || []).indexOf(name) > -1; + }; + + // vulnerableTags + vulnerableTags.forEach(function (tag) { + if (tagAllowed(tag) && !options.allowVulnerableTags) { + console.warn(`\n\n⚠️ Your \`allowedTags\` option includes, \`${tag}\`, which is inherently\nvulnerable to XSS attacks. Please remove it from \`allowedTags\`.\nOr, to disable this warning, add the \`allowVulnerableTags\` option\nand ensure you are accounting for this risk.\n\n`); + } + }); + + // Tags that contain something other than HTML, or where discarding + // the text when the tag is disallowed makes sense for other reasons. + // If we are not allowing these tags, we should drop their content too. + // For other tags you would drop the tag but keep its content. + const nonTextTagsArray = options.nonTextTags || [ + 'script', + 'style', + 'textarea', + 'option' + ]; + let allowedAttributesMap; + let allowedAttributesGlobMap; + if (options.allowedAttributes) { + allowedAttributesMap = {}; + allowedAttributesGlobMap = {}; + each(options.allowedAttributes, function(attributes, tag) { + allowedAttributesMap[tag] = []; + const globRegex = []; + attributes.forEach(function(obj) { + if (typeof obj === 'string' && obj.indexOf('*') >= 0) { + globRegex.push(escapeStringRegexp(obj).replace(/\\\*/g, '.*')); + } else { + allowedAttributesMap[tag].push(obj); + } + }); + if (globRegex.length) { + allowedAttributesGlobMap[tag] = new RegExp('^(' + globRegex.join('|') + ')$'); + } + }); + } + const allowedClassesMap = {}; + const allowedClassesGlobMap = {}; + const allowedClassesRegexMap = {}; + each(options.allowedClasses, function(classes, tag) { + // Implicitly allows the class attribute + if (allowedAttributesMap) { + if (!has(allowedAttributesMap, tag)) { + allowedAttributesMap[tag] = []; + } + allowedAttributesMap[tag].push('class'); + } + + allowedClassesMap[tag] = classes; + + if (Array.isArray(classes)) { + const globRegex = []; + allowedClassesMap[tag] = []; + allowedClassesRegexMap[tag] = []; + classes.forEach(function(obj) { + if (typeof obj === 'string' && obj.indexOf('*') >= 0) { + globRegex.push(escapeStringRegexp(obj).replace(/\\\*/g, '.*')); + } else if (obj instanceof RegExp) { + allowedClassesRegexMap[tag].push(obj); + } else { + allowedClassesMap[tag].push(obj); + } + }); + if (globRegex.length) { + allowedClassesGlobMap[tag] = new RegExp('^(' + globRegex.join('|') + ')$'); + } + } + }); + + const transformTagsMap = {}; + let transformTagsAll; + each(options.transformTags, function(transform, tag) { + let transFun; + if (typeof transform === 'function') { + transFun = transform; + } else if (typeof transform === 'string') { + transFun = sanitizeHtml.simpleTransform(transform); + } + if (tag === '*') { + transformTagsAll = transFun; + } else { + transformTagsMap[tag] = transFun; + } + }); + + let depth; + let stack; + let skipMap; + let transformMap; + let skipText; + let skipTextDepth; + let addedText = false; + + initializeState(); + + const parser = new htmlparser.Parser({ + onopentag: function(name, attribs) { + // If `enforceHtmlBoundary` is `true` and this has found the opening + // `html` tag, reset the state. + if (options.enforceHtmlBoundary && name === 'html') { + initializeState(); + } + + if (skipText) { + skipTextDepth++; + return; + } + const frame = new Frame(name, attribs); + stack.push(frame); + + let skip = false; + const hasText = !!frame.text; + let transformedTag; + if (has(transformTagsMap, name)) { + transformedTag = transformTagsMap[name](name, attribs); + + frame.attribs = attribs = transformedTag.attribs; + + if (transformedTag.text !== undefined) { + frame.innerText = transformedTag.text; + } + + if (name !== transformedTag.tagName) { + frame.name = name = transformedTag.tagName; + transformMap[depth] = transformedTag.tagName; + } + } + if (transformTagsAll) { + transformedTag = transformTagsAll(name, attribs); + + frame.attribs = attribs = transformedTag.attribs; + if (name !== transformedTag.tagName) { + frame.name = name = transformedTag.tagName; + transformMap[depth] = transformedTag.tagName; + } + } + + if (!tagAllowed(name) || (options.disallowedTagsMode === 'recursiveEscape' && !isEmptyObject(skipMap)) || (options.nestingLimit != null && depth >= options.nestingLimit)) { + skip = true; + skipMap[depth] = true; + if (options.disallowedTagsMode === 'discard' || options.disallowedTagsMode === 'completelyDiscard') { + if (nonTextTagsArray.indexOf(name) !== -1) { + skipText = true; + skipTextDepth = 1; + } + } + skipMap[depth] = true; + } + depth++; + if (skip) { + if (options.disallowedTagsMode === 'discard' || options.disallowedTagsMode === 'completelyDiscard') { + // We want the contents but not this tag + return; + } + tempResult = result; + result = ''; + } + result += '<' + name; + + if (name === 'script') { + if (options.allowedScriptHostnames || options.allowedScriptDomains) { + frame.innerText = ''; + } + } + + if (!allowedAttributesMap || has(allowedAttributesMap, name) || allowedAttributesMap['*']) { + each(attribs, function(value, a) { + if (!VALID_HTML_ATTRIBUTE_NAME.test(a)) { + // This prevents part of an attribute name in the output from being + // interpreted as the end of an attribute, or end of a tag. + delete frame.attribs[a]; + return; + } + // If the value is empty, check if the attribute is in the allowedEmptyAttributes array. + // If it is not in the allowedEmptyAttributes array, and it is a known non-boolean attribute, delete it + // List taken from https://html.spec.whatwg.org/multipage/indices.html#attributes-3 + if (value === '' && (!options.allowedEmptyAttributes.includes(a)) && + (options.nonBooleanAttributes.includes(a) || options.nonBooleanAttributes.includes('*'))) { + delete frame.attribs[a]; + return; + } + // check allowedAttributesMap for the element and attribute and modify the value + // as necessary if there are specific values defined. + let passedAllowedAttributesMapCheck = false; + if (!allowedAttributesMap || + (has(allowedAttributesMap, name) && allowedAttributesMap[name].indexOf(a) !== -1) || + (allowedAttributesMap['*'] && allowedAttributesMap['*'].indexOf(a) !== -1) || + (has(allowedAttributesGlobMap, name) && allowedAttributesGlobMap[name].test(a)) || + (allowedAttributesGlobMap['*'] && allowedAttributesGlobMap['*'].test(a))) { + passedAllowedAttributesMapCheck = true; + } else if (allowedAttributesMap && allowedAttributesMap[name]) { + for (const o of allowedAttributesMap[name]) { + if (isPlainObject(o) && o.name && (o.name === a)) { + passedAllowedAttributesMapCheck = true; + let newValue = ''; + if (o.multiple === true) { + // verify the values that are allowed + const splitStrArray = value.split(' '); + for (const s of splitStrArray) { + if (o.values.indexOf(s) !== -1) { + if (newValue === '') { + newValue = s; + } else { + newValue += ' ' + s; + } + } + } + } else if (o.values.indexOf(value) >= 0) { + // verified an allowed value matches the entire attribute value + newValue = value; + } + value = newValue; + } + } + } + if (passedAllowedAttributesMapCheck) { + if (options.allowedSchemesAppliedToAttributes.indexOf(a) !== -1) { + if (naughtyHref(name, value)) { + delete frame.attribs[a]; + return; + } + } + + if (name === 'script' && a === 'src') { + + let allowed = true; + + try { + const parsed = parseUrl(value); + + if (options.allowedScriptHostnames || options.allowedScriptDomains) { + const allowedHostname = (options.allowedScriptHostnames || []).find(function (hostname) { + return hostname === parsed.url.hostname; + }); + const allowedDomain = (options.allowedScriptDomains || []).find(function(domain) { + return parsed.url.hostname === domain || parsed.url.hostname.endsWith(`.${domain}`); + }); + allowed = allowedHostname || allowedDomain; + } + } catch (e) { + allowed = false; + } + + if (!allowed) { + delete frame.attribs[a]; + return; + } + } + + if (name === 'iframe' && a === 'src') { + let allowed = true; + try { + const parsed = parseUrl(value); + + if (parsed.isRelativeUrl) { + // default value of allowIframeRelativeUrls is true + // unless allowedIframeHostnames or allowedIframeDomains specified + allowed = has(options, 'allowIframeRelativeUrls') + ? options.allowIframeRelativeUrls + : (!options.allowedIframeHostnames && !options.allowedIframeDomains); + } else if (options.allowedIframeHostnames || options.allowedIframeDomains) { + const allowedHostname = (options.allowedIframeHostnames || []).find(function (hostname) { + return hostname === parsed.url.hostname; + }); + const allowedDomain = (options.allowedIframeDomains || []).find(function(domain) { + return parsed.url.hostname === domain || parsed.url.hostname.endsWith(`.${domain}`); + }); + allowed = allowedHostname || allowedDomain; + } + } catch (e) { + // Unparseable iframe src + allowed = false; + } + if (!allowed) { + delete frame.attribs[a]; + return; + } + } + if (a === 'srcset') { + try { + let parsed = parseSrcset(value); + parsed.forEach(function(value) { + if (naughtyHref('srcset', value.url)) { + value.evil = true; + } + }); + parsed = filter(parsed, function(v) { + return !v.evil; + }); + if (!parsed.length) { + delete frame.attribs[a]; + return; + } else { + value = stringifySrcset(filter(parsed, function(v) { + return !v.evil; + })); + frame.attribs[a] = value; + } + } catch (e) { + // Unparseable srcset + delete frame.attribs[a]; + return; + } + } + if (a === 'class') { + const allowedSpecificClasses = allowedClassesMap[name]; + const allowedWildcardClasses = allowedClassesMap['*']; + const allowedSpecificClassesGlob = allowedClassesGlobMap[name]; + const allowedSpecificClassesRegex = allowedClassesRegexMap[name]; + const allowedWildcardClassesGlob = allowedClassesGlobMap['*']; + const allowedClassesGlobs = [ + allowedSpecificClassesGlob, + allowedWildcardClassesGlob + ] + .concat(allowedSpecificClassesRegex) + .filter(function (t) { + return t; + }); + if (allowedSpecificClasses && allowedWildcardClasses) { + value = filterClasses(value, deepmerge(allowedSpecificClasses, allowedWildcardClasses), allowedClassesGlobs); + } else { + value = filterClasses(value, allowedSpecificClasses || allowedWildcardClasses, allowedClassesGlobs); + } + if (!value.length) { + delete frame.attribs[a]; + return; + } + } + if (a === 'style') { + if (options.parseStyleAttributes) { + try { + const abstractSyntaxTree = postcssParse(name + ' {' + value + '}', { map: false }); + const filteredAST = filterCss(abstractSyntaxTree, options.allowedStyles); + + value = stringifyStyleAttributes(filteredAST); + + if (value.length === 0) { + delete frame.attribs[a]; + return; + } + } catch (e) { + if (typeof window !== 'undefined') { + console.warn('Failed to parse "' + name + ' {' + value + '}' + '", If you\'re running this in a browser, we recommend to disable style parsing: options.parseStyleAttributes: false, since this only works in a node environment due to a postcss dependency, More info: https://github.com/apostrophecms/sanitize-html/issues/547'); + } + delete frame.attribs[a]; + return; + } + } else if (options.allowedStyles) { + throw new Error('allowedStyles option cannot be used together with parseStyleAttributes: false.'); + } + } + result += ' ' + a; + if (value && value.length) { + result += '="' + escapeHtml(value, true) + '"'; + } else if (options.allowedEmptyAttributes.includes(a)) { + result += '=""'; + } + } else { + delete frame.attribs[a]; + } + }); + } + if (options.selfClosing.indexOf(name) !== -1) { + result += ' />'; + } else { + result += '>'; + if (frame.innerText && !hasText && !options.textFilter) { + result += escapeHtml(frame.innerText); + addedText = true; + } + } + if (skip) { + result = tempResult + escapeHtml(result); + tempResult = ''; + } + }, + ontext: function(text) { + if (skipText) { + return; + } + const lastFrame = stack[stack.length - 1]; + let tag; + + if (lastFrame) { + tag = lastFrame.tag; + // If inner text was set by transform function then let's use it + text = lastFrame.innerText !== undefined ? lastFrame.innerText : text; + } + + if (options.disallowedTagsMode === 'completelyDiscard' && !tagAllowed(tag)) { + text = ''; + } else if ((options.disallowedTagsMode === 'discard' || options.disallowedTagsMode === 'completelyDiscard') && ((tag === 'script') || (tag === 'style'))) { + // htmlparser2 gives us these as-is. Escaping them ruins the content. Allowing + // script tags is, by definition, game over for XSS protection, so if that's + // your concern, don't allow them. The same is essentially true for style tags + // which have their own collection of XSS vectors. + result += text; + } else { + const escaped = escapeHtml(text, false); + if (options.textFilter && !addedText) { + result += options.textFilter(escaped, tag); + } else if (!addedText) { + result += escaped; + } + } + if (stack.length) { + const frame = stack[stack.length - 1]; + frame.text += text; + } + }, + onclosetag: function(name, isImplied) { + + if (skipText) { + skipTextDepth--; + if (!skipTextDepth) { + skipText = false; + } else { + return; + } + } + + const frame = stack.pop(); + if (!frame) { + // Do not crash on bad markup + return; + } + + if (frame.tag !== name) { + // Another case of bad markup. + // Push to stack, so that it will be used in future closing tags. + stack.push(frame); + return; + } + + skipText = options.enforceHtmlBoundary ? name === 'html' : false; + depth--; + const skip = skipMap[depth]; + if (skip) { + delete skipMap[depth]; + if (options.disallowedTagsMode === 'discard' || options.disallowedTagsMode === 'completelyDiscard') { + frame.updateParentNodeText(); + return; + } + tempResult = result; + result = ''; + } + + if (transformMap[depth]) { + name = transformMap[depth]; + delete transformMap[depth]; + } + + if (options.exclusiveFilter && options.exclusiveFilter(frame)) { + result = result.substr(0, frame.tagPosition); + return; + } + + frame.updateParentNodeMediaChildren(); + frame.updateParentNodeText(); + + if ( + // Already output /> + options.selfClosing.indexOf(name) !== -1 || + // Escaped tag, closing tag is implied + (isImplied && !tagAllowed(name) && [ 'escape', 'recursiveEscape' ].indexOf(options.disallowedTagsMode) >= 0) + ) { + if (skip) { + result = tempResult; + tempResult = ''; + } + return; + } + + result += '</' + name + '>'; + if (skip) { + result = tempResult + escapeHtml(result); + tempResult = ''; + } + addedText = false; + } + }, options.parser); + parser.write(html); + parser.end(); + + return result; + + function initializeState() { + result = ''; + depth = 0; + stack = []; + skipMap = {}; + transformMap = {}; + skipText = false; + skipTextDepth = 0; + } + + function escapeHtml(s, quote) { + if (typeof (s) !== 'string') { + s = s + ''; + } + if (options.parser.decodeEntities) { + s = s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); + if (quote) { + s = s.replace(/"/g, '"'); + } + } + // TODO: this is inadequate because it will pass `&0;`. This approach + // will not work, each & must be considered with regard to whether it + // is followed by a 100% syntactically valid entity or not, and escaped + // if it is not. If this bothers you, don't set parser.decodeEntities + // to false. (The default is true.) + s = s.replace(/&(?![a-zA-Z0-9#]{1,20};)/g, '&') // Match ampersands not part of existing HTML entity + .replace(/</g, '<') + .replace(/>/g, '>'); + if (quote) { + s = s.replace(/"/g, '"'); + } + return s; + } + + function naughtyHref(name, href) { + // Browsers ignore character codes of 32 (space) and below in a surprising + // number of situations. Start reading here: + // https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Embedded_tab + // eslint-disable-next-line no-control-regex + href = href.replace(/[\x00-\x20]+/g, ''); + // Clobber any comments in URLs, which the browser might + // interpret inside an XML data island, allowing + // a javascript: URL to be snuck through + while (true) { + const firstIndex = href.indexOf('<!--'); + if (firstIndex === -1) { + break; + } + const lastIndex = href.indexOf('-->', firstIndex + 4); + if (lastIndex === -1) { + break; + } + href = href.substring(0, firstIndex) + href.substring(lastIndex + 3); + } + // Case insensitive so we don't get faked out by JAVASCRIPT #1 + // Allow more characters after the first so we don't get faked + // out by certain schemes browsers accept + const matches = href.match(/^([a-zA-Z][a-zA-Z0-9.\-+]*):/); + if (!matches) { + // Protocol-relative URL starting with any combination of '/' and '\' + if (href.match(/^[/\\]{2}/)) { + return !options.allowProtocolRelative; + } + + // No scheme + return false; + } + const scheme = matches[1].toLowerCase(); + + if (has(options.allowedSchemesByTag, name)) { + return options.allowedSchemesByTag[name].indexOf(scheme) === -1; + } + + return !options.allowedSchemes || options.allowedSchemes.indexOf(scheme) === -1; + } + + function parseUrl(value) { + value = value.replace(/^(\w+:)?\s*[\\/]\s*[\\/]/, '$1//'); + if (value.startsWith('relative:')) { + // An attempt to exploit our workaround for base URLs being + // mandatory for relative URL validation in the WHATWG + // URL parser, reject it + throw new Error('relative: exploit attempt'); + } + // naughtyHref is in charge of whether protocol relative URLs + // are cool. Here we are concerned just with allowed hostnames and + // whether to allow relative URLs. + // + // Build a placeholder "base URL" against which any reasonable + // relative URL may be parsed successfully + let base = 'relative://relative-site'; + for (let i = 0; (i < 100); i++) { + base += `/${i}`; + } + + const parsed = new URL(value, base); + + const isRelativeUrl = parsed && parsed.hostname === 'relative-site' && parsed.protocol === 'relative:'; + return { + isRelativeUrl, + url: parsed + }; + } + /** + * Filters user input css properties by allowlisted regex attributes. + * Modifies the abstractSyntaxTree object. + * + * @param {object} abstractSyntaxTree - Object representation of CSS attributes. + * @property {array[Declaration]} abstractSyntaxTree.nodes[0] - Each object cointains prop and value key, i.e { prop: 'color', value: 'red' }. + * @param {object} allowedStyles - Keys are properties (i.e color), value is list of permitted regex rules (i.e /green/i). + * @return {object} - The modified tree. + */ + function filterCss(abstractSyntaxTree, allowedStyles) { + if (!allowedStyles) { + return abstractSyntaxTree; + } + + const astRules = abstractSyntaxTree.nodes[0]; + let selectedRule; + + // Merge global and tag-specific styles into new AST. + if (allowedStyles[astRules.selector] && allowedStyles['*']) { + selectedRule = deepmerge( + allowedStyles[astRules.selector], + allowedStyles['*'] + ); + } else { + selectedRule = allowedStyles[astRules.selector] || allowedStyles['*']; + } + + if (selectedRule) { + abstractSyntaxTree.nodes[0].nodes = astRules.nodes.reduce(filterDeclarations(selectedRule), []); + } + + return abstractSyntaxTree; + } + + /** + * Extracts the style attributes from an AbstractSyntaxTree and formats those + * values in the inline style attribute format. + * + * @param {AbstractSyntaxTree} filteredAST + * @return {string} - Example: "color:yellow;text-align:center !important;font-family:helvetica;" + */ + function stringifyStyleAttributes(filteredAST) { + return filteredAST.nodes[0].nodes + .reduce(function(extractedAttributes, attrObject) { + extractedAttributes.push( + `${attrObject.prop}:${attrObject.value}${attrObject.important ? ' !important' : ''}` + ); + return extractedAttributes; + }, []) + .join(';'); + } + + /** + * Filters the existing attributes for the given property. Discards any attributes + * which don't match the allowlist. + * + * @param {object} selectedRule - Example: { color: red, font-family: helvetica } + * @param {array} allowedDeclarationsList - List of declarations which pass the allowlist. + * @param {object} attributeObject - Object representing the current css property. + * @property {string} attributeObject.type - Typically 'declaration'. + * @property {string} attributeObject.prop - The CSS property, i.e 'color'. + * @property {string} attributeObject.value - The corresponding value to the css property, i.e 'red'. + * @return {function} - When used in Array.reduce, will return an array of Declaration objects + */ + function filterDeclarations(selectedRule) { + return function (allowedDeclarationsList, attributeObject) { + // If this property is allowlisted... + if (has(selectedRule, attributeObject.prop)) { + const matchesRegex = selectedRule[attributeObject.prop].some(function(regularExpression) { + return regularExpression.test(attributeObject.value); + }); + + if (matchesRegex) { + allowedDeclarationsList.push(attributeObject); + } + } + return allowedDeclarationsList; + }; + } + + function filterClasses(classes, allowed, allowedGlobs) { + if (!allowed) { + // The class attribute is allowed without filtering on this tag + return classes; + } + classes = classes.split(/\s+/); + return classes.filter(function(clss) { + return allowed.indexOf(clss) !== -1 || allowedGlobs.some(function(glob) { + return glob.test(clss); + }); + }).join(' '); + } + } + + // Defaults are accessible to you so that you can use them as a starting point + // programmatically if you wish + + const htmlParserDefaults = { + decodeEntities: true + }; + sanitizeHtml.defaults = { + allowedTags: [ + // Sections derived from MDN element categories and limited to the more + // benign categories. + // https://developer.mozilla.org/en-US/docs/Web/HTML/Element + // Content sectioning + 'address', 'article', 'aside', 'footer', 'header', + 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hgroup', + 'main', 'nav', 'section', + // Text content + 'blockquote', 'dd', 'div', 'dl', 'dt', 'figcaption', 'figure', + 'hr', 'li', 'main', 'ol', 'p', 'pre', 'ul', + // Inline text semantics + 'a', 'abbr', 'b', 'bdi', 'bdo', 'br', 'cite', 'code', 'data', 'dfn', + 'em', 'i', 'kbd', 'mark', 'q', + 'rb', 'rp', 'rt', 'rtc', 'ruby', + 's', 'samp', 'small', 'span', 'strong', 'sub', 'sup', 'time', 'u', 'var', 'wbr', + // Table content + 'caption', 'col', 'colgroup', 'table', 'tbody', 'td', 'tfoot', 'th', + 'thead', 'tr' + ], + // Tags that cannot be boolean + nonBooleanAttributes: [ + 'abbr', 'accept', 'accept-charset', 'accesskey', 'action', + 'allow', 'alt', 'as', 'autocapitalize', 'autocomplete', + 'blocking', 'charset', 'cite', 'class', 'color', 'cols', + 'colspan', 'content', 'contenteditable', 'coords', 'crossorigin', + 'data', 'datetime', 'decoding', 'dir', 'dirname', 'download', + 'draggable', 'enctype', 'enterkeyhint', 'fetchpriority', 'for', + 'form', 'formaction', 'formenctype', 'formmethod', 'formtarget', + 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', + 'http-equiv', 'id', 'imagesizes', 'imagesrcset', 'inputmode', + 'integrity', 'is', 'itemid', 'itemprop', 'itemref', 'itemtype', + 'kind', 'label', 'lang', 'list', 'loading', 'low', 'max', + 'maxlength', 'media', 'method', 'min', 'minlength', 'name', + 'nonce', 'optimum', 'pattern', 'ping', 'placeholder', 'popover', + 'popovertarget', 'popovertargetaction', 'poster', 'preload', + 'referrerpolicy', 'rel', 'rows', 'rowspan', 'sandbox', 'scope', + 'shape', 'size', 'sizes', 'slot', 'span', 'spellcheck', 'src', + 'srcdoc', 'srclang', 'srcset', 'start', 'step', 'style', + 'tabindex', 'target', 'title', 'translate', 'type', 'usemap', + 'value', 'width', 'wrap', + // Event handlers + 'onauxclick', 'onafterprint', 'onbeforematch', 'onbeforeprint', + 'onbeforeunload', 'onbeforetoggle', 'onblur', 'oncancel', + 'oncanplay', 'oncanplaythrough', 'onchange', 'onclick', 'onclose', + 'oncontextlost', 'oncontextmenu', 'oncontextrestored', 'oncopy', + 'oncuechange', 'oncut', 'ondblclick', 'ondrag', 'ondragend', + 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', + 'ondrop', 'ondurationchange', 'onemptied', 'onended', + 'onerror', 'onfocus', 'onformdata', 'onhashchange', 'oninput', + 'oninvalid', 'onkeydown', 'onkeypress', 'onkeyup', + 'onlanguagechange', 'onload', 'onloadeddata', 'onloadedmetadata', + 'onloadstart', 'onmessage', 'onmessageerror', 'onmousedown', + 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', + 'onmouseover', 'onmouseup', 'onoffline', 'ononline', 'onpagehide', + 'onpageshow', 'onpaste', 'onpause', 'onplay', 'onplaying', + 'onpopstate', 'onprogress', 'onratechange', 'onreset', 'onresize', + 'onrejectionhandled', 'onscroll', 'onscrollend', + 'onsecuritypolicyviolation', 'onseeked', 'onseeking', 'onselect', + 'onslotchange', 'onstalled', 'onstorage', 'onsubmit', 'onsuspend', + 'ontimeupdate', 'ontoggle', 'onunhandledrejection', 'onunload', + 'onvolumechange', 'onwaiting', 'onwheel' + ], + disallowedTagsMode: 'discard', + allowedAttributes: { + a: [ 'href', 'name', 'target' ], + // We don't currently allow img itself by default, but + // these attributes would make sense if we did. + img: [ 'src', 'srcset', 'alt', 'title', 'width', 'height', 'loading' ] + }, + allowedEmptyAttributes: [ + 'alt' + ], + // Lots of these won't come up by default because we don't allow them + selfClosing: [ 'img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link', 'meta' ], + // URL schemes we permit + allowedSchemes: [ 'http', 'https', 'ftp', 'mailto', 'tel' ], + allowedSchemesByTag: {}, + allowedSchemesAppliedToAttributes: [ 'href', 'src', 'cite' ], + allowProtocolRelative: true, + enforceHtmlBoundary: false, + parseStyleAttributes: true + }; + + sanitizeHtml.simpleTransform = function(newTagName, newAttribs, merge) { + merge = (merge === undefined) ? true : merge; + newAttribs = newAttribs || {}; + + return function(tagName, attribs) { + let attrib; + if (merge) { + for (attrib in newAttribs) { + attribs[attrib] = newAttribs[attrib]; + } + } else { + attribs = newAttribs; + } + + return { + tagName: newTagName, + attribs: attribs + }; + }; + }; + + var sanitize = /*@__PURE__*/getDefaultExportFromCjs(sanitizeHtml_1); + + // config.js + + + const sanitizeHtmlOptions = { + allowedTags: [ + 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', + 'u', 'b', 'i', 'em', 'strong', 'small', 'sup', 'sub', + 'div', 'span', 'p', 'article', 'blockquote', 'section', + 'details', 'summary', + 'pre', 'code', + 'ul', 'ol', 'li', 'dd', 'dl', + 'table', 'th', 'tr', 'td', 'thead', 'tbody', 'tfood', + 'fieldset', 'legend', + 'figure', 'figcaption', 'img', 'picture', + 'video', 'audio', 'source', + 'iframe', + 'progress', + 'br', 'p', 'hr', + 'label', + 'abbr', + 'a', + 'svg', + ], + allowedAttributes: { + h1: ['id'], + h2: ['id'], + h3: ['id'], + h4: ['id'], + h5: ['id'], + h6: ['id'], + a: ['href', 'target', 'title'], + abbr: ['title'], + progress: ['value', 'max'], + img: ['src', 'srcset', 'alt', 'title'], + picture: ['media', 'srcset'], + video: ['controls', 'width', 'height', 'autoplay', 'muted', 'loop', 'src'], + audio: ['controls', 'width', 'height', 'autoplay', 'muted', 'loop', 'src'], + source: ['src', 'srcset', 'data-srcset', 'type', 'media', 'sizes'], + iframe: ['src', 'frameborder', 'height', 'width', 'scrolling', 'allow'], + svg: ['width', 'height'], // sanitize-html does not support svg fully yet + }, + allowedIframeDomains: [ + 'youtube.com', 'vimeo.com', 'odysee.com', + 'soundcloud.com', 'audius.co', + 'github.com', 'codepen.com', + 'twitter.com', 'facebook.com', 'instagram.com', + ], + disallowedTagsMode: 'discard', + allowVulnerableTags: false, + parseStyleAttributes: false, + enforceHtmlBoundary: false, + }; + + /** + * @returns {SanitizeOptions} + */ + const getSanitizeHtmlOptions = () => { + return clone(sanitizeHtmlOptions) + }; + + const setSanitizeHtmlOptions = (opts = {}) => { + Object.keys(opts).forEach((key) => { + sanitizeHtmlOptions[key] = clone(opts[key]); + }); + }; + + // utils -> html + + + const purify$1 = (html) => { + return sanitize(html, { + allowedTags: false, + allowedAttributes: false, + allowVulnerableTags: true, + }) + }; + + const WS_REGEXP = /^[\s\f\n\r\t\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\ufeff\x09\x0a\x0b\x0c\x0d\x20\xa0]+$/; // eslint-disable-line + + const stripMultiLinebreaks = (str) => { + return str.replace(/(\r\n|\n|\u2424){2,}/g, '\n').split('\n').map((line) => { + return WS_REGEXP.test(line) ? line.trim() : line + }).filter((line) => { + return line.length > 0 + }).join('\n') + }; + + const stripMultispaces = (str) => { + return str.replace(WS_REGEXP, ' ').trim() + }; + + const getCharset = (html) => { + const doc = new DOMParser().parseFromString(html, 'text/html'); + const m = doc.querySelector('meta[charset]') || null; + let charset = m ? m.getAttribute('charset') : ''; + if (!charset) { + const h = doc.querySelector('meta[http-equiv="content-type"]') || null; + charset = h ? h.getAttribute('content')?.split(';')[1]?.replace('charset=', '')?.trim() : ''; + } + return charset?.toLowerCase() || 'utf8' + }; + + const cleanify = (inputHtml) => { + const doc = new DOMParser().parseFromString(inputHtml, 'text/html'); + const html = doc.documentElement.innerHTML; + return pipe( + input => sanitize(input, getSanitizeHtmlOptions()), + input => stripMultiLinebreaks(input), + input => stripMultispaces(input) + )(html) + }; + + // similarity.js + // https://github.com/aceakash/string-similarity + + + const areArgsValid = (mainString, targetStrings) => { + return isString$1(mainString) && isArray$3(targetStrings) + && targetStrings.length > 0 && targetStrings.every(s => isString$1(s)) + }; + + const compareTwoStrings = (first, second) => { + first = first.replace(/\s+/g, ''); + second = second.replace(/\s+/g, ''); + + if (first === second) return 1 // identical or empty + if (first.length < 2 || second.length < 2) return 0 // if either is a 0-letter or 1-letter string + + let firstBigrams = new Map(); + for (let i = 0; i < first.length - 1; i++) { + const bigram = first.substring(i, i + 2); + const count = firstBigrams.has(bigram) + ? firstBigrams.get(bigram) + 1 + : 1; + + firstBigrams.set(bigram, count); + } + + let intersectionSize = 0; + for (let i = 0; i < second.length - 1; i++) { + const bigram = second.substring(i, i + 2); + const count = firstBigrams.has(bigram) + ? firstBigrams.get(bigram) + : 0; + + if (count > 0) { + firstBigrams.set(bigram, count - 1); + intersectionSize++; + } + } + + return (2.0 * intersectionSize) / (first.length + second.length - 2) + }; + + const findBestMatch = (mainString, targetStrings) => { + if (!areArgsValid(mainString, targetStrings)) { + throw new Error('Bad arguments: First argument should be a string, second should be an array of strings') + } + + const ratings = []; + let bestMatchIndex = 0; + + for (let i = 0; i < targetStrings.length; i++) { + const currentTargetString = targetStrings[i]; + const currentRating = compareTwoStrings(mainString, currentTargetString); + ratings.push({ target: currentTargetString, rating: currentRating }); + if (currentRating > ratings[bestMatchIndex].rating) { + bestMatchIndex = i; + } + } + + const bestMatch = ratings[bestMatchIndex]; + + return { ratings: ratings, bestMatch: bestMatch, bestMatchIndex: bestMatchIndex } + }; + + // utils -> linker + + + const isValid = (url = '') => { + try { + const ourl = new URL(url); + return ourl !== null && ourl.protocol.startsWith('http') + } catch { + return false + } + }; + + const chooseBestUrl = (candidates = [], title = '') => { + const ranking = findBestMatch(title, candidates); + return ranking.bestMatch.target + }; + + const absolutify = (fullUrl = '', relativeUrl = '') => { + try { + const result = new URL(relativeUrl, fullUrl); + return result.toString() + } catch { + return '' + } + }; + + const blacklistKeys = [ + 'CNDID', + '__twitter_impression', + '_hsenc', + '_openstat', + 'action_object_map', + 'action_ref_map', + 'action_type_map', + 'amp', + 'fb_action_ids', + 'fb_action_types', + 'fb_ref', + 'fb_source', + 'fbclid', + 'ga_campaign', + 'ga_content', + 'ga_medium', + 'ga_place', + 'ga_source', + 'ga_term', + 'gs_l', + 'hmb_campaign', + 'hmb_medium', + 'hmb_source', + 'mbid', + 'mc_cid', + 'mc_eid', + 'mkt_tok', + 'referrer', + 'spJobID', + 'spMailingID', + 'spReportId', + 'spUserID', + 'utm_brand', + 'utm_campaign', + 'utm_cid', + 'utm_content', + 'utm_int', + 'utm_mailing', + 'utm_medium', + 'utm_name', + 'utm_place', + 'utm_pubreferrer', + 'utm_reader', + 'utm_social', + 'utm_source', + 'utm_swu', + 'utm_term', + 'utm_userid', + 'utm_viz_id', + 'wt_mc_o', + 'yclid', + 'WT.mc_id', + 'WT.mc_ev', + 'WT.srch', + 'pk_source', + 'pk_medium', + 'pk_campaign', + ]; + + const purify = (url) => { + try { + const pureUrl = new URL(url); + + blacklistKeys.forEach((key) => { + pureUrl.searchParams.delete(key); + }); + + return pureUrl.toString().replace(pureUrl.hash, '') + } catch { + return null + } + }; + + /** + * @param inputHtml {string} + * @param url {string} + * @returns article {string} + */ + const normalize = (html, url) => { + const doc = new DOMParser().parseFromString(html, 'text/html'); + + Array.from(doc.getElementsByTagName('a')).forEach((element) => { + const href = element.getAttribute('href'); + if (href) { + element.setAttribute('href', absolutify(url, href)); + element.setAttribute('target', '_blank'); + } + }); + + Array.from(doc.getElementsByTagName('img')).forEach((element) => { + const src = element.getAttribute('data-src') ?? element.getAttribute('src'); + if (src) { + element.setAttribute('src', absolutify(url, src)); + } + }); + + return Array.from(doc.childNodes).map(element => element.outerHTML).join('') + }; + + const getDomain = (url) => { + const host = (new URL(url)).host; + return host.replace('www.', '') + }; + + const typeSchemas = [ + 'aboutpage', + 'checkoutpage', + 'collectionpage', + 'contactpage', + 'faqpage', + 'itempage', + 'medicalwebpage', + 'profilepage', + 'qapage', + 'realestatelisting', + 'searchresultspage', + 'webpage', + 'website', + 'article', + 'advertisercontentarticle', + 'newsarticle', + 'analysisnewsarticle', + 'askpublicnewsarticle', + 'backgroundnewsarticle', + 'opinionnewsarticle', + 'reportagenewsarticle', + 'reviewnewsarticle', + 'report', + 'satiricalarticle', + 'scholarlyarticle', + 'medicalscholarlyarticle', + ]; + + const attributeLists = { + description: 'description', + image: 'image', + author: 'author', + published: 'datePublished', + type: '@type', + }; + + const parseJson = (text) => { + try { + return JSON.parse(text) + } catch { + return null + } + }; + + /** + * Parses JSON-LD data from a document and populates an entry object. + * Only populates if the original entry object is empty or undefined. + * + * @param {Document} document - The HTML Document + * @param {Object} entry - The entry object to merge/populate with JSON-LD. + * @returns {Object} The entry object after being merged/populated with data. + */ + var extractLdSchema = (document, entry) => { + const ldSchema = document.querySelector('script[type="application/ld+json"]')?.textContent; + + const ldJson = ldSchema ? parseJson(ldSchema) : null; + + if (ldJson) { + Object.entries(attributeLists).forEach(([key, attr]) => { + if ((typeof entry[key] === 'undefined' || entry[key] === '') && ldJson[attr]) { + if (key === 'type' && typeof ldJson[attr] === 'string') { + return entry[key] = typeSchemas.includes(ldJson[attr].toLowerCase()) ? ldJson[attr].toLowerCase() : '' + } + + if (typeof ldJson[attr] === 'string') { + return entry[key] = ldJson[attr].toLowerCase() + } + + if (Array.isArray(ldJson[attr]) && typeof ldJson[attr][0] === 'string') { + return entry[key] = ldJson[attr][0].toLowerCase() + } + } + }); + } + + return entry + }; + + // utils -> extractMetaData + + + /** + * @param {Element} node + * @param {Object} attributeLists + * @returns {?{key: string, content: string}} + */ + function getMetaContentByNameOrProperty (node, attributeLists) { + const content = node.getAttribute('content'); + if (!content) return null + + const property = node + .getAttribute('property')?.toLowerCase() ?? + node.getAttribute('itemprop')?.toLowerCase(); + + const name = node.getAttribute('name')?.toLowerCase(); + + for (const [key, attrs] of Object.entries(attributeLists)) { + if (attrs.includes(property) || attrs.includes(name)) { + return { key, content } + } + } + + return null + } + + /** + * @param html {string} + * @returns {{image: string, author: string, amphtml: string, description: string, canonical: string, source: string, published: string, title: string, url: string, shortlink: string, favicon: string, type: string}} + */ + var extractMetaData = (html) => { + const entry = { + url: '', + shortlink: '', + amphtml: '', + canonical: '', + title: '', + description: '', + image: '', + author: '', + source: '', + published: '', + favicon: '', + type: '', + }; + + const sourceAttrs = [ + 'application-name', + 'og:site_name', + 'twitter:site', + 'dc.title', + ]; + const urlAttrs = [ + 'og:url', + 'twitter:url', + 'parsely-link', + ]; + const titleAttrs = [ + 'title', + 'og:title', + 'twitter:title', + 'parsely-title', + ]; + const descriptionAttrs = [ + 'description', + 'og:description', + 'twitter:description', + 'parsely-description', + ]; + const imageAttrs = [ + 'image', + 'og:image', + 'og:image:url', + 'og:image:secure_url', + 'twitter:image', + 'twitter:image:src', + 'parsely-image-url', + ]; + const authorAttrs = [ + 'author', + 'creator', + 'og:creator', + 'article:author', + 'twitter:creator', + 'dc.creator', + 'parsely-author', + ]; + const publishedTimeAttrs = [ + 'article:published_time', + 'article:modified_time', + 'og:updated_time', + 'dc.date', + 'dc.date.issued', + 'dc.date.created', + 'dc:created', + 'dcterms.date', + 'datepublished', + 'datemodified', + 'updated_time', + 'modified_time', + 'published_time', + 'release_date', + 'date', + 'parsely-pub-date', + ]; + const typeAttrs = [ + 'og:type', + ]; + + const attributeLists = { + source: sourceAttrs, + url: urlAttrs, + title: titleAttrs, + description: descriptionAttrs, + image: imageAttrs, + author: authorAttrs, + published: publishedTimeAttrs, + type: typeAttrs, + }; + + const doc = new DOMParser().parseFromString(html, 'text/html'); + entry.title = doc.querySelector('head > title')?.innerText; + + Array.from(doc.getElementsByTagName('link')).forEach(node => { + const rel = node.getAttribute('rel'); + const href = node.getAttribute('href'); + if (rel && href) { + entry[rel] = href; + if (rel === 'icon' || rel === 'shortcut icon') { + entry.favicon = href; + } + } + }); + + Array.from(doc.getElementsByTagName('meta')).forEach(node => { + const result = getMetaContentByNameOrProperty(node, attributeLists); + if (result) { + entry[result.key] = result.content; + } + }); + + const entries = extractLdSchema(doc, entry); + return entries + }; + + var Readability$1 = {exports: {}}; + + /* + * Copyright (c) 2010 Arc90 Inc + * + * 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + (function (module) { + /* + * This code is heavily based on Arc90's readability.js (1.7.1) script + * available at: http://code.google.com/p/arc90labs-readability + */ + + /** + * Public constructor. + * @param {HTMLDocument} doc The document to parse. + * @param {Object} options The options object. + */ + function Readability(doc, options) { + // In some older versions, people passed a URI as the first argument. Cope: + if (options && options.documentElement) { + doc = options; + options = arguments[2]; + } else if (!doc || !doc.documentElement) { + throw new Error("First argument to Readability constructor should be a document object."); + } + options = options || {}; + + this._doc = doc; + this._docJSDOMParser = this._doc.firstChild.__JSDOMParser__; + this._articleTitle = null; + this._articleByline = null; + this._articleDir = null; + this._articleSiteName = null; + this._attempts = []; + + // Configurable options + this._debug = !!options.debug; + this._maxElemsToParse = options.maxElemsToParse || this.DEFAULT_MAX_ELEMS_TO_PARSE; + this._nbTopCandidates = options.nbTopCandidates || this.DEFAULT_N_TOP_CANDIDATES; + this._charThreshold = options.charThreshold || this.DEFAULT_CHAR_THRESHOLD; + this._classesToPreserve = this.CLASSES_TO_PRESERVE.concat(options.classesToPreserve || []); + this._keepClasses = !!options.keepClasses; + this._serializer = options.serializer || function(el) { + return el.innerHTML; + }; + this._disableJSONLD = !!options.disableJSONLD; + this._allowedVideoRegex = options.allowedVideoRegex || this.REGEXPS.videos; + + // Start with all flags set + this._flags = this.FLAG_STRIP_UNLIKELYS | + this.FLAG_WEIGHT_CLASSES | + this.FLAG_CLEAN_CONDITIONALLY; + + + // Control whether log messages are sent to the console + if (this._debug) { + let logNode = function(node) { + if (node.nodeType == node.TEXT_NODE) { + return `${node.nodeName} ("${node.textContent}")`; + } + let attrPairs = Array.from(node.attributes || [], function(attr) { + return `${attr.name}="${attr.value}"`; + }).join(" "); + return `<${node.localName} ${attrPairs}>`; + }; + this.log = function () { + if (typeof console !== "undefined") { + let args = Array.from(arguments, arg => { + if (arg && arg.nodeType == this.ELEMENT_NODE) { + return logNode(arg); + } + return arg; + }); + args.unshift("Reader: (Readability)"); + console.log.apply(console, args); + } else if (typeof dump !== "undefined") { + /* global dump */ + var msg = Array.prototype.map.call(arguments, function(x) { + return (x && x.nodeName) ? logNode(x) : x; + }).join(" "); + dump("Reader: (Readability) " + msg + "\n"); + } + }; + } else { + this.log = function () {}; + } + } + + Readability.prototype = { + FLAG_STRIP_UNLIKELYS: 0x1, + FLAG_WEIGHT_CLASSES: 0x2, + FLAG_CLEAN_CONDITIONALLY: 0x4, + + // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType + ELEMENT_NODE: 1, + TEXT_NODE: 3, + + // Max number of nodes supported by this parser. Default: 0 (no limit) + DEFAULT_MAX_ELEMS_TO_PARSE: 0, + + // The number of top candidates to consider when analysing how + // tight the competition is among candidates. + DEFAULT_N_TOP_CANDIDATES: 5, + + // Element tags to score by default. + DEFAULT_TAGS_TO_SCORE: "section,h2,h3,h4,h5,h6,p,td,pre".toUpperCase().split(","), + + // The default number of chars an article must have in order to return a result + DEFAULT_CHAR_THRESHOLD: 500, + + // All of the regular expressions in use within readability. + // Defined up here so we don't instantiate them repeatedly in loops. + REGEXPS: { + // NOTE: These two regular expressions are duplicated in + // Readability-readerable.js. Please keep both copies in sync. + unlikelyCandidates: /-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i, + okMaybeItsACandidate: /and|article|body|column|content|main|shadow/i, + + positive: /article|body|content|entry|hentry|h-entry|main|page|pagination|post|text|blog|story/i, + negative: /-ad-|hidden|^hid$| hid$| hid |^hid |banner|combx|comment|com-|contact|foot|footer|footnote|gdpr|masthead|media|meta|outbrain|promo|related|scroll|share|shoutbox|sidebar|skyscraper|sponsor|shopping|tags|tool|widget/i, + extraneous: /print|archive|comment|discuss|e[\-]?mail|share|reply|all|login|sign|single|utility/i, + byline: /byline|author|dateline|writtenby|p-author/i, + replaceFonts: /<(\/?)font[^>]*>/gi, + normalize: /\s{2,}/g, + videos: /\/\/(www\.)?((dailymotion|youtube|youtube-nocookie|player\.vimeo|v\.qq)\.com|(archive|upload\.wikimedia)\.org|player\.twitch\.tv)/i, + shareElements: /(\b|_)(share|sharedaddy)(\b|_)/i, + nextLink: /(next|weiter|continue|>([^\|]|$)|»([^\|]|$))/i, + prevLink: /(prev|earl|old|new|<|«)/i, + tokenize: /\W+/g, + whitespace: /^\s*$/, + hasContent: /\S$/, + hashUrl: /^#.+/, + srcsetUrl: /(\S+)(\s+[\d.]+[xw])?(\s*(?:,|$))/g, + b64DataUrl: /^data:\s*([^\s;,]+)\s*;\s*base64\s*,/i, + // Commas as used in Latin, Sindhi, Chinese and various other scripts. + // see: https://en.wikipedia.org/wiki/Comma#Comma_variants + commas: /\u002C|\u060C|\uFE50|\uFE10|\uFE11|\u2E41|\u2E34|\u2E32|\uFF0C/g, + // See: https://schema.org/Article + jsonLdArticleTypes: /^Article|AdvertiserContentArticle|NewsArticle|AnalysisNewsArticle|AskPublicNewsArticle|BackgroundNewsArticle|OpinionNewsArticle|ReportageNewsArticle|ReviewNewsArticle|Report|SatiricalArticle|ScholarlyArticle|MedicalScholarlyArticle|SocialMediaPosting|BlogPosting|LiveBlogPosting|DiscussionForumPosting|TechArticle|APIReference$/ + }, + + UNLIKELY_ROLES: [ "menu", "menubar", "complementary", "navigation", "alert", "alertdialog", "dialog" ], + + DIV_TO_P_ELEMS: new Set([ "BLOCKQUOTE", "DL", "DIV", "IMG", "OL", "P", "PRE", "TABLE", "UL" ]), + + ALTER_TO_DIV_EXCEPTIONS: ["DIV", "ARTICLE", "SECTION", "P"], + + PRESENTATIONAL_ATTRIBUTES: [ "align", "background", "bgcolor", "border", "cellpadding", "cellspacing", "frame", "hspace", "rules", "style", "valign", "vspace" ], + + DEPRECATED_SIZE_ATTRIBUTE_ELEMS: [ "TABLE", "TH", "TD", "HR", "PRE" ], + + // The commented out elements qualify as phrasing content but tend to be + // removed by readability when put into paragraphs, so we ignore them here. + PHRASING_ELEMS: [ + // "CANVAS", "IFRAME", "SVG", "VIDEO", + "ABBR", "AUDIO", "B", "BDO", "BR", "BUTTON", "CITE", "CODE", "DATA", + "DATALIST", "DFN", "EM", "EMBED", "I", "IMG", "INPUT", "KBD", "LABEL", + "MARK", "MATH", "METER", "NOSCRIPT", "OBJECT", "OUTPUT", "PROGRESS", "Q", + "RUBY", "SAMP", "SCRIPT", "SELECT", "SMALL", "SPAN", "STRONG", "SUB", + "SUP", "TEXTAREA", "TIME", "VAR", "WBR" + ], + + // These are the classes that readability sets itself. + CLASSES_TO_PRESERVE: [ "page" ], + + // These are the list of HTML entities that need to be escaped. + HTML_ESCAPE_MAP: { + "lt": "<", + "gt": ">", + "amp": "&", + "quot": '"', + "apos": "'", + }, + + /** + * Run any post-process modifications to article content as necessary. + * + * @param Element + * @return void + **/ + _postProcessContent: function(articleContent) { + // Readability cannot open relative uris so we convert them to absolute uris. + this._fixRelativeUris(articleContent); + + this._simplifyNestedElements(articleContent); + + if (!this._keepClasses) { + // Remove classes. + this._cleanClasses(articleContent); + } + }, + + /** + * Iterates over a NodeList, calls `filterFn` for each node and removes node + * if function returned `true`. + * + * If function is not passed, removes all the nodes in node list. + * + * @param NodeList nodeList The nodes to operate on + * @param Function filterFn the function to use as a filter + * @return void + */ + _removeNodes: function(nodeList, filterFn) { + // Avoid ever operating on live node lists. + if (this._docJSDOMParser && nodeList._isLiveNodeList) { + throw new Error("Do not pass live node lists to _removeNodes"); + } + for (var i = nodeList.length - 1; i >= 0; i--) { + var node = nodeList[i]; + var parentNode = node.parentNode; + if (parentNode) { + if (!filterFn || filterFn.call(this, node, i, nodeList)) { + parentNode.removeChild(node); + } + } + } + }, + + /** + * Iterates over a NodeList, and calls _setNodeTag for each node. + * + * @param NodeList nodeList The nodes to operate on + * @param String newTagName the new tag name to use + * @return void + */ + _replaceNodeTags: function(nodeList, newTagName) { + // Avoid ever operating on live node lists. + if (this._docJSDOMParser && nodeList._isLiveNodeList) { + throw new Error("Do not pass live node lists to _replaceNodeTags"); + } + for (const node of nodeList) { + this._setNodeTag(node, newTagName); + } + }, + + /** + * Iterate over a NodeList, which doesn't natively fully implement the Array + * interface. + * + * For convenience, the current object context is applied to the provided + * iterate function. + * + * @param NodeList nodeList The NodeList. + * @param Function fn The iterate function. + * @return void + */ + _forEachNode: function(nodeList, fn) { + Array.prototype.forEach.call(nodeList, fn, this); + }, + + /** + * Iterate over a NodeList, and return the first node that passes + * the supplied test function + * + * For convenience, the current object context is applied to the provided + * test function. + * + * @param NodeList nodeList The NodeList. + * @param Function fn The test function. + * @return void + */ + _findNode: function(nodeList, fn) { + return Array.prototype.find.call(nodeList, fn, this); + }, + + /** + * Iterate over a NodeList, return true if any of the provided iterate + * function calls returns true, false otherwise. + * + * For convenience, the current object context is applied to the + * provided iterate function. + * + * @param NodeList nodeList The NodeList. + * @param Function fn The iterate function. + * @return Boolean + */ + _someNode: function(nodeList, fn) { + return Array.prototype.some.call(nodeList, fn, this); + }, + + /** + * Iterate over a NodeList, return true if all of the provided iterate + * function calls return true, false otherwise. + * + * For convenience, the current object context is applied to the + * provided iterate function. + * + * @param NodeList nodeList The NodeList. + * @param Function fn The iterate function. + * @return Boolean + */ + _everyNode: function(nodeList, fn) { + return Array.prototype.every.call(nodeList, fn, this); + }, + + /** + * Concat all nodelists passed as arguments. + * + * @return ...NodeList + * @return Array + */ + _concatNodeLists: function() { + var slice = Array.prototype.slice; + var args = slice.call(arguments); + var nodeLists = args.map(function(list) { + return slice.call(list); + }); + return Array.prototype.concat.apply([], nodeLists); + }, + + _getAllNodesWithTag: function(node, tagNames) { + if (node.querySelectorAll) { + return node.querySelectorAll(tagNames.join(",")); + } + return [].concat.apply([], tagNames.map(function(tag) { + var collection = node.getElementsByTagName(tag); + return Array.isArray(collection) ? collection : Array.from(collection); + })); + }, + + /** + * Removes the class="" attribute from every element in the given + * subtree, except those that match CLASSES_TO_PRESERVE and + * the classesToPreserve array from the options object. + * + * @param Element + * @return void + */ + _cleanClasses: function(node) { + var classesToPreserve = this._classesToPreserve; + var className = (node.getAttribute("class") || "") + .split(/\s+/) + .filter(function(cls) { + return classesToPreserve.indexOf(cls) != -1; + }) + .join(" "); + + if (className) { + node.setAttribute("class", className); + } else { + node.removeAttribute("class"); + } + + for (node = node.firstElementChild; node; node = node.nextElementSibling) { + this._cleanClasses(node); + } + }, + + /** + * Converts each <a> and <img> uri in the given element to an absolute URI, + * ignoring #ref URIs. + * + * @param Element + * @return void + */ + _fixRelativeUris: function(articleContent) { + var baseURI = this._doc.baseURI; + var documentURI = this._doc.documentURI; + function toAbsoluteURI(uri) { + // Leave hash links alone if the base URI matches the document URI: + if (baseURI == documentURI && uri.charAt(0) == "#") { + return uri; + } + + // Otherwise, resolve against base URI: + try { + return new URL(uri, baseURI).href; + } catch (ex) { + // Something went wrong, just return the original: + } + return uri; + } + + var links = this._getAllNodesWithTag(articleContent, ["a"]); + this._forEachNode(links, function(link) { + var href = link.getAttribute("href"); + if (href) { + // Remove links with javascript: URIs, since + // they won't work after scripts have been removed from the page. + if (href.indexOf("javascript:") === 0) { + // if the link only contains simple text content, it can be converted to a text node + if (link.childNodes.length === 1 && link.childNodes[0].nodeType === this.TEXT_NODE) { + var text = this._doc.createTextNode(link.textContent); + link.parentNode.replaceChild(text, link); + } else { + // if the link has multiple children, they should all be preserved + var container = this._doc.createElement("span"); + while (link.firstChild) { + container.appendChild(link.firstChild); + } + link.parentNode.replaceChild(container, link); + } + } else { + link.setAttribute("href", toAbsoluteURI(href)); + } + } + }); + + var medias = this._getAllNodesWithTag(articleContent, [ + "img", "picture", "figure", "video", "audio", "source" + ]); + + this._forEachNode(medias, function(media) { + var src = media.getAttribute("src"); + var poster = media.getAttribute("poster"); + var srcset = media.getAttribute("srcset"); + + if (src) { + media.setAttribute("src", toAbsoluteURI(src)); + } + + if (poster) { + media.setAttribute("poster", toAbsoluteURI(poster)); + } + + if (srcset) { + var newSrcset = srcset.replace(this.REGEXPS.srcsetUrl, function(_, p1, p2, p3) { + return toAbsoluteURI(p1) + (p2 || "") + p3; + }); + + media.setAttribute("srcset", newSrcset); + } + }); + }, + + _simplifyNestedElements: function(articleContent) { + var node = articleContent; + + while (node) { + if (node.parentNode && ["DIV", "SECTION"].includes(node.tagName) && !(node.id && node.id.startsWith("readability"))) { + if (this._isElementWithoutContent(node)) { + node = this._removeAndGetNext(node); + continue; + } else if (this._hasSingleTagInsideElement(node, "DIV") || this._hasSingleTagInsideElement(node, "SECTION")) { + var child = node.children[0]; + for (var i = 0; i < node.attributes.length; i++) { + child.setAttribute(node.attributes[i].name, node.attributes[i].value); + } + node.parentNode.replaceChild(child, node); + node = child; + continue; + } + } + + node = this._getNextNode(node); + } + }, + + /** + * Get the article title as an H1. + * + * @return string + **/ + _getArticleTitle: function() { + var doc = this._doc; + var curTitle = ""; + var origTitle = ""; + + try { + curTitle = origTitle = doc.title.trim(); + + // If they had an element with id "title" in their HTML + if (typeof curTitle !== "string") + curTitle = origTitle = this._getInnerText(doc.getElementsByTagName("title")[0]); + } catch (e) {/* ignore exceptions setting the title. */} + + var titleHadHierarchicalSeparators = false; + function wordCount(str) { + return str.split(/\s+/).length; + } + + // If there's a separator in the title, first remove the final part + if ((/ [\|\-\\\/>»] /).test(curTitle)) { + titleHadHierarchicalSeparators = / [\\\/>»] /.test(curTitle); + curTitle = origTitle.replace(/(.*)[\|\-\\\/>»] .*/gi, "$1"); + + // If the resulting title is too short (3 words or fewer), remove + // the first part instead: + if (wordCount(curTitle) < 3) + curTitle = origTitle.replace(/[^\|\-\\\/>»]*[\|\-\\\/>»](.*)/gi, "$1"); + } else if (curTitle.indexOf(": ") !== -1) { + // Check if we have an heading containing this exact string, so we + // could assume it's the full title. + var headings = this._concatNodeLists( + doc.getElementsByTagName("h1"), + doc.getElementsByTagName("h2") + ); + var trimmedTitle = curTitle.trim(); + var match = this._someNode(headings, function(heading) { + return heading.textContent.trim() === trimmedTitle; + }); + + // If we don't, let's extract the title out of the original title string. + if (!match) { + curTitle = origTitle.substring(origTitle.lastIndexOf(":") + 1); + + // If the title is now too short, try the first colon instead: + if (wordCount(curTitle) < 3) { + curTitle = origTitle.substring(origTitle.indexOf(":") + 1); + // But if we have too many words before the colon there's something weird + // with the titles and the H tags so let's just use the original title instead + } else if (wordCount(origTitle.substr(0, origTitle.indexOf(":"))) > 5) { + curTitle = origTitle; + } + } + } else if (curTitle.length > 150 || curTitle.length < 15) { + var hOnes = doc.getElementsByTagName("h1"); + + if (hOnes.length === 1) + curTitle = this._getInnerText(hOnes[0]); + } + + curTitle = curTitle.trim().replace(this.REGEXPS.normalize, " "); + // If we now have 4 words or fewer as our title, and either no + // 'hierarchical' separators (\, /, > or ») were found in the original + // title or we decreased the number of words by more than 1 word, use + // the original title. + var curTitleWordCount = wordCount(curTitle); + if (curTitleWordCount <= 4 && + (!titleHadHierarchicalSeparators || + curTitleWordCount != wordCount(origTitle.replace(/[\|\-\\\/>»]+/g, "")) - 1)) { + curTitle = origTitle; + } + + return curTitle; + }, + + /** + * Prepare the HTML document for readability to scrape it. + * This includes things like stripping javascript, CSS, and handling terrible markup. + * + * @return void + **/ + _prepDocument: function() { + var doc = this._doc; + + // Remove all style tags in head + this._removeNodes(this._getAllNodesWithTag(doc, ["style"])); + + if (doc.body) { + this._replaceBrs(doc.body); + } + + this._replaceNodeTags(this._getAllNodesWithTag(doc, ["font"]), "SPAN"); + }, + + /** + * Finds the next node, starting from the given node, and ignoring + * whitespace in between. If the given node is an element, the same node is + * returned. + */ + _nextNode: function (node) { + var next = node; + while (next + && (next.nodeType != this.ELEMENT_NODE) + && this.REGEXPS.whitespace.test(next.textContent)) { + next = next.nextSibling; + } + return next; + }, + + /** + * Replaces 2 or more successive <br> elements with a single <p>. + * Whitespace between <br> elements are ignored. For example: + * <div>foo<br>bar<br> <br><br>abc</div> + * will become: + * <div>foo<br>bar<p>abc</p></div> + */ + _replaceBrs: function (elem) { + this._forEachNode(this._getAllNodesWithTag(elem, ["br"]), function(br) { + var next = br.nextSibling; + + // Whether 2 or more <br> elements have been found and replaced with a + // <p> block. + var replaced = false; + + // If we find a <br> chain, remove the <br>s until we hit another node + // or non-whitespace. This leaves behind the first <br> in the chain + // (which will be replaced with a <p> later). + while ((next = this._nextNode(next)) && (next.tagName == "BR")) { + replaced = true; + var brSibling = next.nextSibling; + next.parentNode.removeChild(next); + next = brSibling; + } + + // If we removed a <br> chain, replace the remaining <br> with a <p>. Add + // all sibling nodes as children of the <p> until we hit another <br> + // chain. + if (replaced) { + var p = this._doc.createElement("p"); + br.parentNode.replaceChild(p, br); + + next = p.nextSibling; + while (next) { + // If we've hit another <br><br>, we're done adding children to this <p>. + if (next.tagName == "BR") { + var nextElem = this._nextNode(next.nextSibling); + if (nextElem && nextElem.tagName == "BR") + break; + } + + if (!this._isPhrasingContent(next)) + break; + + // Otherwise, make this node a child of the new <p>. + var sibling = next.nextSibling; + p.appendChild(next); + next = sibling; + } + + while (p.lastChild && this._isWhitespace(p.lastChild)) { + p.removeChild(p.lastChild); + } + + if (p.parentNode.tagName === "P") + this._setNodeTag(p.parentNode, "DIV"); + } + }); + }, + + _setNodeTag: function (node, tag) { + this.log("_setNodeTag", node, tag); + if (this._docJSDOMParser) { + node.localName = tag.toLowerCase(); + node.tagName = tag.toUpperCase(); + return node; + } + + var replacement = node.ownerDocument.createElement(tag); + while (node.firstChild) { + replacement.appendChild(node.firstChild); + } + node.parentNode.replaceChild(replacement, node); + if (node.readability) + replacement.readability = node.readability; + + for (var i = 0; i < node.attributes.length; i++) { + try { + replacement.setAttribute(node.attributes[i].name, node.attributes[i].value); + } catch (ex) { + /* it's possible for setAttribute() to throw if the attribute name + * isn't a valid XML Name. Such attributes can however be parsed from + * source in HTML docs, see https://github.com/whatwg/html/issues/4275, + * so we can hit them here and then throw. We don't care about such + * attributes so we ignore them. + */ + } + } + return replacement; + }, + + /** + * Prepare the article node for display. Clean out any inline styles, + * iframes, forms, strip extraneous <p> tags, etc. + * + * @param Element + * @return void + **/ + _prepArticle: function(articleContent) { + this._cleanStyles(articleContent); + + // Check for data tables before we continue, to avoid removing items in + // those tables, which will often be isolated even though they're + // visually linked to other content-ful elements (text, images, etc.). + this._markDataTables(articleContent); + + this._fixLazyImages(articleContent); + + // Clean out junk from the article content + this._cleanConditionally(articleContent, "form"); + this._cleanConditionally(articleContent, "fieldset"); + this._clean(articleContent, "object"); + this._clean(articleContent, "embed"); + this._clean(articleContent, "footer"); + this._clean(articleContent, "link"); + this._clean(articleContent, "aside"); + + // Clean out elements with little content that have "share" in their id/class combinations from final top candidates, + // which means we don't remove the top candidates even they have "share". + + var shareElementThreshold = this.DEFAULT_CHAR_THRESHOLD; + + this._forEachNode(articleContent.children, function (topCandidate) { + this._cleanMatchedNodes(topCandidate, function (node, matchString) { + return this.REGEXPS.shareElements.test(matchString) && node.textContent.length < shareElementThreshold; + }); + }); + + this._clean(articleContent, "iframe"); + this._clean(articleContent, "input"); + this._clean(articleContent, "textarea"); + this._clean(articleContent, "select"); + this._clean(articleContent, "button"); + this._cleanHeaders(articleContent); + + // Do these last as the previous stuff may have removed junk + // that will affect these + this._cleanConditionally(articleContent, "table"); + this._cleanConditionally(articleContent, "ul"); + this._cleanConditionally(articleContent, "div"); + + // replace H1 with H2 as H1 should be only title that is displayed separately + this._replaceNodeTags(this._getAllNodesWithTag(articleContent, ["h1"]), "h2"); + + // Remove extra paragraphs + this._removeNodes(this._getAllNodesWithTag(articleContent, ["p"]), function (paragraph) { + var imgCount = paragraph.getElementsByTagName("img").length; + var embedCount = paragraph.getElementsByTagName("embed").length; + var objectCount = paragraph.getElementsByTagName("object").length; + // At this point, nasty iframes have been removed, only remain embedded video ones. + var iframeCount = paragraph.getElementsByTagName("iframe").length; + var totalCount = imgCount + embedCount + objectCount + iframeCount; + + return totalCount === 0 && !this._getInnerText(paragraph, false); + }); + + this._forEachNode(this._getAllNodesWithTag(articleContent, ["br"]), function(br) { + var next = this._nextNode(br.nextSibling); + if (next && next.tagName == "P") + br.parentNode.removeChild(br); + }); + + // Remove single-cell tables + this._forEachNode(this._getAllNodesWithTag(articleContent, ["table"]), function(table) { + var tbody = this._hasSingleTagInsideElement(table, "TBODY") ? table.firstElementChild : table; + if (this._hasSingleTagInsideElement(tbody, "TR")) { + var row = tbody.firstElementChild; + if (this._hasSingleTagInsideElement(row, "TD")) { + var cell = row.firstElementChild; + cell = this._setNodeTag(cell, this._everyNode(cell.childNodes, this._isPhrasingContent) ? "P" : "DIV"); + table.parentNode.replaceChild(cell, table); + } + } + }); + }, + + /** + * Initialize a node with the readability object. Also checks the + * className/id for special names to add to its score. + * + * @param Element + * @return void + **/ + _initializeNode: function(node) { + node.readability = {"contentScore": 0}; + + switch (node.tagName) { + case "DIV": + node.readability.contentScore += 5; + break; + + case "PRE": + case "TD": + case "BLOCKQUOTE": + node.readability.contentScore += 3; + break; + + case "ADDRESS": + case "OL": + case "UL": + case "DL": + case "DD": + case "DT": + case "LI": + case "FORM": + node.readability.contentScore -= 3; + break; + + case "H1": + case "H2": + case "H3": + case "H4": + case "H5": + case "H6": + case "TH": + node.readability.contentScore -= 5; + break; + } + + node.readability.contentScore += this._getClassWeight(node); + }, + + _removeAndGetNext: function(node) { + var nextNode = this._getNextNode(node, true); + node.parentNode.removeChild(node); + return nextNode; + }, + + /** + * Traverse the DOM from node to node, starting at the node passed in. + * Pass true for the second parameter to indicate this node itself + * (and its kids) are going away, and we want the next node over. + * + * Calling this in a loop will traverse the DOM depth-first. + */ + _getNextNode: function(node, ignoreSelfAndKids) { + // First check for kids if those aren't being ignored + if (!ignoreSelfAndKids && node.firstElementChild) { + return node.firstElementChild; + } + // Then for siblings... + if (node.nextElementSibling) { + return node.nextElementSibling; + } + // And finally, move up the parent chain *and* find a sibling + // (because this is depth-first traversal, we will have already + // seen the parent nodes themselves). + do { + node = node.parentNode; + } while (node && !node.nextElementSibling); + return node && node.nextElementSibling; + }, + + // compares second text to first one + // 1 = same text, 0 = completely different text + // works the way that it splits both texts into words and then finds words that are unique in second text + // the result is given by the lower length of unique parts + _textSimilarity: function(textA, textB) { + var tokensA = textA.toLowerCase().split(this.REGEXPS.tokenize).filter(Boolean); + var tokensB = textB.toLowerCase().split(this.REGEXPS.tokenize).filter(Boolean); + if (!tokensA.length || !tokensB.length) { + return 0; + } + var uniqTokensB = tokensB.filter(token => !tokensA.includes(token)); + var distanceB = uniqTokensB.join(" ").length / tokensB.join(" ").length; + return 1 - distanceB; + }, + + _checkByline: function(node, matchString) { + if (this._articleByline) { + return false; + } + + if (node.getAttribute !== undefined) { + var rel = node.getAttribute("rel"); + var itemprop = node.getAttribute("itemprop"); + } + + if ((rel === "author" || (itemprop && itemprop.indexOf("author") !== -1) || this.REGEXPS.byline.test(matchString)) && this._isValidByline(node.textContent)) { + this._articleByline = node.textContent.trim(); + return true; + } + + return false; + }, + + _getNodeAncestors: function(node, maxDepth) { + maxDepth = maxDepth || 0; + var i = 0, ancestors = []; + while (node.parentNode) { + ancestors.push(node.parentNode); + if (maxDepth && ++i === maxDepth) + break; + node = node.parentNode; + } + return ancestors; + }, + + /*** + * grabArticle - Using a variety of metrics (content score, classname, element types), find the content that is + * most likely to be the stuff a user wants to read. Then return it wrapped up in a div. + * + * @param page a document to run upon. Needs to be a full document, complete with body. + * @return Element + **/ + _grabArticle: function (page) { + this.log("**** grabArticle ****"); + var doc = this._doc; + var isPaging = page !== null; + page = page ? page : this._doc.body; + + // We can't grab an article if we don't have a page! + if (!page) { + this.log("No body found in document. Abort."); + return null; + } + + var pageCacheHtml = page.innerHTML; + + while (true) { + this.log("Starting grabArticle loop"); + var stripUnlikelyCandidates = this._flagIsActive(this.FLAG_STRIP_UNLIKELYS); + + // First, node prepping. Trash nodes that look cruddy (like ones with the + // class name "comment", etc), and turn divs into P tags where they have been + // used inappropriately (as in, where they contain no other block level elements.) + var elementsToScore = []; + var node = this._doc.documentElement; + + let shouldRemoveTitleHeader = true; + + while (node) { + + if (node.tagName === "HTML") { + this._articleLang = node.getAttribute("lang"); + } + + var matchString = node.className + " " + node.id; + + if (!this._isProbablyVisible(node)) { + this.log("Removing hidden node - " + matchString); + node = this._removeAndGetNext(node); + continue; + } + + // User is not able to see elements applied with both "aria-modal = true" and "role = dialog" + if (node.getAttribute("aria-modal") == "true" && node.getAttribute("role") == "dialog") { + node = this._removeAndGetNext(node); + continue; + } + + // Check to see if this node is a byline, and remove it if it is. + if (this._checkByline(node, matchString)) { + node = this._removeAndGetNext(node); + continue; + } + + if (shouldRemoveTitleHeader && this._headerDuplicatesTitle(node)) { + this.log("Removing header: ", node.textContent.trim(), this._articleTitle.trim()); + shouldRemoveTitleHeader = false; + node = this._removeAndGetNext(node); + continue; + } + + // Remove unlikely candidates + if (stripUnlikelyCandidates) { + if (this.REGEXPS.unlikelyCandidates.test(matchString) && + !this.REGEXPS.okMaybeItsACandidate.test(matchString) && + !this._hasAncestorTag(node, "table") && + !this._hasAncestorTag(node, "code") && + node.tagName !== "BODY" && + node.tagName !== "A") { + this.log("Removing unlikely candidate - " + matchString); + node = this._removeAndGetNext(node); + continue; + } + + if (this.UNLIKELY_ROLES.includes(node.getAttribute("role"))) { + this.log("Removing content with role " + node.getAttribute("role") + " - " + matchString); + node = this._removeAndGetNext(node); + continue; + } + } + + // Remove DIV, SECTION, and HEADER nodes without any content(e.g. text, image, video, or iframe). + if ((node.tagName === "DIV" || node.tagName === "SECTION" || node.tagName === "HEADER" || + node.tagName === "H1" || node.tagName === "H2" || node.tagName === "H3" || + node.tagName === "H4" || node.tagName === "H5" || node.tagName === "H6") && + this._isElementWithoutContent(node)) { + node = this._removeAndGetNext(node); + continue; + } + + if (this.DEFAULT_TAGS_TO_SCORE.indexOf(node.tagName) !== -1) { + elementsToScore.push(node); + } + + // Turn all divs that don't have children block level elements into p's + if (node.tagName === "DIV") { + // Put phrasing content into paragraphs. + var p = null; + var childNode = node.firstChild; + while (childNode) { + var nextSibling = childNode.nextSibling; + if (this._isPhrasingContent(childNode)) { + if (p !== null) { + p.appendChild(childNode); + } else if (!this._isWhitespace(childNode)) { + p = doc.createElement("p"); + node.replaceChild(p, childNode); + p.appendChild(childNode); + } + } else if (p !== null) { + while (p.lastChild && this._isWhitespace(p.lastChild)) { + p.removeChild(p.lastChild); + } + p = null; + } + childNode = nextSibling; + } + + // Sites like http://mobile.slate.com encloses each paragraph with a DIV + // element. DIVs with only a P element inside and no text content can be + // safely converted into plain P elements to avoid confusing the scoring + // algorithm with DIVs with are, in practice, paragraphs. + if (this._hasSingleTagInsideElement(node, "P") && this._getLinkDensity(node) < 0.25) { + var newNode = node.children[0]; + node.parentNode.replaceChild(newNode, node); + node = newNode; + elementsToScore.push(node); + } else if (!this._hasChildBlockElement(node)) { + node = this._setNodeTag(node, "P"); + elementsToScore.push(node); + } + } + node = this._getNextNode(node); + } + + /** + * Loop through all paragraphs, and assign a score to them based on how content-y they look. + * Then add their score to their parent node. + * + * A score is determined by things like number of commas, class names, etc. Maybe eventually link density. + **/ + var candidates = []; + this._forEachNode(elementsToScore, function(elementToScore) { + if (!elementToScore.parentNode || typeof(elementToScore.parentNode.tagName) === "undefined") + return; + + // If this paragraph is less than 25 characters, don't even count it. + var innerText = this._getInnerText(elementToScore); + if (innerText.length < 25) + return; + + // Exclude nodes with no ancestor. + var ancestors = this._getNodeAncestors(elementToScore, 5); + if (ancestors.length === 0) + return; + + var contentScore = 0; + + // Add a point for the paragraph itself as a base. + contentScore += 1; + + // Add points for any commas within this paragraph. + contentScore += innerText.split(this.REGEXPS.commas).length; + + // For every 100 characters in this paragraph, add another point. Up to 3 points. + contentScore += Math.min(Math.floor(innerText.length / 100), 3); + + // Initialize and score ancestors. + this._forEachNode(ancestors, function(ancestor, level) { + if (!ancestor.tagName || !ancestor.parentNode || typeof(ancestor.parentNode.tagName) === "undefined") + return; + + if (typeof(ancestor.readability) === "undefined") { + this._initializeNode(ancestor); + candidates.push(ancestor); + } + + // Node score divider: + // - parent: 1 (no division) + // - grandparent: 2 + // - great grandparent+: ancestor level * 3 + if (level === 0) + var scoreDivider = 1; + else if (level === 1) + scoreDivider = 2; + else + scoreDivider = level * 3; + ancestor.readability.contentScore += contentScore / scoreDivider; + }); + }); + + // After we've calculated scores, loop through all of the possible + // candidate nodes we found and find the one with the highest score. + var topCandidates = []; + for (var c = 0, cl = candidates.length; c < cl; c += 1) { + var candidate = candidates[c]; + + // Scale the final candidates score based on link density. Good content + // should have a relatively small link density (5% or less) and be mostly + // unaffected by this operation. + var candidateScore = candidate.readability.contentScore * (1 - this._getLinkDensity(candidate)); + candidate.readability.contentScore = candidateScore; + + this.log("Candidate:", candidate, "with score " + candidateScore); + + for (var t = 0; t < this._nbTopCandidates; t++) { + var aTopCandidate = topCandidates[t]; + + if (!aTopCandidate || candidateScore > aTopCandidate.readability.contentScore) { + topCandidates.splice(t, 0, candidate); + if (topCandidates.length > this._nbTopCandidates) + topCandidates.pop(); + break; + } + } + } + + var topCandidate = topCandidates[0] || null; + var neededToCreateTopCandidate = false; + var parentOfTopCandidate; + + // If we still have no top candidate, just use the body as a last resort. + // We also have to copy the body node so it is something we can modify. + if (topCandidate === null || topCandidate.tagName === "BODY") { + // Move all of the page's children into topCandidate + topCandidate = doc.createElement("DIV"); + neededToCreateTopCandidate = true; + // Move everything (not just elements, also text nodes etc.) into the container + // so we even include text directly in the body: + while (page.firstChild) { + this.log("Moving child out:", page.firstChild); + topCandidate.appendChild(page.firstChild); + } + + page.appendChild(topCandidate); + + this._initializeNode(topCandidate); + } else if (topCandidate) { + // Find a better top candidate node if it contains (at least three) nodes which belong to `topCandidates` array + // and whose scores are quite closed with current `topCandidate` node. + var alternativeCandidateAncestors = []; + for (var i = 1; i < topCandidates.length; i++) { + if (topCandidates[i].readability.contentScore / topCandidate.readability.contentScore >= 0.75) { + alternativeCandidateAncestors.push(this._getNodeAncestors(topCandidates[i])); + } + } + var MINIMUM_TOPCANDIDATES = 3; + if (alternativeCandidateAncestors.length >= MINIMUM_TOPCANDIDATES) { + parentOfTopCandidate = topCandidate.parentNode; + while (parentOfTopCandidate.tagName !== "BODY") { + var listsContainingThisAncestor = 0; + for (var ancestorIndex = 0; ancestorIndex < alternativeCandidateAncestors.length && listsContainingThisAncestor < MINIMUM_TOPCANDIDATES; ancestorIndex++) { + listsContainingThisAncestor += Number(alternativeCandidateAncestors[ancestorIndex].includes(parentOfTopCandidate)); + } + if (listsContainingThisAncestor >= MINIMUM_TOPCANDIDATES) { + topCandidate = parentOfTopCandidate; + break; + } + parentOfTopCandidate = parentOfTopCandidate.parentNode; + } + } + if (!topCandidate.readability) { + this._initializeNode(topCandidate); + } + + // Because of our bonus system, parents of candidates might have scores + // themselves. They get half of the node. There won't be nodes with higher + // scores than our topCandidate, but if we see the score going *up* in the first + // few steps up the tree, that's a decent sign that there might be more content + // lurking in other places that we want to unify in. The sibling stuff + // below does some of that - but only if we've looked high enough up the DOM + // tree. + parentOfTopCandidate = topCandidate.parentNode; + var lastScore = topCandidate.readability.contentScore; + // The scores shouldn't get too low. + var scoreThreshold = lastScore / 3; + while (parentOfTopCandidate.tagName !== "BODY") { + if (!parentOfTopCandidate.readability) { + parentOfTopCandidate = parentOfTopCandidate.parentNode; + continue; + } + var parentScore = parentOfTopCandidate.readability.contentScore; + if (parentScore < scoreThreshold) + break; + if (parentScore > lastScore) { + // Alright! We found a better parent to use. + topCandidate = parentOfTopCandidate; + break; + } + lastScore = parentOfTopCandidate.readability.contentScore; + parentOfTopCandidate = parentOfTopCandidate.parentNode; + } + + // If the top candidate is the only child, use parent instead. This will help sibling + // joining logic when adjacent content is actually located in parent's sibling node. + parentOfTopCandidate = topCandidate.parentNode; + while (parentOfTopCandidate.tagName != "BODY" && parentOfTopCandidate.children.length == 1) { + topCandidate = parentOfTopCandidate; + parentOfTopCandidate = topCandidate.parentNode; + } + if (!topCandidate.readability) { + this._initializeNode(topCandidate); + } + } + + // Now that we have the top candidate, look through its siblings for content + // that might also be related. Things like preambles, content split by ads + // that we removed, etc. + var articleContent = doc.createElement("DIV"); + if (isPaging) + articleContent.id = "readability-content"; + + var siblingScoreThreshold = Math.max(10, topCandidate.readability.contentScore * 0.2); + // Keep potential top candidate's parent node to try to get text direction of it later. + parentOfTopCandidate = topCandidate.parentNode; + var siblings = parentOfTopCandidate.children; + + for (var s = 0, sl = siblings.length; s < sl; s++) { + var sibling = siblings[s]; + var append = false; + + this.log("Looking at sibling node:", sibling, sibling.readability ? ("with score " + sibling.readability.contentScore) : ""); + this.log("Sibling has score", sibling.readability ? sibling.readability.contentScore : "Unknown"); + + if (sibling === topCandidate) { + append = true; + } else { + var contentBonus = 0; + + // Give a bonus if sibling nodes and top candidates have the example same classname + if (sibling.className === topCandidate.className && topCandidate.className !== "") + contentBonus += topCandidate.readability.contentScore * 0.2; + + if (sibling.readability && + ((sibling.readability.contentScore + contentBonus) >= siblingScoreThreshold)) { + append = true; + } else if (sibling.nodeName === "P") { + var linkDensity = this._getLinkDensity(sibling); + var nodeContent = this._getInnerText(sibling); + var nodeLength = nodeContent.length; + + if (nodeLength > 80 && linkDensity < 0.25) { + append = true; + } else if (nodeLength < 80 && nodeLength > 0 && linkDensity === 0 && + nodeContent.search(/\.( |$)/) !== -1) { + append = true; + } + } + } + + if (append) { + this.log("Appending node:", sibling); + + if (this.ALTER_TO_DIV_EXCEPTIONS.indexOf(sibling.nodeName) === -1) { + // We have a node that isn't a common block level element, like a form or td tag. + // Turn it into a div so it doesn't get filtered out later by accident. + this.log("Altering sibling:", sibling, "to div."); + + sibling = this._setNodeTag(sibling, "DIV"); + } + + articleContent.appendChild(sibling); + // Fetch children again to make it compatible + // with DOM parsers without live collection support. + siblings = parentOfTopCandidate.children; + // siblings is a reference to the children array, and + // sibling is removed from the array when we call appendChild(). + // As a result, we must revisit this index since the nodes + // have been shifted. + s -= 1; + sl -= 1; + } + } + + if (this._debug) + this.log("Article content pre-prep: " + articleContent.innerHTML); + // So we have all of the content that we need. Now we clean it up for presentation. + this._prepArticle(articleContent); + if (this._debug) + this.log("Article content post-prep: " + articleContent.innerHTML); + + if (neededToCreateTopCandidate) { + // We already created a fake div thing, and there wouldn't have been any siblings left + // for the previous loop, so there's no point trying to create a new div, and then + // move all the children over. Just assign IDs and class names here. No need to append + // because that already happened anyway. + topCandidate.id = "readability-page-1"; + topCandidate.className = "page"; + } else { + var div = doc.createElement("DIV"); + div.id = "readability-page-1"; + div.className = "page"; + while (articleContent.firstChild) { + div.appendChild(articleContent.firstChild); + } + articleContent.appendChild(div); + } + + if (this._debug) + this.log("Article content after paging: " + articleContent.innerHTML); + + var parseSuccessful = true; + + // Now that we've gone through the full algorithm, check to see if + // we got any meaningful content. If we didn't, we may need to re-run + // grabArticle with different flags set. This gives us a higher likelihood of + // finding the content, and the sieve approach gives us a higher likelihood of + // finding the -right- content. + var textLength = this._getInnerText(articleContent, true).length; + if (textLength < this._charThreshold) { + parseSuccessful = false; + page.innerHTML = pageCacheHtml; + + if (this._flagIsActive(this.FLAG_STRIP_UNLIKELYS)) { + this._removeFlag(this.FLAG_STRIP_UNLIKELYS); + this._attempts.push({articleContent: articleContent, textLength: textLength}); + } else if (this._flagIsActive(this.FLAG_WEIGHT_CLASSES)) { + this._removeFlag(this.FLAG_WEIGHT_CLASSES); + this._attempts.push({articleContent: articleContent, textLength: textLength}); + } else if (this._flagIsActive(this.FLAG_CLEAN_CONDITIONALLY)) { + this._removeFlag(this.FLAG_CLEAN_CONDITIONALLY); + this._attempts.push({articleContent: articleContent, textLength: textLength}); + } else { + this._attempts.push({articleContent: articleContent, textLength: textLength}); + // No luck after removing flags, just return the longest text we found during the different loops + this._attempts.sort(function (a, b) { + return b.textLength - a.textLength; + }); + + // But first check if we actually have something + if (!this._attempts[0].textLength) { + return null; + } + + articleContent = this._attempts[0].articleContent; + parseSuccessful = true; + } + } + + if (parseSuccessful) { + // Find out text direction from ancestors of final top candidate. + var ancestors = [parentOfTopCandidate, topCandidate].concat(this._getNodeAncestors(parentOfTopCandidate)); + this._someNode(ancestors, function(ancestor) { + if (!ancestor.tagName) + return false; + var articleDir = ancestor.getAttribute("dir"); + if (articleDir) { + this._articleDir = articleDir; + return true; + } + return false; + }); + return articleContent; + } + } + }, + + /** + * Check whether the input string could be a byline. + * This verifies that the input is a string, and that the length + * is less than 100 chars. + * + * @param possibleByline {string} - a string to check whether its a byline. + * @return Boolean - whether the input string is a byline. + */ + _isValidByline: function(byline) { + if (typeof byline == "string" || byline instanceof String) { + byline = byline.trim(); + return (byline.length > 0) && (byline.length < 100); + } + return false; + }, + + /** + * Converts some of the common HTML entities in string to their corresponding characters. + * + * @param str {string} - a string to unescape. + * @return string without HTML entity. + */ + _unescapeHtmlEntities: function(str) { + if (!str) { + return str; + } + + var htmlEscapeMap = this.HTML_ESCAPE_MAP; + return str.replace(/&(quot|amp|apos|lt|gt);/g, function(_, tag) { + return htmlEscapeMap[tag]; + }).replace(/&#(?:x([0-9a-z]{1,4})|([0-9]{1,4}));/gi, function(_, hex, numStr) { + var num = parseInt(hex || numStr, hex ? 16 : 10); + return String.fromCharCode(num); + }); + }, + + /** + * Try to extract metadata from JSON-LD object. + * For now, only Schema.org objects of type Article or its subtypes are supported. + * @return Object with any metadata that could be extracted (possibly none) + */ + _getJSONLD: function (doc) { + var scripts = this._getAllNodesWithTag(doc, ["script"]); + + var metadata; + + this._forEachNode(scripts, function(jsonLdElement) { + if (!metadata && jsonLdElement.getAttribute("type") === "application/ld+json") { + try { + // Strip CDATA markers if present + var content = jsonLdElement.textContent.replace(/^\s*<!\[CDATA\[|\]\]>\s*$/g, ""); + var parsed = JSON.parse(content); + if ( + !parsed["@context"] || + !parsed["@context"].match(/^https?\:\/\/schema\.org$/) + ) { + return; + } + + if (!parsed["@type"] && Array.isArray(parsed["@graph"])) { + parsed = parsed["@graph"].find(function(it) { + return (it["@type"] || "").match( + this.REGEXPS.jsonLdArticleTypes + ); + }); + } + + if ( + !parsed || + !parsed["@type"] || + !parsed["@type"].match(this.REGEXPS.jsonLdArticleTypes) + ) { + return; + } + + metadata = {}; + + if (typeof parsed.name === "string" && typeof parsed.headline === "string" && parsed.name !== parsed.headline) { + // we have both name and headline element in the JSON-LD. They should both be the same but some websites like aktualne.cz + // put their own name into "name" and the article title to "headline" which confuses Readability. So we try to check if either + // "name" or "headline" closely matches the html title, and if so, use that one. If not, then we use "name" by default. + + var title = this._getArticleTitle(); + var nameMatches = this._textSimilarity(parsed.name, title) > 0.75; + var headlineMatches = this._textSimilarity(parsed.headline, title) > 0.75; + + if (headlineMatches && !nameMatches) { + metadata.title = parsed.headline; + } else { + metadata.title = parsed.name; + } + } else if (typeof parsed.name === "string") { + metadata.title = parsed.name.trim(); + } else if (typeof parsed.headline === "string") { + metadata.title = parsed.headline.trim(); + } + if (parsed.author) { + if (typeof parsed.author.name === "string") { + metadata.byline = parsed.author.name.trim(); + } else if (Array.isArray(parsed.author) && parsed.author[0] && typeof parsed.author[0].name === "string") { + metadata.byline = parsed.author + .filter(function(author) { + return author && typeof author.name === "string"; + }) + .map(function(author) { + return author.name.trim(); + }) + .join(", "); + } + } + if (typeof parsed.description === "string") { + metadata.excerpt = parsed.description.trim(); + } + if ( + parsed.publisher && + typeof parsed.publisher.name === "string" + ) { + metadata.siteName = parsed.publisher.name.trim(); + } + if (typeof parsed.datePublished === "string") { + metadata.datePublished = parsed.datePublished.trim(); + } + return; + } catch (err) { + this.log(err.message); + } + } + }); + return metadata ? metadata : {}; + }, + + /** + * Attempts to get excerpt and byline metadata for the article. + * + * @param {Object} jsonld — object containing any metadata that + * could be extracted from JSON-LD object. + * + * @return Object with optional "excerpt" and "byline" properties + */ + _getArticleMetadata: function(jsonld) { + var metadata = {}; + var values = {}; + var metaElements = this._doc.getElementsByTagName("meta"); + + // property is a space-separated list of values + var propertyPattern = /\s*(article|dc|dcterm|og|twitter)\s*:\s*(author|creator|description|published_time|title|site_name)\s*/gi; + + // name is a single value + var namePattern = /^\s*(?:(dc|dcterm|og|twitter|weibo:(article|webpage))\s*[\.:]\s*)?(author|creator|description|title|site_name)\s*$/i; + + // Find description tags. + this._forEachNode(metaElements, function(element) { + var elementName = element.getAttribute("name"); + var elementProperty = element.getAttribute("property"); + var content = element.getAttribute("content"); + if (!content) { + return; + } + var matches = null; + var name = null; + + if (elementProperty) { + matches = elementProperty.match(propertyPattern); + if (matches) { + // Convert to lowercase, and remove any whitespace + // so we can match below. + name = matches[0].toLowerCase().replace(/\s/g, ""); + // multiple authors + values[name] = content.trim(); + } + } + if (!matches && elementName && namePattern.test(elementName)) { + name = elementName; + if (content) { + // Convert to lowercase, remove any whitespace, and convert dots + // to colons so we can match below. + name = name.toLowerCase().replace(/\s/g, "").replace(/\./g, ":"); + values[name] = content.trim(); + } + } + }); + + // get title + metadata.title = jsonld.title || + values["dc:title"] || + values["dcterm:title"] || + values["og:title"] || + values["weibo:article:title"] || + values["weibo:webpage:title"] || + values["title"] || + values["twitter:title"]; + + if (!metadata.title) { + metadata.title = this._getArticleTitle(); + } + + // get author + metadata.byline = jsonld.byline || + values["dc:creator"] || + values["dcterm:creator"] || + values["author"]; + + // get description + metadata.excerpt = jsonld.excerpt || + values["dc:description"] || + values["dcterm:description"] || + values["og:description"] || + values["weibo:article:description"] || + values["weibo:webpage:description"] || + values["description"] || + values["twitter:description"]; + + // get site name + metadata.siteName = jsonld.siteName || + values["og:site_name"]; + + // get article published time + metadata.publishedTime = jsonld.datePublished || + values["article:published_time"] || null; + + // in many sites the meta value is escaped with HTML entities, + // so here we need to unescape it + metadata.title = this._unescapeHtmlEntities(metadata.title); + metadata.byline = this._unescapeHtmlEntities(metadata.byline); + metadata.excerpt = this._unescapeHtmlEntities(metadata.excerpt); + metadata.siteName = this._unescapeHtmlEntities(metadata.siteName); + metadata.publishedTime = this._unescapeHtmlEntities(metadata.publishedTime); + + return metadata; + }, + + /** + * Check if node is image, or if node contains exactly only one image + * whether as a direct child or as its descendants. + * + * @param Element + **/ + _isSingleImage: function(node) { + if (node.tagName === "IMG") { + return true; + } + + if (node.children.length !== 1 || node.textContent.trim() !== "") { + return false; + } + + return this._isSingleImage(node.children[0]); + }, + + /** + * Find all <noscript> that are located after <img> nodes, and which contain only one + * <img> element. Replace the first image with the image from inside the <noscript> tag, + * and remove the <noscript> tag. This improves the quality of the images we use on + * some sites (e.g. Medium). + * + * @param Element + **/ + _unwrapNoscriptImages: function(doc) { + // Find img without source or attributes that might contains image, and remove it. + // This is done to prevent a placeholder img is replaced by img from noscript in next step. + var imgs = Array.from(doc.getElementsByTagName("img")); + this._forEachNode(imgs, function(img) { + for (var i = 0; i < img.attributes.length; i++) { + var attr = img.attributes[i]; + switch (attr.name) { + case "src": + case "srcset": + case "data-src": + case "data-srcset": + return; + } + + if (/\.(jpg|jpeg|png|webp)/i.test(attr.value)) { + return; + } + } + + img.parentNode.removeChild(img); + }); + + // Next find noscript and try to extract its image + var noscripts = Array.from(doc.getElementsByTagName("noscript")); + this._forEachNode(noscripts, function(noscript) { + // Parse content of noscript and make sure it only contains image + var tmp = doc.createElement("div"); + tmp.innerHTML = noscript.innerHTML; + if (!this._isSingleImage(tmp)) { + return; + } + + // If noscript has previous sibling and it only contains image, + // replace it with noscript content. However we also keep old + // attributes that might contains image. + var prevElement = noscript.previousElementSibling; + if (prevElement && this._isSingleImage(prevElement)) { + var prevImg = prevElement; + if (prevImg.tagName !== "IMG") { + prevImg = prevElement.getElementsByTagName("img")[0]; + } + + var newImg = tmp.getElementsByTagName("img")[0]; + for (var i = 0; i < prevImg.attributes.length; i++) { + var attr = prevImg.attributes[i]; + if (attr.value === "") { + continue; + } + + if (attr.name === "src" || attr.name === "srcset" || /\.(jpg|jpeg|png|webp)/i.test(attr.value)) { + if (newImg.getAttribute(attr.name) === attr.value) { + continue; + } + + var attrName = attr.name; + if (newImg.hasAttribute(attrName)) { + attrName = "data-old-" + attrName; + } + + newImg.setAttribute(attrName, attr.value); + } + } + + noscript.parentNode.replaceChild(tmp.firstElementChild, prevElement); + } + }); + }, + + /** + * Removes script tags from the document. + * + * @param Element + **/ + _removeScripts: function(doc) { + this._removeNodes(this._getAllNodesWithTag(doc, ["script", "noscript"])); + }, + + /** + * Check if this node has only whitespace and a single element with given tag + * Returns false if the DIV node contains non-empty text nodes + * or if it contains no element with given tag or more than 1 element. + * + * @param Element + * @param string tag of child element + **/ + _hasSingleTagInsideElement: function(element, tag) { + // There should be exactly 1 element child with given tag + if (element.children.length != 1 || element.children[0].tagName !== tag) { + return false; + } + + // And there should be no text nodes with real content + return !this._someNode(element.childNodes, function(node) { + return node.nodeType === this.TEXT_NODE && + this.REGEXPS.hasContent.test(node.textContent); + }); + }, + + _isElementWithoutContent: function(node) { + return node.nodeType === this.ELEMENT_NODE && + node.textContent.trim().length == 0 && + (node.children.length == 0 || + node.children.length == node.getElementsByTagName("br").length + node.getElementsByTagName("hr").length); + }, + + /** + * Determine whether element has any children block level elements. + * + * @param Element + */ + _hasChildBlockElement: function (element) { + return this._someNode(element.childNodes, function(node) { + return this.DIV_TO_P_ELEMS.has(node.tagName) || + this._hasChildBlockElement(node); + }); + }, + + /*** + * Determine if a node qualifies as phrasing content. + * https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Phrasing_content + **/ + _isPhrasingContent: function(node) { + return node.nodeType === this.TEXT_NODE || this.PHRASING_ELEMS.indexOf(node.tagName) !== -1 || + ((node.tagName === "A" || node.tagName === "DEL" || node.tagName === "INS") && + this._everyNode(node.childNodes, this._isPhrasingContent)); + }, + + _isWhitespace: function(node) { + return (node.nodeType === this.TEXT_NODE && node.textContent.trim().length === 0) || + (node.nodeType === this.ELEMENT_NODE && node.tagName === "BR"); + }, + + /** + * Get the inner text of a node - cross browser compatibly. + * This also strips out any excess whitespace to be found. + * + * @param Element + * @param Boolean normalizeSpaces (default: true) + * @return string + **/ + _getInnerText: function(e, normalizeSpaces) { + normalizeSpaces = (typeof normalizeSpaces === "undefined") ? true : normalizeSpaces; + var textContent = e.textContent.trim(); + + if (normalizeSpaces) { + return textContent.replace(this.REGEXPS.normalize, " "); + } + return textContent; + }, + + /** + * Get the number of times a string s appears in the node e. + * + * @param Element + * @param string - what to split on. Default is "," + * @return number (integer) + **/ + _getCharCount: function(e, s) { + s = s || ","; + return this._getInnerText(e).split(s).length - 1; + }, + + /** + * Remove the style attribute on every e and under. + * TODO: Test if getElementsByTagName(*) is faster. + * + * @param Element + * @return void + **/ + _cleanStyles: function(e) { + if (!e || e.tagName.toLowerCase() === "svg") + return; + + // Remove `style` and deprecated presentational attributes + for (var i = 0; i < this.PRESENTATIONAL_ATTRIBUTES.length; i++) { + e.removeAttribute(this.PRESENTATIONAL_ATTRIBUTES[i]); + } + + if (this.DEPRECATED_SIZE_ATTRIBUTE_ELEMS.indexOf(e.tagName) !== -1) { + e.removeAttribute("width"); + e.removeAttribute("height"); + } + + var cur = e.firstElementChild; + while (cur !== null) { + this._cleanStyles(cur); + cur = cur.nextElementSibling; + } + }, + + /** + * Get the density of links as a percentage of the content + * This is the amount of text that is inside a link divided by the total text in the node. + * + * @param Element + * @return number (float) + **/ + _getLinkDensity: function(element) { + var textLength = this._getInnerText(element).length; + if (textLength === 0) + return 0; + + var linkLength = 0; + + // XXX implement _reduceNodeList? + this._forEachNode(element.getElementsByTagName("a"), function(linkNode) { + var href = linkNode.getAttribute("href"); + var coefficient = href && this.REGEXPS.hashUrl.test(href) ? 0.3 : 1; + linkLength += this._getInnerText(linkNode).length * coefficient; + }); + + return linkLength / textLength; + }, + + /** + * Get an elements class/id weight. Uses regular expressions to tell if this + * element looks good or bad. + * + * @param Element + * @return number (Integer) + **/ + _getClassWeight: function(e) { + if (!this._flagIsActive(this.FLAG_WEIGHT_CLASSES)) + return 0; + + var weight = 0; + + // Look for a special classname + if (typeof(e.className) === "string" && e.className !== "") { + if (this.REGEXPS.negative.test(e.className)) + weight -= 25; + + if (this.REGEXPS.positive.test(e.className)) + weight += 25; + } + + // Look for a special ID + if (typeof(e.id) === "string" && e.id !== "") { + if (this.REGEXPS.negative.test(e.id)) + weight -= 25; + + if (this.REGEXPS.positive.test(e.id)) + weight += 25; + } + + return weight; + }, + + /** + * Clean a node of all elements of type "tag". + * (Unless it's a youtube/vimeo video. People love movies.) + * + * @param Element + * @param string tag to clean + * @return void + **/ + _clean: function(e, tag) { + var isEmbed = ["object", "embed", "iframe"].indexOf(tag) !== -1; + + this._removeNodes(this._getAllNodesWithTag(e, [tag]), function(element) { + // Allow youtube and vimeo videos through as people usually want to see those. + if (isEmbed) { + // First, check the elements attributes to see if any of them contain youtube or vimeo + for (var i = 0; i < element.attributes.length; i++) { + if (this._allowedVideoRegex.test(element.attributes[i].value)) { + return false; + } + } + + // For embed with <object> tag, check inner HTML as well. + if (element.tagName === "object" && this._allowedVideoRegex.test(element.innerHTML)) { + return false; + } + } + + return true; + }); + }, + + /** + * Check if a given node has one of its ancestor tag name matching the + * provided one. + * @param HTMLElement node + * @param String tagName + * @param Number maxDepth + * @param Function filterFn a filter to invoke to determine whether this node 'counts' + * @return Boolean + */ + _hasAncestorTag: function(node, tagName, maxDepth, filterFn) { + maxDepth = maxDepth || 3; + tagName = tagName.toUpperCase(); + var depth = 0; + while (node.parentNode) { + if (maxDepth > 0 && depth > maxDepth) + return false; + if (node.parentNode.tagName === tagName && (!filterFn || filterFn(node.parentNode))) + return true; + node = node.parentNode; + depth++; + } + return false; + }, + + /** + * Return an object indicating how many rows and columns this table has. + */ + _getRowAndColumnCount: function(table) { + var rows = 0; + var columns = 0; + var trs = table.getElementsByTagName("tr"); + for (var i = 0; i < trs.length; i++) { + var rowspan = trs[i].getAttribute("rowspan") || 0; + if (rowspan) { + rowspan = parseInt(rowspan, 10); + } + rows += (rowspan || 1); + + // Now look for column-related info + var columnsInThisRow = 0; + var cells = trs[i].getElementsByTagName("td"); + for (var j = 0; j < cells.length; j++) { + var colspan = cells[j].getAttribute("colspan") || 0; + if (colspan) { + colspan = parseInt(colspan, 10); + } + columnsInThisRow += (colspan || 1); + } + columns = Math.max(columns, columnsInThisRow); + } + return {rows: rows, columns: columns}; + }, + + /** + * Look for 'data' (as opposed to 'layout') tables, for which we use + * similar checks as + * https://searchfox.org/mozilla-central/rev/f82d5c549f046cb64ce5602bfd894b7ae807c8f8/accessible/generic/TableAccessible.cpp#19 + */ + _markDataTables: function(root) { + var tables = root.getElementsByTagName("table"); + for (var i = 0; i < tables.length; i++) { + var table = tables[i]; + var role = table.getAttribute("role"); + if (role == "presentation") { + table._readabilityDataTable = false; + continue; + } + var datatable = table.getAttribute("datatable"); + if (datatable == "0") { + table._readabilityDataTable = false; + continue; + } + var summary = table.getAttribute("summary"); + if (summary) { + table._readabilityDataTable = true; + continue; + } + + var caption = table.getElementsByTagName("caption")[0]; + if (caption && caption.childNodes.length > 0) { + table._readabilityDataTable = true; + continue; + } + + // If the table has a descendant with any of these tags, consider a data table: + var dataTableDescendants = ["col", "colgroup", "tfoot", "thead", "th"]; + var descendantExists = function(tag) { + return !!table.getElementsByTagName(tag)[0]; + }; + if (dataTableDescendants.some(descendantExists)) { + this.log("Data table because found data-y descendant"); + table._readabilityDataTable = true; + continue; + } + + // Nested tables indicate a layout table: + if (table.getElementsByTagName("table")[0]) { + table._readabilityDataTable = false; + continue; + } + + var sizeInfo = this._getRowAndColumnCount(table); + if (sizeInfo.rows >= 10 || sizeInfo.columns > 4) { + table._readabilityDataTable = true; + continue; + } + // Now just go by size entirely: + table._readabilityDataTable = sizeInfo.rows * sizeInfo.columns > 10; + } + }, + + /* convert images and figures that have properties like data-src into images that can be loaded without JS */ + _fixLazyImages: function (root) { + this._forEachNode(this._getAllNodesWithTag(root, ["img", "picture", "figure"]), function (elem) { + // In some sites (e.g. Kotaku), they put 1px square image as base64 data uri in the src attribute. + // So, here we check if the data uri is too short, just might as well remove it. + if (elem.src && this.REGEXPS.b64DataUrl.test(elem.src)) { + // Make sure it's not SVG, because SVG can have a meaningful image in under 133 bytes. + var parts = this.REGEXPS.b64DataUrl.exec(elem.src); + if (parts[1] === "image/svg+xml") { + return; + } + + // Make sure this element has other attributes which contains image. + // If it doesn't, then this src is important and shouldn't be removed. + var srcCouldBeRemoved = false; + for (var i = 0; i < elem.attributes.length; i++) { + var attr = elem.attributes[i]; + if (attr.name === "src") { + continue; + } + + if (/\.(jpg|jpeg|png|webp)/i.test(attr.value)) { + srcCouldBeRemoved = true; + break; + } + } + + // Here we assume if image is less than 100 bytes (or 133B after encoded to base64) + // it will be too small, therefore it might be placeholder image. + if (srcCouldBeRemoved) { + var b64starts = elem.src.search(/base64\s*/i) + 7; + var b64length = elem.src.length - b64starts; + if (b64length < 133) { + elem.removeAttribute("src"); + } + } + } + + // also check for "null" to work around https://github.com/jsdom/jsdom/issues/2580 + if ((elem.src || (elem.srcset && elem.srcset != "null")) && elem.className.toLowerCase().indexOf("lazy") === -1) { + return; + } + + for (var j = 0; j < elem.attributes.length; j++) { + attr = elem.attributes[j]; + if (attr.name === "src" || attr.name === "srcset" || attr.name === "alt") { + continue; + } + var copyTo = null; + if (/\.(jpg|jpeg|png|webp)\s+\d/.test(attr.value)) { + copyTo = "srcset"; + } else if (/^\s*\S+\.(jpg|jpeg|png|webp)\S*\s*$/.test(attr.value)) { + copyTo = "src"; + } + if (copyTo) { + //if this is an img or picture, set the attribute directly + if (elem.tagName === "IMG" || elem.tagName === "PICTURE") { + elem.setAttribute(copyTo, attr.value); + } else if (elem.tagName === "FIGURE" && !this._getAllNodesWithTag(elem, ["img", "picture"]).length) { + //if the item is a <figure> that does not contain an image or picture, create one and place it inside the figure + //see the nytimes-3 testcase for an example + var img = this._doc.createElement("img"); + img.setAttribute(copyTo, attr.value); + elem.appendChild(img); + } + } + } + }); + }, + + _getTextDensity: function(e, tags) { + var textLength = this._getInnerText(e, true).length; + if (textLength === 0) { + return 0; + } + var childrenLength = 0; + var children = this._getAllNodesWithTag(e, tags); + this._forEachNode(children, (child) => childrenLength += this._getInnerText(child, true).length); + return childrenLength / textLength; + }, + + /** + * Clean an element of all tags of type "tag" if they look fishy. + * "Fishy" is an algorithm based on content length, classnames, link density, number of images & embeds, etc. + * + * @return void + **/ + _cleanConditionally: function(e, tag) { + if (!this._flagIsActive(this.FLAG_CLEAN_CONDITIONALLY)) + return; + + // Gather counts for other typical elements embedded within. + // Traverse backwards so we can remove nodes at the same time + // without effecting the traversal. + // + // TODO: Consider taking into account original contentScore here. + this._removeNodes(this._getAllNodesWithTag(e, [tag]), function(node) { + // First check if this node IS data table, in which case don't remove it. + var isDataTable = function(t) { + return t._readabilityDataTable; + }; + + var isList = tag === "ul" || tag === "ol"; + if (!isList) { + var listLength = 0; + var listNodes = this._getAllNodesWithTag(node, ["ul", "ol"]); + this._forEachNode(listNodes, (list) => listLength += this._getInnerText(list).length); + isList = listLength / this._getInnerText(node).length > 0.9; + } + + if (tag === "table" && isDataTable(node)) { + return false; + } + + // Next check if we're inside a data table, in which case don't remove it as well. + if (this._hasAncestorTag(node, "table", -1, isDataTable)) { + return false; + } + + if (this._hasAncestorTag(node, "code")) { + return false; + } + + var weight = this._getClassWeight(node); + + this.log("Cleaning Conditionally", node); + + var contentScore = 0; + + if (weight + contentScore < 0) { + return true; + } + + if (this._getCharCount(node, ",") < 10) { + // If there are not very many commas, and the number of + // non-paragraph elements is more than paragraphs or other + // ominous signs, remove the element. + var p = node.getElementsByTagName("p").length; + var img = node.getElementsByTagName("img").length; + var li = node.getElementsByTagName("li").length - 100; + var input = node.getElementsByTagName("input").length; + var headingDensity = this._getTextDensity(node, ["h1", "h2", "h3", "h4", "h5", "h6"]); + + var embedCount = 0; + var embeds = this._getAllNodesWithTag(node, ["object", "embed", "iframe"]); + + for (var i = 0; i < embeds.length; i++) { + // If this embed has attribute that matches video regex, don't delete it. + for (var j = 0; j < embeds[i].attributes.length; j++) { + if (this._allowedVideoRegex.test(embeds[i].attributes[j].value)) { + return false; + } + } + + // For embed with <object> tag, check inner HTML as well. + if (embeds[i].tagName === "object" && this._allowedVideoRegex.test(embeds[i].innerHTML)) { + return false; + } + + embedCount++; + } + + var linkDensity = this._getLinkDensity(node); + var contentLength = this._getInnerText(node).length; + + var haveToRemove = + (img > 1 && p / img < 0.5 && !this._hasAncestorTag(node, "figure")) || + (!isList && li > p) || + (input > Math.floor(p/3)) || + (!isList && headingDensity < 0.9 && contentLength < 25 && (img === 0 || img > 2) && !this._hasAncestorTag(node, "figure")) || + (!isList && weight < 25 && linkDensity > 0.2) || + (weight >= 25 && linkDensity > 0.5) || + ((embedCount === 1 && contentLength < 75) || embedCount > 1); + // Allow simple lists of images to remain in pages + if (isList && haveToRemove) { + for (var x = 0; x < node.children.length; x++) { + let child = node.children[x]; + // Don't filter in lists with li's that contain more than one child + if (child.children.length > 1) { + return haveToRemove; + } + } + let li_count = node.getElementsByTagName("li").length; + // Only allow the list to remain if every li contains an image + if (img == li_count) { + return false; + } + } + return haveToRemove; + } + return false; + }); + }, + + /** + * Clean out elements that match the specified conditions + * + * @param Element + * @param Function determines whether a node should be removed + * @return void + **/ + _cleanMatchedNodes: function(e, filter) { + var endOfSearchMarkerNode = this._getNextNode(e, true); + var next = this._getNextNode(e); + while (next && next != endOfSearchMarkerNode) { + if (filter.call(this, next, next.className + " " + next.id)) { + next = this._removeAndGetNext(next); + } else { + next = this._getNextNode(next); + } + } + }, + + /** + * Clean out spurious headers from an Element. + * + * @param Element + * @return void + **/ + _cleanHeaders: function(e) { + let headingNodes = this._getAllNodesWithTag(e, ["h1", "h2"]); + this._removeNodes(headingNodes, function(node) { + let shouldRemove = this._getClassWeight(node) < 0; + if (shouldRemove) { + this.log("Removing header with low class weight:", node); + } + return shouldRemove; + }); + }, + + /** + * Check if this node is an H1 or H2 element whose content is mostly + * the same as the article title. + * + * @param Element the node to check. + * @return boolean indicating whether this is a title-like header. + */ + _headerDuplicatesTitle: function(node) { + if (node.tagName != "H1" && node.tagName != "H2") { + return false; + } + var heading = this._getInnerText(node, false); + this.log("Evaluating similarity of header:", heading, this._articleTitle); + return this._textSimilarity(this._articleTitle, heading) > 0.75; + }, + + _flagIsActive: function(flag) { + return (this._flags & flag) > 0; + }, + + _removeFlag: function(flag) { + this._flags = this._flags & ~flag; + }, + + _isProbablyVisible: function(node) { + // Have to null-check node.style and node.className.indexOf to deal with SVG and MathML nodes. + return (!node.style || node.style.display != "none") + && (!node.style || node.style.visibility != "hidden") + && !node.hasAttribute("hidden") + //check for "fallback-image" so that wikimedia math images are displayed + && (!node.hasAttribute("aria-hidden") || node.getAttribute("aria-hidden") != "true" || (node.className && node.className.indexOf && node.className.indexOf("fallback-image") !== -1)); + }, + + /** + * Runs readability. + * + * Workflow: + * 1. Prep the document by removing script tags, css, etc. + * 2. Build readability's DOM tree. + * 3. Grab the article content from the current dom tree. + * 4. Replace the current DOM tree with the new one. + * 5. Read peacefully. + * + * @return void + **/ + parse: function () { + // Avoid parsing too large documents, as per configuration option + if (this._maxElemsToParse > 0) { + var numTags = this._doc.getElementsByTagName("*").length; + if (numTags > this._maxElemsToParse) { + throw new Error("Aborting parsing document; " + numTags + " elements found"); + } + } + + // Unwrap image from noscript + this._unwrapNoscriptImages(this._doc); + + // Extract JSON-LD metadata before removing scripts + var jsonLd = this._disableJSONLD ? {} : this._getJSONLD(this._doc); + + // Remove script tags from the document. + this._removeScripts(this._doc); + + this._prepDocument(); + + var metadata = this._getArticleMetadata(jsonLd); + this._articleTitle = metadata.title; + + var articleContent = this._grabArticle(); + if (!articleContent) + return null; + + this.log("Grabbed: " + articleContent.innerHTML); + + this._postProcessContent(articleContent); + + // If we haven't found an excerpt in the article's metadata, use the article's + // first paragraph as the excerpt. This is used for displaying a preview of + // the article's content. + if (!metadata.excerpt) { + var paragraphs = articleContent.getElementsByTagName("p"); + if (paragraphs.length > 0) { + metadata.excerpt = paragraphs[0].textContent.trim(); + } + } + + var textContent = articleContent.textContent; + return { + title: this._articleTitle, + byline: metadata.byline || this._articleByline, + dir: this._articleDir, + lang: this._articleLang, + content: this._serializer(articleContent), + textContent: textContent, + length: textContent.length, + excerpt: metadata.excerpt, + siteName: metadata.siteName || this._articleSiteName, + publishedTime: metadata.publishedTime + }; + } + }; + + { + /* global module */ + module.exports = Readability; + } + } (Readability$1)); + + var ReadabilityExports = Readability$1.exports; + + var ReadabilityReaderable = {exports: {}}; + + /* + * Copyright (c) 2010 Arc90 Inc + * + * 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 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + (function (module) { + /* + * This code is heavily based on Arc90's readability.js (1.7.1) script + * available at: http://code.google.com/p/arc90labs-readability + */ + + var REGEXPS = { + // NOTE: These two regular expressions are duplicated in + // Readability.js. Please keep both copies in sync. + unlikelyCandidates: /-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i, + okMaybeItsACandidate: /and|article|body|column|content|main|shadow/i, + }; + + function isNodeVisible(node) { + // Have to null-check node.style and node.className.indexOf to deal with SVG and MathML nodes. + return (!node.style || node.style.display != "none") + && !node.hasAttribute("hidden") + //check for "fallback-image" so that wikimedia math images are displayed + && (!node.hasAttribute("aria-hidden") || node.getAttribute("aria-hidden") != "true" || (node.className && node.className.indexOf && node.className.indexOf("fallback-image") !== -1)); + } + + /** + * Decides whether or not the document is reader-able without parsing the whole thing. + * @param {Object} options Configuration object. + * @param {number} [options.minContentLength=140] The minimum node content length used to decide if the document is readerable. + * @param {number} [options.minScore=20] The minumum cumulated 'score' used to determine if the document is readerable. + * @param {Function} [options.visibilityChecker=isNodeVisible] The function used to determine if a node is visible. + * @return {boolean} Whether or not we suspect Readability.parse() will suceeed at returning an article object. + */ + function isProbablyReaderable(doc, options = {}) { + // For backward compatibility reasons 'options' can either be a configuration object or the function used + // to determine if a node is visible. + if (typeof options == "function") { + options = { visibilityChecker: options }; + } + + var defaultOptions = { minScore: 20, minContentLength: 140, visibilityChecker: isNodeVisible }; + options = Object.assign(defaultOptions, options); + + var nodes = doc.querySelectorAll("p, pre, article"); + + // Get <div> nodes which have <br> node(s) and append them into the `nodes` variable. + // Some articles' DOM structures might look like + // <div> + // Sentences<br> + // <br> + // Sentences<br> + // </div> + var brNodes = doc.querySelectorAll("div > br"); + if (brNodes.length) { + var set = new Set(nodes); + [].forEach.call(brNodes, function (node) { + set.add(node.parentNode); + }); + nodes = Array.from(set); + } + + var score = 0; + // This is a little cheeky, we use the accumulator 'score' to decide what to return from + // this callback: + return [].some.call(nodes, function (node) { + if (!options.visibilityChecker(node)) { + return false; + } + + var matchString = node.className + " " + node.id; + if (REGEXPS.unlikelyCandidates.test(matchString) && + !REGEXPS.okMaybeItsACandidate.test(matchString)) { + return false; + } + + if (node.matches("li p")) { + return false; + } + + var textContentLength = node.textContent.trim().length; + if (textContentLength < options.minContentLength) { + return false; + } + + score += Math.sqrt(textContentLength - options.minContentLength); + + if (score > options.minScore) { + return true; + } + return false; + }); + } + + { + /* global module */ + module.exports = isProbablyReaderable; + } + } (ReadabilityReaderable)); + + var ReadabilityReaderableExports = ReadabilityReaderable.exports; + + /* eslint-env node */ + + var Readability = ReadabilityExports; + var isProbablyReaderable = ReadabilityReaderableExports; + + var readability = { + Readability: Readability, + isProbablyReaderable: isProbablyReaderable + }; + + // utils/extractWithReadability + + + var extractWithReadability = (html, url = '') => { + if (!isString$1(html)) { + return null + } + const doc = new DOMParser().parseFromString(html, 'text/html'); + const base = doc.createElement('base'); + base.setAttribute('href', url); + doc.head.appendChild(base); + const reader = new readability.Readability(doc, { + keepClasses: true, + }); + const result = reader.parse() ?? {}; + return result.textContent ? result.content : null + }; + + function extractTitleWithReadability (html) { + if (!isString$1(html)) { + return null + } + const doc = new DOMParser().parseFromString(html, 'text/html'); + const reader = new readability.Readability(doc); + return reader._getArticleTitle() || null + } + + // utils --> transformation.js + + + const transformations = []; + + const add = (tn) => { + const { patterns } = tn; + if (!patterns || !isArray$3(patterns) || !patterns.length) { + return 0 + } + transformations.push(tn); + return 1 + }; + + const addTransformations = (tfms) => { + if (isArray$3(tfms)) { + return tfms.map(tfm => add(tfm)).filter(result => result === 1).length + } + return add(tfms) + }; + + const removeTransformations = (patterns) => { + if (!patterns) { + const removed = transformations.length; + transformations.length = 0; + return removed + } + let removing = 0; + for (let i = transformations.length - 1; i > 0; i--) { + const { patterns: ipatterns } = transformations[i]; + const matched = ipatterns.some((ptn) => patterns.some((pattern) => String(pattern) === String(ptn))); + if (matched) { + transformations.splice(i, 1); + removing += 1; + } + } + return removing + }; + + const findTransformations = (links) => { + const urls = !isArray$3(links) ? [links] : links; + const tfms = []; + for (const transformation of transformations) { + const { patterns } = transformation; + const matched = urls.some((url) => patterns.some((pattern) => pattern.test(url))); + if (matched) { + tfms.push(clone(transformation)); + } + } + return tfms + }; + + const execPreParser = (html, links) => { + const doc = new DOMParser().parseFromString(html, 'text/html'); + findTransformations(links).map(tfm => tfm.pre).filter(fn => isFunction(fn)).map(fn => fn(doc)); + return Array.from(doc.childNodes).map(it => it.outerHTML).join('') + }; + + const execPostParser = (html, links) => { + const doc = new DOMParser().parseFromString(html, 'text/html'); + findTransformations(links).map(tfm => tfm.post).filter(fn => isFunction(fn)).map(fn => fn(doc)); + return Array.from(doc.childNodes).map(it => it.outerHTML).join('') + }; + + // utils -> getTimeToRead + + var getTimeToRead = (text, wordsPerMinute) => { + const words = text.trim().split(/\s+/g).length; + const minToRead = words / wordsPerMinute; + const secToRead = Math.ceil(minToRead * 60); + return secToRead + }; + + // utils -> parseFromHtml + + + const summarize = (desc, txt, threshold, maxlen) => { // eslint-disable-line + return desc.length > threshold + ? desc + : truncate(txt, maxlen).replace(/\n/g, ' ') + }; + + var parseFromHtml = async (inputHtml, inputUrl = '', parserOptions = {}) => { + const pureHtml = purify$1(inputHtml); + const meta = extractMetaData(pureHtml); + + let title = meta.title; + + const { + url, + shortlink, + amphtml, + canonical, + description: metaDesc, + image: metaImg, + author, + published, + favicon: metaFav, + type, + } = meta; + + const { + wordsPerMinute = 300, + descriptionTruncateLen = 210, + descriptionLengthThreshold = 180, + contentLengthThreshold = 200, + } = parserOptions; + + // gather title + if (!title) { + title = extractTitleWithReadability(pureHtml); + } + if (!title) { + return null + } + + // gather urls to choose the best url later + const links = unique( + [url, shortlink, amphtml, canonical, inputUrl] + .filter(isValid) + .map(purify) + ); + + if (!links.length) { + return null + } + + // choose the best url, which one looks like title the most + const bestUrl = chooseBestUrl(links, title); + + const fns = pipe( + (input) => { + return normalize(input, bestUrl) + }, + (input) => { + return execPreParser(input, links) + }, + (input) => { + return extractWithReadability(input, bestUrl) + }, + (input) => { + return input ? execPostParser(input, links) : null + }, + (input) => { + return input ? cleanify(input) : null + } + ); + + const content = fns(inputHtml); + + if (!content) { + return null + } + + const textContent = stripTags(content); + if (textContent.length < contentLengthThreshold) { + return null + } + + const description = summarize( + metaDesc, + textContent, + descriptionLengthThreshold, + descriptionTruncateLen + ); + + const image = metaImg ? absolutify(bestUrl, metaImg) : ''; + const favicon = metaFav ? absolutify(bestUrl, metaFav) : ''; + + return { + url: bestUrl, + title, + description, + links, + image, + content, + author, + favicon, + source: getDomain(bestUrl), + published, + ttr: getTimeToRead(textContent, wordsPerMinute), + type, + } + }; + + // main.js + + + const extract = async (input, parserOptions = {}, fetchOptions = {}) => { + if (!isString$1(input)) { + throw new Error('Input must be a string') + } + + if (!isValid(input)) { + return parseFromHtml(input, null, parserOptions || {}) + } + const buffer = await retrieve(input, fetchOptions); + const text = buffer ? Buffer.from(buffer).toString().trim() : ''; + if (!text) { + return null + } + const charset = getCharset(text); + const decoder = new TextDecoder(charset); + const html = decoder.decode(buffer); + return parseFromHtml(html, input, parserOptions || {}) + }; + + const extractFromHtml = async (html, url, parserOptions = {}) => { + return parseFromHtml(html, url, parserOptions) + }; + + exports.addTransformations = addTransformations; + exports.extract = extract; + exports.extractFromHtml = extractFromHtml; + exports.getSanitizeHtmlOptions = getSanitizeHtmlOptions; + exports.removeTransformations = removeTransformations; + exports.setSanitizeHtmlOptions = setSanitizeHtmlOptions; + + return exports; + +})({}, fetch); diff --git a/package.json b/package.json index 1278983..d48f35a 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,8 @@ }, "dependencies": { "@mozilla/readability": "^0.5.0", + "@rollup/plugin-commonjs": "^26.0.1", + "@rollup/plugin-node-resolve": "^15.2.3", "bellajs": "^11.1.3", "cross-fetch": "^4.0.0", "linkedom": "^0.16.11", @@ -42,7 +44,9 @@ "globals": "^15.1.0", "https-proxy-agent": "^7.0.4", "jest": "^29.7.0", - "nock": "^13.5.4" + "nock": "^13.5.4", + "rollup-plugin-polyfill-node": "^0.13.0", + "rollup-plugin-terser": "^7.0.2" }, "keywords": [ "article", diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..0cc580e --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,22 @@ +import resolve from "@rollup/plugin-node-resolve"; +import commonjs from "@rollup/plugin-commonjs"; +import { terser } from "rollup-plugin-terser"; +import nodePolyfills from "rollup-plugin-polyfill-node"; + +export default { + input: "src/main.js", + output: { + file: "bundle.js", + format: "iife", + name: "ArticleExtractor", + globals: { + bellajs: "bellajs", + "cross-fetch": "fetch", + linkedom: "linkedom", + "sanitize-html": "sanitizeHtml", + "@mozilla/readability": "Readability", + }, + }, + plugins: [resolve(), commonjs(), nodePolyfills()], + external: ["cross-fetch"], +};