PNG  IHDRQgAMA a cHRMz&u0`:pQ<bKGDgmIDATxwUﹻ& ^CX(J I@ "% (** BX +*i"]j(IH{~R)[~>h{}gy)I$Ij .I$I$ʊy@}x.: $I$Ii}VZPC)I$IF ^0ʐJ$I$Q^}{"r=OzI$gRZeC.IOvH eKX $IMpxsk.쒷/&r[޳<v| .I~)@$updYRa$I |M.e JaֶpSYR6j>h%IRز if&uJ)M$I vLi=H;7UJ,],X$I1AҒJ$ XY XzI@GNҥRT)E@;]K*Mw;#5_wOn~\ DC&$(A5 RRFkvIR}l!RytRl;~^ǷJj اy뷦BZJr&ӥ8Pjw~vnv X^(I;4R=P[3]J,]ȏ~:3?[ a&e)`e*P[4]T=Cq6R[ ~ޤrXR Հg(t_HZ-Hg M$ãmL5R uk*`%C-E6/%[t X.{8P9Z.vkXŐKjgKZHg(aK9ڦmKjѺm_ \#$5,)-  61eJ,5m| r'= &ڡd%-]J on Xm|{ RҞe $eڧY XYrԮ-a7RK6h>n$5AVڴi*ֆK)mѦtmr1p| q:흺,)Oi*ֺK)ܬ֦K-5r3>0ԔHjJئEZj,%re~/z%jVMڸmrt)3]J,T K֦OvԒgii*bKiNO~%PW0=dii2tJ9Jݕ{7"I P9JKTbu,%r"6RKU}Ij2HKZXJ,妝 XYrP ެ24c%i^IK|.H,%rb:XRl1X4Pe/`x&P8Pj28Mzsx2r\zRPz4J}yP[g=L) .Q[6RjWgp FIH*-`IMRaK9TXcq*I y[jE>cw%gLRԕiFCj-ďa`#e~I j,%r,)?[gp FI˨mnWX#>mʔ XA DZf9,nKҲzIZXJ,L#kiPz4JZF,I,`61%2s $,VOϚ2/UFJfy7K> X+6 STXIeJILzMfKm LRaK9%|4p9LwJI!`NsiazĔ)%- XMq>pk$-$Q2x#N ؎-QR}ᶦHZډ)J,l#i@yn3LN`;nڔ XuX5pF)m|^0(>BHF9(cզEerJI rg7 4I@z0\JIi䵙RR0s;$s6eJ,`n 䂦0a)S)A 1eJ,堌#635RIgpNHuTH_SԕqVe ` &S)>p;S$魁eKIuX`I4춒o}`m$1":PI<[v9^\pTJjriRŭ P{#{R2,`)e-`mgj~1ϣLKam7&U\j/3mJ,`F;M'䱀 .KR#)yhTq;pcK9(q!w?uRR,n.yw*UXj#\]ɱ(qv2=RqfB#iJmmL<]Y͙#$5 uTU7ӦXR+q,`I}qL'`6Kͷ6r,]0S$- [RKR3oiRE|nӦXR.(i:LDLTJjY%o:)6rxzҒqTJjh㞦I.$YR.ʼnGZ\ֿf:%55 I˼!6dKxm4E"mG_ s? .e*?LRfK9%q#uh$)i3ULRfK9yxm܌bj84$i1U^@Wbm4uJ,ҪA>_Ij?1v32[gLRD96oTaR׿N7%L2 NT,`)7&ƝL*꽙yp_$M2#AS,`)7$rkTA29_Iye"|/0t)$n XT2`YJ;6Jx".e<`$) PI$5V4]29SRI>~=@j]lp2`K9Jaai^" Ԋ29ORI%:XV5]JmN9]H;1UC39NI%Xe78t)a;Oi Ҙ>Xt"~G>_mn:%|~ޅ_+]$o)@ǀ{hgN;IK6G&rp)T2i୦KJuv*T=TOSV>(~D>dm,I*Ɛ:R#ۙNI%D>G.n$o;+#RR!.eU˽TRI28t)1LWϚ>IJa3oFbu&:tJ*(F7y0ZR ^p'Ii L24x| XRI%ۄ>S1]Jy[zL$adB7.eh4%%누>WETf+3IR:I3Xה)3אOۦSRO'ٺ)S}"qOr[B7ϙ.edG)^ETR"RtRݜh0}LFVӦDB^k_JDj\=LS(Iv─aTeZ%eUAM-0;~˃@i|l @S4y72>sX-vA}ϛBI!ݎߨWl*)3{'Y|iSlEڻ(5KtSI$Uv02,~ԩ~x;P4ցCrO%tyn425:KMlD ^4JRxSهF_}شJTS6uj+ﷸk$eZO%G*^V2u3EMj3k%)okI]dT)URKDS 7~m@TJR~荪fT"֛L \sM -0T KfJz+nإKr L&j()[E&I ߴ>e FW_kJR|!O:5/2跌3T-'|zX ryp0JS ~^F>-2< `*%ZFP)bSn"L :)+pʷf(pO3TMW$~>@~ū:TAIsV1}S2<%ޟM?@iT ,Eūoz%i~g|`wS(]oȤ8)$ ntu`өe`6yPl IzMI{ʣzʨ )IZ2= ld:5+請M$-ї;U>_gsY$ÁN5WzWfIZ)-yuXIfp~S*IZdt;t>KūKR|$#LcԀ+2\;kJ`]YǔM1B)UbG"IRߊ<xܾӔJ0Z='Y嵤 Leveg)$znV-º^3Ւof#0Tfk^Zs[*I꯳3{)ˬW4Ւ4 OdpbZRS|*I 55#"&-IvT&/윚Ye:i$ 9{LkuRe[I~_\ؠ%>GL$iY8 9ܕ"S`kS.IlC;Ҏ4x&>u_0JLr<J2(^$5L s=MgV ~,Iju> 7r2)^=G$1:3G< `J3~&IR% 6Tx/rIj3O< ʔ&#f_yXJiގNSz; Tx(i8%#4 ~AS+IjerIUrIj362v885+IjAhK__5X%nV%Iͳ-y|7XV2v4fzo_68"S/I-qbf; LkF)KSM$ Ms>K WNV}^`-큧32ŒVؙGdu,^^m%6~Nn&͓3ŒVZMsRpfEW%IwdǀLm[7W&bIRL@Q|)* i ImsIMmKmyV`i$G+R 0tV'!V)֏28vU7͒vHꦼtxꗞT ;S}7Mf+fIRHNZUkUx5SAJㄌ9MqμAIRi|j5)o*^'<$TwI1hEU^c_j?Е$%d`z cyf,XO IJnTgA UXRD }{H}^S,P5V2\Xx`pZ|Yk:$e ~ @nWL.j+ϝYb퇪bZ BVu)u/IJ_ 1[p.p60bC >|X91P:N\!5qUB}5a5ja `ubcVxYt1N0Zzl4]7­gKj]?4ϻ *[bg$)+À*x쳀ogO$~,5 زUS9 lq3+5mgw@np1sso Ӻ=|N6 /g(Wv7U;zωM=wk,0uTg_`_P`uz?2yI!b`kĸSo+Qx%!\οe|އԁKS-s6pu_(ֿ$i++T8=eY; צP+phxWQv*|p1. ά. XRkIQYP,drZ | B%wP|S5`~́@i޾ E;Չaw{o'Q?%iL{u D?N1BD!owPHReFZ* k_-~{E9b-~P`fE{AܶBJAFO wx6Rox5 K5=WwehS8 (JClJ~ p+Fi;ŗo+:bD#g(C"wA^ r.F8L;dzdIHUX݆ϞXg )IFqem%I4dj&ppT{'{HOx( Rk6^C٫O.)3:s(۳(Z?~ٻ89zmT"PLtw䥈5&b<8GZ-Y&K?e8,`I6e(֍xb83 `rzXj)F=l($Ij 2*(F?h(/9ik:I`m#p3MgLaKjc/U#n5S# m(^)=y=đx8ŬI[U]~SцA4p$-F i(R,7Cx;X=cI>{Km\ o(Tv2vx2qiiDJN,Ҏ!1f 5quBj1!8 rDFd(!WQl,gSkL1Bxg''՞^ǘ;pQ P(c_ IRujg(Wz bs#P­rz> k c&nB=q+ؔXn#r5)co*Ũ+G?7< |PQӣ'G`uOd>%Mctz# Ԫڞ&7CaQ~N'-P.W`Oedp03C!IZcIAMPUۀ5J<\u~+{9(FbbyAeBhOSܳ1 bÈT#ŠyDžs,`5}DC-`̞%r&ڙa87QWWp6e7 Rϫ/oY ꇅ Nܶըtc!LA T7V4Jsū I-0Pxz7QNF_iZgúWkG83 0eWr9 X]㾮݁#Jˢ C}0=3ݱtBi]_ &{{[/o[~ \q鯜00٩|cD3=4B_b RYb$óBRsf&lLX#M*C_L܄:gx)WΘsGSbuL rF$9';\4Ɍq'n[%p.Q`u hNb`eCQyQ|l_C>Lb꟟3hSb #xNxSs^ 88|Mz)}:](vbۢamŖ࿥ 0)Q7@0=?^k(*J}3ibkFn HjB׻NO z x}7p 0tfDX.lwgȔhԾŲ }6g E |LkLZteu+=q\Iv0쮑)QٵpH8/2?Σo>Jvppho~f>%bMM}\//":PTc(v9v!gոQ )UfVG+! 35{=x\2+ki,y$~A1iC6#)vC5^>+gǵ@1Hy٪7u;p psϰu/S <aʸGu'tD1ԝI<pg|6j'p:tպhX{o(7v],*}6a_ wXRk,O]Lܳ~Vo45rp"N5k;m{rZbΦ${#)`(Ŵg,;j%6j.pyYT?}-kBDc3qA`NWQū20/^AZW%NQ MI.X#P#,^Ebc&?XR tAV|Y.1!؅⨉ccww>ivl(JT~ u`ٵDm q)+Ri x/x8cyFO!/*!/&,7<.N,YDŽ&ܑQF1Bz)FPʛ?5d 6`kQձ λc؎%582Y&nD_$Je4>a?! ͨ|ȎWZSsv8 j(I&yj Jb5m?HWp=g}G3#|I,5v珿] H~R3@B[☉9Ox~oMy=J;xUVoj bUsl_35t-(ՃɼRB7U!qc+x4H_Qo֮$[GO<4`&č\GOc[.[*Af%mG/ ňM/r W/Nw~B1U3J?P&Y )`ѓZ1p]^l“W#)lWZilUQu`-m|xĐ,_ƪ|9i:_{*(3Gѧ}UoD+>m_?VPۅ15&}2|/pIOʵ> GZ9cmíتmnz)yߐbD >e}:) r|@R5qVSA10C%E_'^8cR7O;6[eKePGϦX7jb}OTGO^jn*媓7nGMC t,k31Rb (vyܴʭ!iTh8~ZYZp(qsRL ?b}cŨʊGO^!rPJO15MJ[c&~Z`"ѓޔH1C&^|Ш|rʼ,AwĴ?b5)tLU)F| &g٣O]oqSUjy(x<Ϳ3 .FSkoYg2 \_#wj{u'rQ>o;%n|F*O_L"e9umDds?.fuuQbIWz |4\0 sb;OvxOSs; G%T4gFRurj(֍ڑb uԖKDu1MK{1^ q; C=6\8FR艇!%\YÔU| 88m)֓NcLve C6z;o&X x59:q61Z(T7>C?gcļxѐ Z oo-08jہ x,`' ҔOcRlf~`jj".Nv+sM_]Zk g( UOPyεx%pUh2(@il0ݽQXxppx-NS( WO+轾 nFߢ3M<;z)FBZjciu/QoF 7R¥ ZFLF~#ȣߨ^<쩡ݛкvџ))ME>ώx4m#!-m!L;vv#~Y[đKmx9.[,UFS CVkZ +ߟrY٧IZd/ioi$%͝ب_ֶX3ܫhNU ZZgk=]=bbJS[wjU()*I =ώ:}-蹞lUj:1}MWm=̛ _ ¾,8{__m{_PVK^n3esw5ӫh#$-q=A̟> ,^I}P^J$qY~Q[ Xq9{#&T.^GVj__RKpn,b=`żY@^՝;z{paVKkQXj/)y TIc&F;FBG7wg ZZDG!x r_tƢ!}i/V=M/#nB8 XxЫ ^@CR<{䤭YCN)eKOSƟa $&g[i3.C6xrOc8TI;o hH6P&L{@q6[ Gzp^71j(l`J}]e6X☉#͕ ׈$AB1Vjh㭦IRsqFBjwQ_7Xk>y"N=MB0 ,C #o6MRc0|$)ف"1!ixY<B9mx `,tA>)5ػQ?jQ?cn>YZe Tisvh# GMމȇp:ԴVuږ8ɼH]C.5C!UV;F`mbBk LTMvPʍϤj?ԯ/Qr1NB`9s"s TYsz &9S%U԰> {<ؿSMxB|H\3@!U| k']$U+> |HHMLޢ?V9iD!-@x TIî%6Z*9X@HMW#?nN ,oe6?tQwڱ.]-y':mW0#!J82qFjH -`ѓ&M0u Uγmxϵ^-_\])@0Rt.8/?ٰCY]x}=sD3ojަЫNuS%U}ԤwHH>ڗjܷ_3gN q7[q2la*ArǓԖ+p8/RGM ]jacd(JhWko6ڎbj]i5Bj3+3!\j1UZLsLTv8HHmup<>gKMJj0@H%,W΃7R) ">c, xixј^ aܖ>H[i.UIHc U1=yW\=S*GR~)AF=`&2h`DzT󑓶J+?W+}C%P:|0H܆}-<;OC[~o.$~i}~HQ TvXΈr=b}$vizL4:ȰT|4~*!oXQR6Lk+#t/g lԁߖ[Jڶ_N$k*". xsxX7jRVbAAʯKҎU3)zSNN _'s?f)6X!%ssAkʱ>qƷb hg %n ~p1REGMHH=BJiy[<5 ǁJҖgKR*倳e~HUy)Ag,K)`Vw6bRR:qL#\rclK/$sh*$ 6덤 KԖc 3Z9=Ɣ=o>X Ώ"1 )a`SJJ6k(<c e{%kϊP+SL'TcMJWRm ŏ"w)qc ef꒵i?b7b('"2r%~HUS1\<(`1Wx9=8HY9m:X18bgD1u ~|H;K-Uep,, C1 RV.MR5άh,tWO8WC$ XRVsQS]3GJ|12 [vM :k#~tH30Rf-HYݺ-`I9%lIDTm\ S{]9gOڒMNCV\G*2JRŨ;Rҏ^ڽ̱mq1Eu?To3I)y^#jJw^Ńj^vvlB_⋌P4x>0$c>K†Aļ9s_VjTt0l#m>E-,,x,-W)سo&96RE XR.6bXw+)GAEvL)͞K4$p=Ũi_ѱOjb HY/+@θH9޼]Nԥ%n{ &zjT? Ty) s^ULlb,PiTf^<À] 62R^V7)S!nllS6~͝V}-=%* ʻ>G DnK<y&>LPy7'r=Hj 9V`[c"*^8HpcO8bnU`4JȪAƋ#1_\ XϘHPRgik(~G~0DAA_2p|J묭a2\NCr]M_0 ^T%e#vD^%xy-n}-E\3aS%yN!r_{ )sAw ڼp1pEAk~v<:`'ӭ^5 ArXOI驻T (dk)_\ PuA*BY]yB"l\ey hH*tbK)3 IKZ򹞋XjN n *n>k]X_d!ryBH ]*R 0(#'7 %es9??ښFC,ՁQPjARJ\Ρw K#jahgw;2$l*) %Xq5!U᢯6Re] |0[__64ch&_}iL8KEgҎ7 M/\`|.p,~`a=BR?xܐrQ8K XR2M8f ?`sgWS%" Ԉ 7R%$ N}?QL1|-эټwIZ%pvL3Hk>,ImgW7{E xPHx73RA @RS CC !\ȟ5IXR^ZxHл$Q[ŝ40 (>+ _C >BRt<,TrT {O/H+˟Pl6 I B)/VC<6a2~(XwV4gnXR ϱ5ǀHٻ?tw똤Eyxp{#WK qG%5],(0ӈH HZ])ג=K1j&G(FbM@)%I` XRg ʔ KZG(vP,<`[ Kn^ SJRsAʠ5xՅF`0&RbV tx:EaUE/{fi2;.IAwW8/tTxAGOoN?G}l L(n`Zv?pB8K_gI+ܗ #i?ޙ.) p$utc ~DžfՈEo3l/)I-U?aԅ^jxArA ΧX}DmZ@QLےbTXGd.^|xKHR{|ΕW_h] IJ`[G9{).y) 0X YA1]qp?p_k+J*Y@HI>^?gt.06Rn ,` ?);p pSF9ZXLBJPWjgQ|&)7! HjQt<| ؅W5 x W HIzYoVMGP Hjn`+\(dNW)F+IrS[|/a`K|ͻ0Hj{R,Q=\ (F}\WR)AgSG`IsnAR=|8$}G(vC$)s FBJ?]_u XRvύ6z ŨG[36-T9HzpW̞ú Xg큽=7CufzI$)ki^qk-) 0H*N` QZkk]/tnnsI^Gu't=7$ Z;{8^jB% IItRQS7[ϭ3 $_OQJ`7!]W"W,)Iy W AJA;KWG`IY{8k$I$^%9.^(`N|LJ%@$I}ֽp=FB*xN=gI?Q{٥4B)mw $Igc~dZ@G9K X?7)aK%݅K$IZ-`IpC U6$I\0>!9k} Xa IIS0H$I H ?1R.Чj:4~Rw@p$IrA*u}WjWFPJ$I➓/6#! LӾ+ X36x8J |+L;v$Io4301R20M I$-E}@,pS^ޟR[/s¹'0H$IKyfŸfVOπFT*a$I>He~VY/3R/)>d$I>28`Cjw,n@FU*9ttf$I~<;=/4RD~@ X-ѕzἱI$: ԍR a@b X{+Qxuq$IЛzo /~3\8ڒ4BN7$IҀj V]n18H$IYFBj3̵̚ja pp $Is/3R Ӻ-Yj+L;.0ŔI$Av? #!5"aʄj}UKmɽH$IjCYs?h$IDl843.v}m7UiI=&=0Lg0$I4: embe` eQbm0u? $IT!Sƍ'-sv)s#C0:XB2a w I$zbww{."pPzO =Ɔ\[ o($Iaw]`E).Kvi:L*#gР7[$IyGPI=@R 4yR~̮´cg I$I/<tPͽ hDgo 94Z^k盇΄8I56^W$I^0̜N?4*H`237}g+hxoq)SJ@p|` $I%>-hO0eO>\ԣNߌZD6R=K ~n($I$y3D>o4b#px2$yڪtzW~a $I~?x'BwwpH$IZݑnC㧄Pc_9sO gwJ=l1:mKB>Ab<4Lp$Ib o1ZQ@85b̍ S'F,Fe,^I$IjEdù{l4 8Ys_s Z8.x m"+{~?q,Z D!I$ϻ'|XhB)=…']M>5 rgotԎ 獽PH$IjIPhh)n#cÔqA'ug5qwU&rF|1E%I$%]!'3AFD/;Ck_`9 v!ٴtPV;x`'*bQa w I$Ix5 FC3D_~A_#O݆DvV?<qw+I$I{=Z8".#RIYyjǪ=fDl9%M,a8$I$Ywi[7ݍFe$s1ՋBVA?`]#!oz4zjLJo8$I$%@3jAa4(o ;p,,dya=F9ً[LSPH$IJYЉ+3> 5"39aZ<ñh!{TpBGkj}Sp $IlvF.F$I z< '\K*qq.f<2Y!S"-\I$IYwčjF$ w9 \ߪB.1v!Ʊ?+r:^!I$BϹB H"B;L'G[ 4U#5>੐)|#o0aڱ$I>}k&1`U#V?YsV x>{t1[I~D&(I$I/{H0fw"q"y%4 IXyE~M3 8XψL}qE$I[> nD?~sf ]o΁ cT6"?'_Ἣ $I>~.f|'!N?⟩0G KkXZE]ޡ;/&?k OۘH$IRۀwXӨ<7@PnS04aӶp.:@\IWQJ6sS%I$e5ڑv`3:x';wq_vpgHyXZ 3gЂ7{{EuԹn±}$I$8t;b|591nءQ"P6O5i }iR̈́%Q̄p!I䮢]O{H$IRϻ9s֧ a=`- aB\X0"+5"C1Hb?߮3x3&gşggl_hZ^,`5?ߎvĸ%̀M!OZC2#0x LJ0 Gw$I$I}<{Eb+y;iI,`ܚF:5ܛA8-O-|8K7s|#Z8a&><a&/VtbtLʌI$I$I$I$I$I$IRjDD%tEXtdate:create2022-05-31T04:40:26+00:00!Î%tEXtdate:modify2022-05-31T04:40:26+00:00|{2IENDB`Mini Shell

HOME


Mini Shell 1.0
DIR:/home/mykeywordtracker.com/www/keyword-tracker/node_modules/saxes/
Upload File :
Current File : //home/mykeywordtracker.com/www/keyword-tracker/node_modules/saxes/saxes.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const ed5 = require("xmlchars/xml/1.0/ed5");
const ed2 = require("xmlchars/xml/1.1/ed2");
const NSed3 = require("xmlchars/xmlns/1.0/ed3");
var isS = ed5.isS;
var isChar10 = ed5.isChar;
var isNameStartChar = ed5.isNameStartChar;
var isNameChar = ed5.isNameChar;
var S_LIST = ed5.S_LIST;
var NAME_RE = ed5.NAME_RE;
var isChar11 = ed2.isChar;
var isNCNameStartChar = NSed3.isNCNameStartChar;
var isNCNameChar = NSed3.isNCNameChar;
var NC_NAME_RE = NSed3.NC_NAME_RE;
const XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace";
const XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/";
const rootNS = {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    __proto__: null,
    xml: XML_NAMESPACE,
    xmlns: XMLNS_NAMESPACE,
};
const XML_ENTITIES = {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    __proto__: null,
    amp: "&",
    gt: ">",
    lt: "<",
    quot: "\"",
    apos: "'",
};
// EOC: end-of-chunk
const EOC = -1;
const NL_LIKE = -2;
const S_BEGIN = 0; // Initial state.
const S_BEGIN_WHITESPACE = 1; // leading whitespace
const S_DOCTYPE = 2; // <!DOCTYPE
const S_DOCTYPE_QUOTE = 3; // <!DOCTYPE "//blah
const S_DTD = 4; // <!DOCTYPE "//blah" [ ...
const S_DTD_QUOTED = 5; // <!DOCTYPE "//blah" [ "foo
const S_DTD_OPEN_WAKA = 6;
const S_DTD_OPEN_WAKA_BANG = 7;
const S_DTD_COMMENT = 8; // <!--
const S_DTD_COMMENT_ENDING = 9; // <!-- blah -
const S_DTD_COMMENT_ENDED = 10; // <!-- blah --
const S_DTD_PI = 11; // <?
const S_DTD_PI_ENDING = 12; // <?hi "there" ?
const S_TEXT = 13; // general stuff
const S_ENTITY = 14; // &amp and such
const S_OPEN_WAKA = 15; // <
const S_OPEN_WAKA_BANG = 16; // <!...
const S_COMMENT = 17; // <!--
const S_COMMENT_ENDING = 18; // <!-- blah -
const S_COMMENT_ENDED = 19; // <!-- blah --
const S_CDATA = 20; // <![CDATA[ something
const S_CDATA_ENDING = 21; // ]
const S_CDATA_ENDING_2 = 22; // ]]
const S_PI_FIRST_CHAR = 23; // <?hi, first char
const S_PI_REST = 24; // <?hi, rest of the name
const S_PI_BODY = 25; // <?hi there
const S_PI_ENDING = 26; // <?hi "there" ?
const S_XML_DECL_NAME_START = 27; // <?xml
const S_XML_DECL_NAME = 28; // <?xml foo
const S_XML_DECL_EQ = 29; // <?xml foo=
const S_XML_DECL_VALUE_START = 30; // <?xml foo=
const S_XML_DECL_VALUE = 31; // <?xml foo="bar"
const S_XML_DECL_SEPARATOR = 32; // <?xml foo="bar"
const S_XML_DECL_ENDING = 33; // <?xml ... ?
const S_OPEN_TAG = 34; // <strong
const S_OPEN_TAG_SLASH = 35; // <strong /
const S_ATTRIB = 36; // <a
const S_ATTRIB_NAME = 37; // <a foo
const S_ATTRIB_NAME_SAW_WHITE = 38; // <a foo _
const S_ATTRIB_VALUE = 39; // <a foo=
const S_ATTRIB_VALUE_QUOTED = 40; // <a foo="bar
const S_ATTRIB_VALUE_CLOSED = 41; // <a foo="bar"
const S_ATTRIB_VALUE_UNQUOTED = 42; // <a foo=bar
const S_CLOSE_TAG = 43; // </a
const S_CLOSE_TAG_SAW_WHITE = 44; // </a   >
const TAB = 9;
const NL = 0xA;
const CR = 0xD;
const SPACE = 0x20;
const BANG = 0x21;
const DQUOTE = 0x22;
const AMP = 0x26;
const SQUOTE = 0x27;
const MINUS = 0x2D;
const FORWARD_SLASH = 0x2F;
const SEMICOLON = 0x3B;
const LESS = 0x3C;
const EQUAL = 0x3D;
const GREATER = 0x3E;
const QUESTION = 0x3F;
const OPEN_BRACKET = 0x5B;
const CLOSE_BRACKET = 0x5D;
const NEL = 0x85;
const LS = 0x2028; // Line Separator
const isQuote = (c) => c === DQUOTE || c === SQUOTE;
const QUOTES = [DQUOTE, SQUOTE];
const DOCTYPE_TERMINATOR = [...QUOTES, OPEN_BRACKET, GREATER];
const DTD_TERMINATOR = [...QUOTES, LESS, CLOSE_BRACKET];
const XML_DECL_NAME_TERMINATOR = [EQUAL, QUESTION, ...S_LIST];
const ATTRIB_VALUE_UNQUOTED_TERMINATOR = [...S_LIST, GREATER, AMP, LESS];
function nsPairCheck(parser, prefix, uri) {
    switch (prefix) {
        case "xml":
            if (uri !== XML_NAMESPACE) {
                parser.fail(`xml prefix must be bound to ${XML_NAMESPACE}.`);
            }
            break;
        case "xmlns":
            if (uri !== XMLNS_NAMESPACE) {
                parser.fail(`xmlns prefix must be bound to ${XMLNS_NAMESPACE}.`);
            }
            break;
        default:
    }
    switch (uri) {
        case XMLNS_NAMESPACE:
            parser.fail(prefix === "" ?
                `the default namespace may not be set to ${uri}.` :
                `may not assign a prefix (even "xmlns") to the URI \
${XMLNS_NAMESPACE}.`);
            break;
        case XML_NAMESPACE:
            switch (prefix) {
                case "xml":
                    // Assinging the XML namespace to "xml" is fine.
                    break;
                case "":
                    parser.fail(`the default namespace may not be set to ${uri}.`);
                    break;
                default:
                    parser.fail("may not assign the xml namespace to another prefix.");
            }
            break;
        default:
    }
}
function nsMappingCheck(parser, mapping) {
    for (const local of Object.keys(mapping)) {
        nsPairCheck(parser, local, mapping[local]);
    }
}
const isNCName = (name) => NC_NAME_RE.test(name);
const isName = (name) => NAME_RE.test(name);
const FORBIDDEN_START = 0;
const FORBIDDEN_BRACKET = 1;
const FORBIDDEN_BRACKET_BRACKET = 2;
/**
 * The list of supported events.
 */
exports.EVENTS = [
    "xmldecl",
    "text",
    "processinginstruction",
    "doctype",
    "comment",
    "opentagstart",
    "attribute",
    "opentag",
    "closetag",
    "cdata",
    "error",
    "end",
    "ready",
];
const EVENT_NAME_TO_HANDLER_NAME = {
    xmldecl: "xmldeclHandler",
    text: "textHandler",
    processinginstruction: "piHandler",
    doctype: "doctypeHandler",
    comment: "commentHandler",
    opentagstart: "openTagStartHandler",
    attribute: "attributeHandler",
    opentag: "openTagHandler",
    closetag: "closeTagHandler",
    cdata: "cdataHandler",
    error: "errorHandler",
    end: "endHandler",
    ready: "readyHandler",
};
class SaxesParser {
    /**
     * @param opt The parser options.
     */
    constructor(opt) {
        this.opt = opt !== null && opt !== void 0 ? opt : {};
        this.fragmentOpt = !!this.opt.fragment;
        const xmlnsOpt = this.xmlnsOpt = !!this.opt.xmlns;
        this.trackPosition = this.opt.position !== false;
        this.fileName = this.opt.fileName;
        if (xmlnsOpt) {
            // This is the function we use to perform name checks on PIs and entities.
            // When namespaces are used, colons are not allowed in PI target names or
            // entity names. So the check depends on whether namespaces are used. See:
            //
            // https://www.w3.org/XML/xml-names-19990114-errata.html
            // NE08
            //
            this.nameStartCheck = isNCNameStartChar;
            this.nameCheck = isNCNameChar;
            this.isName = isNCName;
            // eslint-disable-next-line @typescript-eslint/unbound-method
            this.processAttribs = this.processAttribsNS;
            // eslint-disable-next-line @typescript-eslint/unbound-method
            this.pushAttrib = this.pushAttribNS;
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            this.ns = Object.assign({ __proto__: null }, rootNS);
            const additional = this.opt.additionalNamespaces;
            if (additional != null) {
                nsMappingCheck(this, additional);
                Object.assign(this.ns, additional);
            }
        }
        else {
            this.nameStartCheck = isNameStartChar;
            this.nameCheck = isNameChar;
            this.isName = isName;
            // eslint-disable-next-line @typescript-eslint/unbound-method
            this.processAttribs = this.processAttribsPlain;
            // eslint-disable-next-line @typescript-eslint/unbound-method
            this.pushAttrib = this.pushAttribPlain;
        }
        //
        // The order of the members in this table needs to correspond to the state
        // numbers given to the states that correspond to the methods being recorded
        // here.
        //
        this.stateTable = [
            /* eslint-disable @typescript-eslint/unbound-method */
            this.sBegin,
            this.sBeginWhitespace,
            this.sDoctype,
            this.sDoctypeQuote,
            this.sDTD,
            this.sDTDQuoted,
            this.sDTDOpenWaka,
            this.sDTDOpenWakaBang,
            this.sDTDComment,
            this.sDTDCommentEnding,
            this.sDTDCommentEnded,
            this.sDTDPI,
            this.sDTDPIEnding,
            this.sText,
            this.sEntity,
            this.sOpenWaka,
            this.sOpenWakaBang,
            this.sComment,
            this.sCommentEnding,
            this.sCommentEnded,
            this.sCData,
            this.sCDataEnding,
            this.sCDataEnding2,
            this.sPIFirstChar,
            this.sPIRest,
            this.sPIBody,
            this.sPIEnding,
            this.sXMLDeclNameStart,
            this.sXMLDeclName,
            this.sXMLDeclEq,
            this.sXMLDeclValueStart,
            this.sXMLDeclValue,
            this.sXMLDeclSeparator,
            this.sXMLDeclEnding,
            this.sOpenTag,
            this.sOpenTagSlash,
            this.sAttrib,
            this.sAttribName,
            this.sAttribNameSawWhite,
            this.sAttribValue,
            this.sAttribValueQuoted,
            this.sAttribValueClosed,
            this.sAttribValueUnquoted,
            this.sCloseTag,
            this.sCloseTagSawWhite,
        ];
        this._init();
    }
    /**
     * Indicates whether or not the parser is closed. If ``true``, wait for
     * the ``ready`` event to write again.
     */
    get closed() {
        return this._closed;
    }
    _init() {
        var _a;
        this.openWakaBang = "";
        this.text = "";
        this.name = "";
        this.piTarget = "";
        this.entity = "";
        this.q = null;
        this.tags = [];
        this.tag = null;
        this.topNS = null;
        this.chunk = "";
        this.chunkPosition = 0;
        this.i = 0;
        this.prevI = 0;
        this.carriedFromPrevious = undefined;
        this.forbiddenState = FORBIDDEN_START;
        this.attribList = [];
        // The logic is organized so as to minimize the need to check
        // this.opt.fragment while parsing.
        const { fragmentOpt } = this;
        this.state = fragmentOpt ? S_TEXT : S_BEGIN;
        // We want these to be all true if we are dealing with a fragment.
        this.reportedTextBeforeRoot = this.reportedTextAfterRoot = this.closedRoot =
            this.sawRoot = fragmentOpt;
        // An XML declaration is intially possible only when parsing whole
        // documents.
        this.xmlDeclPossible = !fragmentOpt;
        this.xmlDeclExpects = ["version"];
        this.entityReturnState = undefined;
        let { defaultXMLVersion } = this.opt;
        if (defaultXMLVersion === undefined) {
            if (this.opt.forceXMLVersion === true) {
                throw new Error("forceXMLVersion set but defaultXMLVersion is not set");
            }
            defaultXMLVersion = "1.0";
        }
        this.setXMLVersion(defaultXMLVersion);
        this.positionAtNewLine = 0;
        this.doctype = false;
        this._closed = false;
        this.xmlDecl = {
            version: undefined,
            encoding: undefined,
            standalone: undefined,
        };
        this.line = 1;
        this.column = 0;
        this.ENTITIES = Object.create(XML_ENTITIES);
        // eslint-disable-next-line no-unused-expressions
        (_a = this.readyHandler) === null || _a === void 0 ? void 0 : _a.call(this);
    }
    /**
     * The stream position the parser is currently looking at. This field is
     * zero-based.
     *
     * This field is not based on counting Unicode characters but is to be
     * interpreted as a plain index into a JavaScript string.
     */
    get position() {
        return this.chunkPosition + this.i;
    }
    /**
     * The column number of the next character to be read by the parser.  *
     * This field is zero-based. (The first column in a line is 0.)
     *
     * This field reports the index at which the next character would be in the
     * line if the line were represented as a JavaScript string.  Note that this
     * *can* be different to a count based on the number of *Unicode characters*
     * due to how JavaScript handles astral plane characters.
     *
     * See [[column]] for a number that corresponds to a count of Unicode
     * characters.
     */
    get columnIndex() {
        return this.position - this.positionAtNewLine;
    }
    /**
     * Set an event listener on an event. The parser supports one handler per
     * event type. If you try to set an event handler over an existing handler,
     * the old handler is silently overwritten.
     *
     * @param name The event to listen to.
     *
     * @param handler The handler to set.
     */
    on(name, handler) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        this[EVENT_NAME_TO_HANDLER_NAME[name]] = handler;
    }
    /**
     * Unset an event handler.
     *
     * @parma name The event to stop listening to.
     */
    off(name) {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        this[EVENT_NAME_TO_HANDLER_NAME[name]] = undefined;
    }
    /**
     * Make an error object. The error object will have a message that contains
     * the ``fileName`` option passed at the creation of the parser. If position
     * tracking was turned on, it will also have line and column number
     * information.
     *
     * @param message The message describing the error to report.
     *
     * @returns An error object with a properly formatted message.
     */
    makeError(message) {
        var _a;
        let msg = (_a = this.fileName) !== null && _a !== void 0 ? _a : "";
        if (this.trackPosition) {
            if (msg.length > 0) {
                msg += ":";
            }
            msg += `${this.line}:${this.column}`;
        }
        if (msg.length > 0) {
            msg += ": ";
        }
        return new Error(msg + message);
    }
    /**
     * Report a parsing error. This method is made public so that client code may
     * check for issues that are outside the scope of this project and can report
     * errors.
     *
     * @param message The error to report.
     *
     * @returns this
     */
    fail(message) {
        const err = this.makeError(message);
        const handler = this.errorHandler;
        if (handler === undefined) {
            throw err;
        }
        else {
            handler(err);
        }
        return this;
    }
    /**
     * Write a XML data to the parser.
     *
     * @param chunk The XML data to write.
     *
     * @returns this
     */
    write(chunk) {
        if (this.closed) {
            return this.fail("cannot write after close; assign an onready handler.");
        }
        let end = false;
        if (chunk === null) {
            // We cannot return immediately because carriedFromPrevious may need
            // processing.
            end = true;
            chunk = "";
        }
        else if (typeof chunk === "object") {
            chunk = chunk.toString();
        }
        // We checked if performing a pre-decomposition of the string into an array
        // of single complete characters (``Array.from(chunk)``) would be faster
        // than the current repeated calls to ``charCodeAt``. As of August 2018, it
        // isn't. (There may be Node-specific code that would perform faster than
        // ``Array.from`` but don't want to be dependent on Node.)
        if (this.carriedFromPrevious !== undefined) {
            // The previous chunk had char we must carry over.
            chunk = `${this.carriedFromPrevious}${chunk}`;
            this.carriedFromPrevious = undefined;
        }
        let limit = chunk.length;
        const lastCode = chunk.charCodeAt(limit - 1);
        if (!end &&
            // A trailing CR or surrogate must be carried over to the next
            // chunk.
            (lastCode === CR || (lastCode >= 0xD800 && lastCode <= 0xDBFF))) {
            // The chunk ends with a character that must be carried over. We cannot
            // know how to handle it until we get the next chunk or the end of the
            // stream. So save it for later.
            this.carriedFromPrevious = chunk[limit - 1];
            limit--;
            chunk = chunk.slice(0, limit);
        }
        const { stateTable } = this;
        this.chunk = chunk;
        this.i = 0;
        while (this.i < limit) {
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            stateTable[this.state].call(this);
        }
        this.chunkPosition += limit;
        return end ? this.end() : this;
    }
    /**
     * Close the current stream. Perform final well-formedness checks and reset
     * the parser tstate.
     *
     * @returns this
     */
    close() {
        return this.write(null);
    }
    /**
     * Get a single code point out of the current chunk. This updates the current
     * position if we do position tracking.
     *
     * This is the algorithm to use for XML 1.0.
     *
     * @returns The character read.
     */
    getCode10() {
        const { chunk, i } = this;
        this.prevI = i;
        // Yes, we do this instead of doing this.i++. Doing it this way, we do not
        // read this.i again, which is a bit faster.
        this.i = i + 1;
        if (i >= chunk.length) {
            return EOC;
        }
        // Using charCodeAt and handling the surrogates ourselves is faster
        // than using codePointAt.
        const code = chunk.charCodeAt(i);
        this.column++;
        if (code < 0xD800) {
            if (code >= SPACE || code === TAB) {
                return code;
            }
            switch (code) {
                case NL:
                    this.line++;
                    this.column = 0;
                    this.positionAtNewLine = this.position;
                    return NL;
                case CR:
                    // We may get NaN if we read past the end of the chunk, which is fine.
                    if (chunk.charCodeAt(i + 1) === NL) {
                        // A \r\n sequence is converted to \n so we have to skip over the
                        // next character. We already know it has a size of 1 so ++ is fine
                        // here.
                        this.i = i + 2;
                    }
                    // Otherwise, a \r is just converted to \n, so we don't have to skip
                    // ahead.
                    // In either case, \r becomes \n.
                    this.line++;
                    this.column = 0;
                    this.positionAtNewLine = this.position;
                    return NL_LIKE;
                default:
                    // If we get here, then code < SPACE and it is not NL CR or TAB.
                    this.fail("disallowed character.");
                    return code;
            }
        }
        if (code > 0xDBFF) {
            // This is a specialized version of isChar10 that takes into account
            // that in this context code > 0xDBFF and code <= 0xFFFF. So it does not
            // test cases that don't need testing.
            if (!(code >= 0xE000 && code <= 0xFFFD)) {
                this.fail("disallowed character.");
            }
            return code;
        }
        const final = 0x10000 + ((code - 0xD800) * 0x400) +
            (chunk.charCodeAt(i + 1) - 0xDC00);
        this.i = i + 2;
        // This is a specialized version of isChar10 that takes into account that in
        // this context necessarily final >= 0x10000.
        if (final > 0x10FFFF) {
            this.fail("disallowed character.");
        }
        return final;
    }
    /**
     * Get a single code point out of the current chunk. This updates the current
     * position if we do position tracking.
     *
     * This is the algorithm to use for XML 1.1.
     *
     * @returns {number} The character read.
     */
    getCode11() {
        const { chunk, i } = this;
        this.prevI = i;
        // Yes, we do this instead of doing this.i++. Doing it this way, we do not
        // read this.i again, which is a bit faster.
        this.i = i + 1;
        if (i >= chunk.length) {
            return EOC;
        }
        // Using charCodeAt and handling the surrogates ourselves is faster
        // than using codePointAt.
        const code = chunk.charCodeAt(i);
        this.column++;
        if (code < 0xD800) {
            if ((code > 0x1F && code < 0x7F) || (code > 0x9F && code !== LS) ||
                code === TAB) {
                return code;
            }
            switch (code) {
                case NL: // 0xA
                    this.line++;
                    this.column = 0;
                    this.positionAtNewLine = this.position;
                    return NL;
                case CR: { // 0xD
                    // We may get NaN if we read past the end of the chunk, which is
                    // fine.
                    const next = chunk.charCodeAt(i + 1);
                    if (next === NL || next === NEL) {
                        // A CR NL or CR NEL sequence is converted to NL so we have to skip
                        // over the next character. We already know it has a size of 1.
                        this.i = i + 2;
                    }
                    // Otherwise, a CR is just converted to NL, no skip.
                }
                /* yes, fall through */
                case NEL: // 0x85
                case LS: // Ox2028
                    this.line++;
                    this.column = 0;
                    this.positionAtNewLine = this.position;
                    return NL_LIKE;
                default:
                    this.fail("disallowed character.");
                    return code;
            }
        }
        if (code > 0xDBFF) {
            // This is a specialized version of isCharAndNotRestricted that takes into
            // account that in this context code > 0xDBFF and code <= 0xFFFF. So it
            // does not test cases that don't need testing.
            if (!(code >= 0xE000 && code <= 0xFFFD)) {
                this.fail("disallowed character.");
            }
            return code;
        }
        const final = 0x10000 + ((code - 0xD800) * 0x400) +
            (chunk.charCodeAt(i + 1) - 0xDC00);
        this.i = i + 2;
        // This is a specialized version of isCharAndNotRestricted that takes into
        // account that in this context necessarily final >= 0x10000.
        if (final > 0x10FFFF) {
            this.fail("disallowed character.");
        }
        return final;
    }
    /**
     * Like ``getCode`` but with the return value normalized so that ``NL`` is
     * returned for ``NL_LIKE``.
     */
    getCodeNorm() {
        const c = this.getCode();
        return c === NL_LIKE ? NL : c;
    }
    unget() {
        this.i = this.prevI;
        this.column--;
    }
    /**
     * Capture characters into a buffer until encountering one of a set of
     * characters.
     *
     * @param chars An array of codepoints. Encountering a character in the array
     * ends the capture. (``chars`` may safely contain ``NL``.)
     *
     * @return The character code that made the capture end, or ``EOC`` if we hit
     * the end of the chunk. The return value cannot be NL_LIKE: NL is returned
     * instead.
     */
    captureTo(chars) {
        let { i: start } = this;
        const { chunk } = this;
        // eslint-disable-next-line no-constant-condition
        while (true) {
            const c = this.getCode();
            const isNLLike = c === NL_LIKE;
            const final = isNLLike ? NL : c;
            if (final === EOC || chars.includes(final)) {
                this.text += chunk.slice(start, this.prevI);
                return final;
            }
            if (isNLLike) {
                this.text += `${chunk.slice(start, this.prevI)}\n`;
                start = this.i;
            }
        }
    }
    /**
     * Capture characters into a buffer until encountering a character.
     *
     * @param char The codepoint that ends the capture. **NOTE ``char`` MAY NOT
     * CONTAIN ``NL``.** Passing ``NL`` will result in buggy behavior.
     *
     * @return ``true`` if we ran into the character. Otherwise, we ran into the
     * end of the current chunk.
     */
    captureToChar(char) {
        let { i: start } = this;
        const { chunk } = this;
        // eslint-disable-next-line no-constant-condition
        while (true) {
            let c = this.getCode();
            switch (c) {
                case NL_LIKE:
                    this.text += `${chunk.slice(start, this.prevI)}\n`;
                    start = this.i;
                    c = NL;
                    break;
                case EOC:
                    this.text += chunk.slice(start);
                    return false;
                default:
            }
            if (c === char) {
                this.text += chunk.slice(start, this.prevI);
                return true;
            }
        }
    }
    /**
     * Capture characters that satisfy ``isNameChar`` into the ``name`` field of
     * this parser.
     *
     * @return The character code that made the test fail, or ``EOC`` if we hit
     * the end of the chunk. The return value cannot be NL_LIKE: NL is returned
     * instead.
     */
    captureNameChars() {
        const { chunk, i: start } = this;
        // eslint-disable-next-line no-constant-condition
        while (true) {
            const c = this.getCode();
            if (c === EOC) {
                this.name += chunk.slice(start);
                return EOC;
            }
            // NL is not a name char so we don't have to test specifically for it.
            if (!isNameChar(c)) {
                this.name += chunk.slice(start, this.prevI);
                return c === NL_LIKE ? NL : c;
            }
        }
    }
    /**
     * Skip white spaces.
     *
     * @return The character that ended the skip, or ``EOC`` if we hit
     * the end of the chunk. The return value cannot be NL_LIKE: NL is returned
     * instead.
     */
    skipSpaces() {
        // eslint-disable-next-line no-constant-condition
        while (true) {
            const c = this.getCodeNorm();
            if (c === EOC || !isS(c)) {
                return c;
            }
        }
    }
    setXMLVersion(version) {
        this.currentXMLVersion = version;
        /*  eslint-disable @typescript-eslint/unbound-method */
        if (version === "1.0") {
            this.isChar = isChar10;
            this.getCode = this.getCode10;
        }
        else {
            this.isChar = isChar11;
            this.getCode = this.getCode11;
        }
        /* eslint-enable @typescript-eslint/unbound-method */
    }
    // STATE ENGINE METHODS
    // This needs to be a state separate from S_BEGIN_WHITESPACE because we want
    // to be sure never to come back to this state later.
    sBegin() {
        // We are essentially peeking at the first character of the chunk. Since
        // S_BEGIN can be in effect only when we start working on the first chunk,
        // the index at which we must look is necessarily 0. Note also that the
        // following test does not depend on decoding surrogates.
        // If the initial character is 0xFEFF, ignore it.
        if (this.chunk.charCodeAt(0) === 0xFEFF) {
            this.i++;
            this.column++;
        }
        this.state = S_BEGIN_WHITESPACE;
    }
    sBeginWhitespace() {
        // We need to know whether we've encountered spaces or not because as soon
        // as we run into a space, an XML declaration is no longer possible. Rather
        // than slow down skipSpaces even in places where we don't care whether it
        // skipped anything or not, we check whether prevI is equal to the value of
        // i from before we skip spaces.
        const iBefore = this.i;
        const c = this.skipSpaces();
        if (this.prevI !== iBefore) {
            this.xmlDeclPossible = false;
        }
        switch (c) {
            case LESS:
                this.state = S_OPEN_WAKA;
                // We could naively call closeText but in this state, it is not normal
                // to have text be filled with any data.
                if (this.text.length !== 0) {
                    throw new Error("no-empty text at start");
                }
                break;
            case EOC:
                break;
            default:
                this.unget();
                this.state = S_TEXT;
                this.xmlDeclPossible = false;
        }
    }
    sDoctype() {
        var _a;
        const c = this.captureTo(DOCTYPE_TERMINATOR);
        switch (c) {
            case GREATER: {
                // eslint-disable-next-line no-unused-expressions
                (_a = this.doctypeHandler) === null || _a === void 0 ? void 0 : _a.call(this, this.text);
                this.text = "";
                this.state = S_TEXT;
                this.doctype = true; // just remember that we saw it.
                break;
            }
            case EOC:
                break;
            default:
                this.text += String.fromCodePoint(c);
                if (c === OPEN_BRACKET) {
                    this.state = S_DTD;
                }
                else if (isQuote(c)) {
                    this.state = S_DOCTYPE_QUOTE;
                    this.q = c;
                }
        }
    }
    sDoctypeQuote() {
        const q = this.q;
        if (this.captureToChar(q)) {
            this.text += String.fromCodePoint(q);
            this.q = null;
            this.state = S_DOCTYPE;
        }
    }
    sDTD() {
        const c = this.captureTo(DTD_TERMINATOR);
        if (c === EOC) {
            return;
        }
        this.text += String.fromCodePoint(c);
        if (c === CLOSE_BRACKET) {
            this.state = S_DOCTYPE;
        }
        else if (c === LESS) {
            this.state = S_DTD_OPEN_WAKA;
        }
        else if (isQuote(c)) {
            this.state = S_DTD_QUOTED;
            this.q = c;
        }
    }
    sDTDQuoted() {
        const q = this.q;
        if (this.captureToChar(q)) {
            this.text += String.fromCodePoint(q);
            this.state = S_DTD;
            this.q = null;
        }
    }
    sDTDOpenWaka() {
        const c = this.getCodeNorm();
        this.text += String.fromCodePoint(c);
        switch (c) {
            case BANG:
                this.state = S_DTD_OPEN_WAKA_BANG;
                this.openWakaBang = "";
                break;
            case QUESTION:
                this.state = S_DTD_PI;
                break;
            default:
                this.state = S_DTD;
        }
    }
    sDTDOpenWakaBang() {
        const char = String.fromCodePoint(this.getCodeNorm());
        const owb = this.openWakaBang += char;
        this.text += char;
        if (owb !== "-") {
            this.state = owb === "--" ? S_DTD_COMMENT : S_DTD;
            this.openWakaBang = "";
        }
    }
    sDTDComment() {
        if (this.captureToChar(MINUS)) {
            this.text += "-";
            this.state = S_DTD_COMMENT_ENDING;
        }
    }
    sDTDCommentEnding() {
        const c = this.getCodeNorm();
        this.text += String.fromCodePoint(c);
        this.state = c === MINUS ? S_DTD_COMMENT_ENDED : S_DTD_COMMENT;
    }
    sDTDCommentEnded() {
        const c = this.getCodeNorm();
        this.text += String.fromCodePoint(c);
        if (c === GREATER) {
            this.state = S_DTD;
        }
        else {
            this.fail("malformed comment.");
            // <!-- blah -- bloo --> will be recorded as
            // a comment of " blah -- bloo "
            this.state = S_DTD_COMMENT;
        }
    }
    sDTDPI() {
        if (this.captureToChar(QUESTION)) {
            this.text += "?";
            this.state = S_DTD_PI_ENDING;
        }
    }
    sDTDPIEnding() {
        const c = this.getCodeNorm();
        this.text += String.fromCodePoint(c);
        if (c === GREATER) {
            this.state = S_DTD;
        }
    }
    sText() {
        //
        // We did try a version of saxes where the S_TEXT state was split in two
        // states: one for text inside the root element, and one for text
        // outside. This was avoiding having to test this.tags.length to decide
        // what implementation to actually use.
        //
        // Peformance testing on gigabyte-size files did not show any advantage to
        // using the two states solution instead of the current one. Conversely, it
        // made the code a bit more complicated elsewhere. For instance, a comment
        // can appear before the root element so when a comment ended it was
        // necessary to determine whether to return to the S_TEXT state or to the
        // new text-outside-root state.
        //
        if (this.tags.length !== 0) {
            this.handleTextInRoot();
        }
        else {
            this.handleTextOutsideRoot();
        }
    }
    sEntity() {
        // This is essentially a specialized version of captureToChar(SEMICOLON...)
        let { i: start } = this;
        const { chunk } = this;
        // eslint-disable-next-line no-labels, no-restricted-syntax
        loop: 
        // eslint-disable-next-line no-constant-condition
        while (true) {
            switch (this.getCode()) {
                case NL_LIKE:
                    this.entity += `${chunk.slice(start, this.prevI)}\n`;
                    start = this.i;
                    break;
                case SEMICOLON: {
                    const { entityReturnState } = this;
                    const entity = this.entity + chunk.slice(start, this.prevI);
                    this.state = entityReturnState;
                    let parsed;
                    if (entity === "") {
                        this.fail("empty entity name.");
                        parsed = "&;";
                    }
                    else {
                        parsed = this.parseEntity(entity);
                        this.entity = "";
                    }
                    if (entityReturnState !== S_TEXT || this.textHandler !== undefined) {
                        this.text += parsed;
                    }
                    // eslint-disable-next-line no-labels
                    break loop;
                }
                case EOC:
                    this.entity += chunk.slice(start);
                    // eslint-disable-next-line no-labels
                    break loop;
                default:
            }
        }
    }
    sOpenWaka() {
        // Reminder: a state handler is called with at least one character
        // available in the current chunk. So the first call to get code inside of
        // a state handler cannot return ``EOC``. That's why we don't test
        // for it.
        const c = this.getCode();
        // either a /, ?, !, or text is coming next.
        if (isNameStartChar(c)) {
            this.state = S_OPEN_TAG;
            this.unget();
            this.xmlDeclPossible = false;
        }
        else {
            switch (c) {
                case FORWARD_SLASH:
                    this.state = S_CLOSE_TAG;
                    this.xmlDeclPossible = false;
                    break;
                case BANG:
                    this.state = S_OPEN_WAKA_BANG;
                    this.openWakaBang = "";
                    this.xmlDeclPossible = false;
                    break;
                case QUESTION:
                    this.state = S_PI_FIRST_CHAR;
                    break;
                default:
                    this.fail("disallowed character in tag name");
                    this.state = S_TEXT;
                    this.xmlDeclPossible = false;
            }
        }
    }
    sOpenWakaBang() {
        this.openWakaBang += String.fromCodePoint(this.getCodeNorm());
        switch (this.openWakaBang) {
            case "[CDATA[":
                if (!this.sawRoot && !this.reportedTextBeforeRoot) {
                    this.fail("text data outside of root node.");
                    this.reportedTextBeforeRoot = true;
                }
                if (this.closedRoot && !this.reportedTextAfterRoot) {
                    this.fail("text data outside of root node.");
                    this.reportedTextAfterRoot = true;
                }
                this.state = S_CDATA;
                this.openWakaBang = "";
                break;
            case "--":
                this.state = S_COMMENT;
                this.openWakaBang = "";
                break;
            case "DOCTYPE":
                this.state = S_DOCTYPE;
                if (this.doctype || this.sawRoot) {
                    this.fail("inappropriately located doctype declaration.");
                }
                this.openWakaBang = "";
                break;
            default:
                // 7 happens to be the maximum length of the string that can possibly
                // match one of the cases above.
                if (this.openWakaBang.length >= 7) {
                    this.fail("incorrect syntax.");
                }
        }
    }
    sComment() {
        if (this.captureToChar(MINUS)) {
            this.state = S_COMMENT_ENDING;
        }
    }
    sCommentEnding() {
        var _a;
        const c = this.getCodeNorm();
        if (c === MINUS) {
            this.state = S_COMMENT_ENDED;
            // eslint-disable-next-line no-unused-expressions
            (_a = this.commentHandler) === null || _a === void 0 ? void 0 : _a.call(this, this.text);
            this.text = "";
        }
        else {
            this.text += `-${String.fromCodePoint(c)}`;
            this.state = S_COMMENT;
        }
    }
    sCommentEnded() {
        const c = this.getCodeNorm();
        if (c !== GREATER) {
            this.fail("malformed comment.");
            // <!-- blah -- bloo --> will be recorded as
            // a comment of " blah -- bloo "
            this.text += `--${String.fromCodePoint(c)}`;
            this.state = S_COMMENT;
        }
        else {
            this.state = S_TEXT;
        }
    }
    sCData() {
        if (this.captureToChar(CLOSE_BRACKET)) {
            this.state = S_CDATA_ENDING;
        }
    }
    sCDataEnding() {
        const c = this.getCodeNorm();
        if (c === CLOSE_BRACKET) {
            this.state = S_CDATA_ENDING_2;
        }
        else {
            this.text += `]${String.fromCodePoint(c)}`;
            this.state = S_CDATA;
        }
    }
    sCDataEnding2() {
        var _a;
        const c = this.getCodeNorm();
        switch (c) {
            case GREATER: {
                // eslint-disable-next-line no-unused-expressions
                (_a = this.cdataHandler) === null || _a === void 0 ? void 0 : _a.call(this, this.text);
                this.text = "";
                this.state = S_TEXT;
                break;
            }
            case CLOSE_BRACKET:
                this.text += "]";
                break;
            default:
                this.text += `]]${String.fromCodePoint(c)}`;
                this.state = S_CDATA;
        }
    }
    // We need this separate state to check the first character fo the pi target
    // with this.nameStartCheck which allows less characters than this.nameCheck.
    sPIFirstChar() {
        const c = this.getCodeNorm();
        // This is first because in the case where the file is well-formed this is
        // the branch taken. We optimize for well-formedness.
        if (this.nameStartCheck(c)) {
            this.piTarget += String.fromCodePoint(c);
            this.state = S_PI_REST;
        }
        else if (c === QUESTION || isS(c)) {
            this.fail("processing instruction without a target.");
            this.state = c === QUESTION ? S_PI_ENDING : S_PI_BODY;
        }
        else {
            this.fail("disallowed character in processing instruction name.");
            this.piTarget += String.fromCodePoint(c);
            this.state = S_PI_REST;
        }
    }
    sPIRest() {
        // Capture characters into a piTarget while ``this.nameCheck`` run on the
        // character read returns true.
        const { chunk, i: start } = this;
        // eslint-disable-next-line no-constant-condition
        while (true) {
            const c = this.getCodeNorm();
            if (c === EOC) {
                this.piTarget += chunk.slice(start);
                return;
            }
            // NL cannot satisfy this.nameCheck so we don't have to test specifically
            // for it.
            if (!this.nameCheck(c)) {
                this.piTarget += chunk.slice(start, this.prevI);
                const isQuestion = c === QUESTION;
                if (isQuestion || isS(c)) {
                    if (this.piTarget === "xml") {
                        if (!this.xmlDeclPossible) {
                            this.fail("an XML declaration must be at the start of the document.");
                        }
                        this.state = isQuestion ? S_XML_DECL_ENDING : S_XML_DECL_NAME_START;
                    }
                    else {
                        this.state = isQuestion ? S_PI_ENDING : S_PI_BODY;
                    }
                }
                else {
                    this.fail("disallowed character in processing instruction name.");
                    this.piTarget += String.fromCodePoint(c);
                }
                break;
            }
        }
    }
    sPIBody() {
        if (this.text.length === 0) {
            const c = this.getCodeNorm();
            if (c === QUESTION) {
                this.state = S_PI_ENDING;
            }
            else if (!isS(c)) {
                this.text = String.fromCodePoint(c);
            }
        }
        // The question mark character is not valid inside any of the XML
        // declaration name/value pairs.
        else if (this.captureToChar(QUESTION)) {
            this.state = S_PI_ENDING;
        }
    }
    sPIEnding() {
        var _a;
        const c = this.getCodeNorm();
        if (c === GREATER) {
            const { piTarget } = this;
            if (piTarget.toLowerCase() === "xml") {
                this.fail("the XML declaration must appear at the start of the document.");
            }
            // eslint-disable-next-line no-unused-expressions
            (_a = this.piHandler) === null || _a === void 0 ? void 0 : _a.call(this, {
                target: piTarget,
                body: this.text,
            });
            this.piTarget = this.text = "";
            this.state = S_TEXT;
        }
        else if (c === QUESTION) {
            // We ran into ?? as part of a processing instruction. We initially took
            // the first ? as a sign that the PI was ending, but it is not. So we have
            // to add it to the body but we take the new ? as a sign that the PI is
            // ending.
            this.text += "?";
        }
        else {
            this.text += `?${String.fromCodePoint(c)}`;
            this.state = S_PI_BODY;
        }
        this.xmlDeclPossible = false;
    }
    sXMLDeclNameStart() {
        const c = this.skipSpaces();
        // The question mark character is not valid inside any of the XML
        // declaration name/value pairs.
        if (c === QUESTION) {
            // It is valid to go to S_XML_DECL_ENDING from this state.
            this.state = S_XML_DECL_ENDING;
            return;
        }
        if (c !== EOC) {
            this.state = S_XML_DECL_NAME;
            this.name = String.fromCodePoint(c);
        }
    }
    sXMLDeclName() {
        const c = this.captureTo(XML_DECL_NAME_TERMINATOR);
        // The question mark character is not valid inside any of the XML
        // declaration name/value pairs.
        if (c === QUESTION) {
            this.state = S_XML_DECL_ENDING;
            this.name += this.text;
            this.text = "";
            this.fail("XML declaration is incomplete.");
            return;
        }
        if (!(isS(c) || c === EQUAL)) {
            return;
        }
        this.name += this.text;
        this.text = "";
        if (!this.xmlDeclExpects.includes(this.name)) {
            switch (this.name.length) {
                case 0:
                    this.fail("did not expect any more name/value pairs.");
                    break;
                case 1:
                    this.fail(`expected the name ${this.xmlDeclExpects[0]}.`);
                    break;
                default:
                    this.fail(`expected one of ${this.xmlDeclExpects.join(", ")}`);
            }
        }
        this.state = c === EQUAL ? S_XML_DECL_VALUE_START : S_XML_DECL_EQ;
    }
    sXMLDeclEq() {
        const c = this.getCodeNorm();
        // The question mark character is not valid inside any of the XML
        // declaration name/value pairs.
        if (c === QUESTION) {
            this.state = S_XML_DECL_ENDING;
            this.fail("XML declaration is incomplete.");
            return;
        }
        if (isS(c)) {
            return;
        }
        if (c !== EQUAL) {
            this.fail("value required.");
        }
        this.state = S_XML_DECL_VALUE_START;
    }
    sXMLDeclValueStart() {
        const c = this.getCodeNorm();
        // The question mark character is not valid inside any of the XML
        // declaration name/value pairs.
        if (c === QUESTION) {
            this.state = S_XML_DECL_ENDING;
            this.fail("XML declaration is incomplete.");
            return;
        }
        if (isS(c)) {
            return;
        }
        if (!isQuote(c)) {
            this.fail("value must be quoted.");
            this.q = SPACE;
        }
        else {
            this.q = c;
        }
        this.state = S_XML_DECL_VALUE;
    }
    sXMLDeclValue() {
        const c = this.captureTo([this.q, QUESTION]);
        // The question mark character is not valid inside any of the XML
        // declaration name/value pairs.
        if (c === QUESTION) {
            this.state = S_XML_DECL_ENDING;
            this.text = "";
            this.fail("XML declaration is incomplete.");
            return;
        }
        if (c === EOC) {
            return;
        }
        const value = this.text;
        this.text = "";
        switch (this.name) {
            case "version": {
                this.xmlDeclExpects = ["encoding", "standalone"];
                const version = value;
                this.xmlDecl.version = version;
                // This is the test specified by XML 1.0 but it is fine for XML 1.1.
                if (!/^1\.[0-9]+$/.test(version)) {
                    this.fail("version number must match /^1\\.[0-9]+$/.");
                }
                // When forceXMLVersion is set, the XML declaration is ignored.
                else if (!this.opt.forceXMLVersion) {
                    this.setXMLVersion(version);
                }
                break;
            }
            case "encoding":
                if (!/^[A-Za-z][A-Za-z0-9._-]*$/.test(value)) {
                    this.fail("encoding value must match \
/^[A-Za-z0-9][A-Za-z0-9._-]*$/.");
                }
                this.xmlDeclExpects = ["standalone"];
                this.xmlDecl.encoding = value;
                break;
            case "standalone":
                if (value !== "yes" && value !== "no") {
                    this.fail("standalone value must match \"yes\" or \"no\".");
                }
                this.xmlDeclExpects = [];
                this.xmlDecl.standalone = value;
                break;
            default:
            // We don't need to raise an error here since we've already raised one
            // when checking what name was expected.
        }
        this.name = "";
        this.state = S_XML_DECL_SEPARATOR;
    }
    sXMLDeclSeparator() {
        const c = this.getCodeNorm();
        // The question mark character is not valid inside any of the XML
        // declaration name/value pairs.
        if (c === QUESTION) {
            // It is valid to go to S_XML_DECL_ENDING from this state.
            this.state = S_XML_DECL_ENDING;
            return;
        }
        if (!isS(c)) {
            this.fail("whitespace required.");
            this.unget();
        }
        this.state = S_XML_DECL_NAME_START;
    }
    sXMLDeclEnding() {
        var _a;
        const c = this.getCodeNorm();
        if (c === GREATER) {
            if (this.piTarget !== "xml") {
                this.fail("processing instructions are not allowed before root.");
            }
            else if (this.name !== "version" &&
                this.xmlDeclExpects.includes("version")) {
                this.fail("XML declaration must contain a version.");
            }
            // eslint-disable-next-line no-unused-expressions
            (_a = this.xmldeclHandler) === null || _a === void 0 ? void 0 : _a.call(this, this.xmlDecl);
            this.name = "";
            this.piTarget = this.text = "";
            this.state = S_TEXT;
        }
        else {
            // We got here because the previous character was a ?, but the question
            // mark character is not valid inside any of the XML declaration
            // name/value pairs.
            this.fail("The character ? is disallowed anywhere in XML declarations.");
        }
        this.xmlDeclPossible = false;
    }
    sOpenTag() {
        var _a;
        const c = this.captureNameChars();
        if (c === EOC) {
            return;
        }
        const tag = this.tag = {
            name: this.name,
            attributes: Object.create(null),
        };
        this.name = "";
        if (this.xmlnsOpt) {
            this.topNS = tag.ns = Object.create(null);
        }
        // eslint-disable-next-line no-unused-expressions
        (_a = this.openTagStartHandler) === null || _a === void 0 ? void 0 : _a.call(this, tag);
        this.sawRoot = true;
        if (!this.fragmentOpt && this.closedRoot) {
            this.fail("documents may contain only one root.");
        }
        switch (c) {
            case GREATER:
                this.openTag();
                break;
            case FORWARD_SLASH:
                this.state = S_OPEN_TAG_SLASH;
                break;
            default:
                if (!isS(c)) {
                    this.fail("disallowed character in tag name.");
                }
                this.state = S_ATTRIB;
        }
    }
    sOpenTagSlash() {
        if (this.getCode() === GREATER) {
            this.openSelfClosingTag();
        }
        else {
            this.fail("forward-slash in opening tag not followed by >.");
            this.state = S_ATTRIB;
        }
    }
    sAttrib() {
        const c = this.skipSpaces();
        if (c === EOC) {
            return;
        }
        if (isNameStartChar(c)) {
            this.unget();
            this.state = S_ATTRIB_NAME;
        }
        else if (c === GREATER) {
            this.openTag();
        }
        else if (c === FORWARD_SLASH) {
            this.state = S_OPEN_TAG_SLASH;
        }
        else {
            this.fail("disallowed character in attribute name.");
        }
    }
    sAttribName() {
        const c = this.captureNameChars();
        if (c === EQUAL) {
            this.state = S_ATTRIB_VALUE;
        }
        else if (isS(c)) {
            this.state = S_ATTRIB_NAME_SAW_WHITE;
        }
        else if (c === GREATER) {
            this.fail("attribute without value.");
            this.pushAttrib(this.name, this.name);
            this.name = this.text = "";
            this.openTag();
        }
        else if (c !== EOC) {
            this.fail("disallowed character in attribute name.");
        }
    }
    sAttribNameSawWhite() {
        const c = this.skipSpaces();
        switch (c) {
            case EOC:
                return;
            case EQUAL:
                this.state = S_ATTRIB_VALUE;
                break;
            default:
                this.fail("attribute without value.");
                // Should we do this???
                // this.tag.attributes[this.name] = "";
                this.text = "";
                this.name = "";
                if (c === GREATER) {
                    this.openTag();
                }
                else if (isNameStartChar(c)) {
                    this.unget();
                    this.state = S_ATTRIB_NAME;
                }
                else {
                    this.fail("disallowed character in attribute name.");
                    this.state = S_ATTRIB;
                }
        }
    }
    sAttribValue() {
        const c = this.getCodeNorm();
        if (isQuote(c)) {
            this.q = c;
            this.state = S_ATTRIB_VALUE_QUOTED;
        }
        else if (!isS(c)) {
            this.fail("unquoted attribute value.");
            this.state = S_ATTRIB_VALUE_UNQUOTED;
            this.unget();
        }
    }
    sAttribValueQuoted() {
        // We deliberately do not use captureTo here. The specialized code we use
        // here is faster than using captureTo.
        const { q, chunk } = this;
        let { i: start } = this;
        // eslint-disable-next-line no-constant-condition
        while (true) {
            switch (this.getCode()) {
                case q:
                    this.pushAttrib(this.name, this.text + chunk.slice(start, this.prevI));
                    this.name = this.text = "";
                    this.q = null;
                    this.state = S_ATTRIB_VALUE_CLOSED;
                    return;
                case AMP:
                    this.text += chunk.slice(start, this.prevI);
                    this.state = S_ENTITY;
                    this.entityReturnState = S_ATTRIB_VALUE_QUOTED;
                    return;
                case NL:
                case NL_LIKE:
                case TAB:
                    this.text += `${chunk.slice(start, this.prevI)} `;
                    start = this.i;
                    break;
                case LESS:
                    this.text += chunk.slice(start, this.prevI);
                    this.fail("disallowed character.");
                    return;
                case EOC:
                    this.text += chunk.slice(start);
                    return;
                default:
            }
        }
    }
    sAttribValueClosed() {
        const c = this.getCodeNorm();
        if (isS(c)) {
            this.state = S_ATTRIB;
        }
        else if (c === GREATER) {
            this.openTag();
        }
        else if (c === FORWARD_SLASH) {
            this.state = S_OPEN_TAG_SLASH;
        }
        else if (isNameStartChar(c)) {
            this.fail("no whitespace between attributes.");
            this.unget();
            this.state = S_ATTRIB_NAME;
        }
        else {
            this.fail("disallowed character in attribute name.");
        }
    }
    sAttribValueUnquoted() {
        // We don't do anything regarding EOL or space handling for unquoted
        // attributes. We already have failed by the time we get here, and the
        // contract that saxes upholds states that upon failure, it is not safe to
        // rely on the data passed to event handlers (other than
        // ``onerror``). Passing "bad" data is not a problem.
        const c = this.captureTo(ATTRIB_VALUE_UNQUOTED_TERMINATOR);
        switch (c) {
            case AMP:
                this.state = S_ENTITY;
                this.entityReturnState = S_ATTRIB_VALUE_UNQUOTED;
                break;
            case LESS:
                this.fail("disallowed character.");
                break;
            case EOC:
                break;
            default:
                if (this.text.includes("]]>")) {
                    this.fail("the string \"]]>\" is disallowed in char data.");
                }
                this.pushAttrib(this.name, this.text);
                this.name = this.text = "";
                if (c === GREATER) {
                    this.openTag();
                }
                else {
                    this.state = S_ATTRIB;
                }
        }
    }
    sCloseTag() {
        const c = this.captureNameChars();
        if (c === GREATER) {
            this.closeTag();
        }
        else if (isS(c)) {
            this.state = S_CLOSE_TAG_SAW_WHITE;
        }
        else if (c !== EOC) {
            this.fail("disallowed character in closing tag.");
        }
    }
    sCloseTagSawWhite() {
        switch (this.skipSpaces()) {
            case GREATER:
                this.closeTag();
                break;
            case EOC:
                break;
            default:
                this.fail("disallowed character in closing tag.");
        }
    }
    // END OF STATE ENGINE METHODS
    handleTextInRoot() {
        // This is essentially a specialized version of captureTo which is optimized
        // for performing the ]]> check. A previous version of this code, checked
        // ``this.text`` for the presence of ]]>. It simplified the code but was
        // very costly when character data contained a lot of entities to be parsed.
        //
        // Since we are using a specialized loop, we also keep track of the presence
        // of ]]> in text data. The sequence ]]> is forbidden to appear as-is.
        //
        let { i: start, forbiddenState } = this;
        const { chunk, textHandler: handler } = this;
        // eslint-disable-next-line no-labels, no-restricted-syntax
        scanLoop: 
        // eslint-disable-next-line no-constant-condition
        while (true) {
            switch (this.getCode()) {
                case LESS: {
                    this.state = S_OPEN_WAKA;
                    if (handler !== undefined) {
                        const { text } = this;
                        const slice = chunk.slice(start, this.prevI);
                        if (text.length !== 0) {
                            handler(text + slice);
                            this.text = "";
                        }
                        else if (slice.length !== 0) {
                            handler(slice);
                        }
                    }
                    forbiddenState = FORBIDDEN_START;
                    // eslint-disable-next-line no-labels
                    break scanLoop;
                }
                case AMP:
                    this.state = S_ENTITY;
                    this.entityReturnState = S_TEXT;
                    if (handler !== undefined) {
                        this.text += chunk.slice(start, this.prevI);
                    }
                    forbiddenState = FORBIDDEN_START;
                    // eslint-disable-next-line no-labels
                    break scanLoop;
                case CLOSE_BRACKET:
                    switch (forbiddenState) {
                        case FORBIDDEN_START:
                            forbiddenState = FORBIDDEN_BRACKET;
                            break;
                        case FORBIDDEN_BRACKET:
                            forbiddenState = FORBIDDEN_BRACKET_BRACKET;
                            break;
                        case FORBIDDEN_BRACKET_BRACKET:
                            break;
                        default:
                            throw new Error("impossible state");
                    }
                    break;
                case GREATER:
                    if (forbiddenState === FORBIDDEN_BRACKET_BRACKET) {
                        this.fail("the string \"]]>\" is disallowed in char data.");
                    }
                    forbiddenState = FORBIDDEN_START;
                    break;
                case NL_LIKE:
                    if (handler !== undefined) {
                        this.text += `${chunk.slice(start, this.prevI)}\n`;
                    }
                    start = this.i;
                    forbiddenState = FORBIDDEN_START;
                    break;
                case EOC:
                    if (handler !== undefined) {
                        this.text += chunk.slice(start);
                    }
                    // eslint-disable-next-line no-labels
                    break scanLoop;
                default:
                    forbiddenState = FORBIDDEN_START;
            }
        }
        this.forbiddenState = forbiddenState;
    }
    handleTextOutsideRoot() {
        // This is essentially a specialized version of captureTo which is optimized
        // for a specialized task. We keep track of the presence of non-space
        // characters in the text since these are errors when appearing outside the
        // document root element.
        let { i: start } = this;
        const { chunk, textHandler: handler } = this;
        let nonSpace = false;
        // eslint-disable-next-line no-labels, no-restricted-syntax
        outRootLoop: 
        // eslint-disable-next-line no-constant-condition
        while (true) {
            const code = this.getCode();
            switch (code) {
                case LESS: {
                    this.state = S_OPEN_WAKA;
                    if (handler !== undefined) {
                        const { text } = this;
                        const slice = chunk.slice(start, this.prevI);
                        if (text.length !== 0) {
                            handler(text + slice);
                            this.text = "";
                        }
                        else if (slice.length !== 0) {
                            handler(slice);
                        }
                    }
                    // eslint-disable-next-line no-labels
                    break outRootLoop;
                }
                case AMP:
                    this.state = S_ENTITY;
                    this.entityReturnState = S_TEXT;
                    if (handler !== undefined) {
                        this.text += chunk.slice(start, this.prevI);
                    }
                    nonSpace = true;
                    // eslint-disable-next-line no-labels
                    break outRootLoop;
                case NL_LIKE:
                    if (handler !== undefined) {
                        this.text += `${chunk.slice(start, this.prevI)}\n`;
                    }
                    start = this.i;
                    break;
                case EOC:
                    if (handler !== undefined) {
                        this.text += chunk.slice(start);
                    }
                    // eslint-disable-next-line no-labels
                    break outRootLoop;
                default:
                    if (!isS(code)) {
                        nonSpace = true;
                    }
            }
        }
        if (!nonSpace) {
            return;
        }
        // We use the reportedTextBeforeRoot and reportedTextAfterRoot flags
        // to avoid reporting errors for every single character that is out of
        // place.
        if (!this.sawRoot && !this.reportedTextBeforeRoot) {
            this.fail("text data outside of root node.");
            this.reportedTextBeforeRoot = true;
        }
        if (this.closedRoot && !this.reportedTextAfterRoot) {
            this.fail("text data outside of root node.");
            this.reportedTextAfterRoot = true;
        }
    }
    pushAttribNS(name, value) {
        var _a;
        const { prefix, local } = this.qname(name);
        const attr = { name, prefix, local, value };
        this.attribList.push(attr);
        // eslint-disable-next-line no-unused-expressions
        (_a = this.attributeHandler) === null || _a === void 0 ? void 0 : _a.call(this, attr);
        if (prefix === "xmlns") {
            const trimmed = value.trim();
            if (this.currentXMLVersion === "1.0" && trimmed === "") {
                this.fail("invalid attempt to undefine prefix in XML 1.0");
            }
            this.topNS[local] = trimmed;
            nsPairCheck(this, local, trimmed);
        }
        else if (name === "xmlns") {
            const trimmed = value.trim();
            this.topNS[""] = trimmed;
            nsPairCheck(this, "", trimmed);
        }
    }
    pushAttribPlain(name, value) {
        var _a;
        const attr = { name, value };
        this.attribList.push(attr);
        // eslint-disable-next-line no-unused-expressions
        (_a = this.attributeHandler) === null || _a === void 0 ? void 0 : _a.call(this, attr);
    }
    /**
     * End parsing. This performs final well-formedness checks and resets the
     * parser to a clean state.
     *
     * @returns this
     */
    end() {
        var _a, _b;
        if (!this.sawRoot) {
            this.fail("document must contain a root element.");
        }
        const { tags } = this;
        while (tags.length > 0) {
            const tag = tags.pop();
            this.fail(`unclosed tag: ${tag.name}`);
        }
        if ((this.state !== S_BEGIN) && (this.state !== S_TEXT)) {
            this.fail("unexpected end.");
        }
        const { text } = this;
        if (text.length !== 0) {
            // eslint-disable-next-line no-unused-expressions
            (_a = this.textHandler) === null || _a === void 0 ? void 0 : _a.call(this, text);
            this.text = "";
        }
        this._closed = true;
        // eslint-disable-next-line no-unused-expressions
        (_b = this.endHandler) === null || _b === void 0 ? void 0 : _b.call(this);
        this._init();
        return this;
    }
    /**
     * Resolve a namespace prefix.
     *
     * @param prefix The prefix to resolve.
     *
     * @returns The namespace URI or ``undefined`` if the prefix is not defined.
     */
    resolve(prefix) {
        var _a, _b;
        let uri = this.topNS[prefix];
        if (uri !== undefined) {
            return uri;
        }
        const { tags } = this;
        for (let index = tags.length - 1; index >= 0; index--) {
            uri = tags[index].ns[prefix];
            if (uri !== undefined) {
                return uri;
            }
        }
        uri = this.ns[prefix];
        if (uri !== undefined) {
            return uri;
        }
        return (_b = (_a = this.opt).resolvePrefix) === null || _b === void 0 ? void 0 : _b.call(_a, prefix);
    }
    /**
     * Parse a qname into its prefix and local name parts.
     *
     * @param name The name to parse
     *
     * @returns
     */
    qname(name) {
        // This is faster than using name.split(":").
        const colon = name.indexOf(":");
        if (colon === -1) {
            return { prefix: "", local: name };
        }
        const local = name.slice(colon + 1);
        const prefix = name.slice(0, colon);
        if (prefix === "" || local === "" || local.includes(":")) {
            this.fail(`malformed name: ${name}.`);
        }
        return { prefix, local };
    }
    processAttribsNS() {
        var _a;
        const { attribList } = this;
        const tag = this.tag;
        {
            // add namespace info to tag
            const { prefix, local } = this.qname(tag.name);
            tag.prefix = prefix;
            tag.local = local;
            const uri = tag.uri = (_a = this.resolve(prefix)) !== null && _a !== void 0 ? _a : "";
            if (prefix !== "") {
                if (prefix === "xmlns") {
                    this.fail("tags may not have \"xmlns\" as prefix.");
                }
                if (uri === "") {
                    this.fail(`unbound namespace prefix: ${JSON.stringify(prefix)}.`);
                    tag.uri = prefix;
                }
            }
        }
        if (attribList.length === 0) {
            return;
        }
        const { attributes } = tag;
        const seen = new Set();
        // Note: do not apply default ns to attributes:
        //   http://www.w3.org/TR/REC-xml-names/#defaulting
        for (const attr of attribList) {
            const { name, prefix, local } = attr;
            let uri;
            let eqname;
            if (prefix === "") {
                uri = name === "xmlns" ? XMLNS_NAMESPACE : "";
                eqname = name;
            }
            else {
                uri = this.resolve(prefix);
                // if there's any attributes with an undefined namespace,
                // then fail on them now.
                if (uri === undefined) {
                    this.fail(`unbound namespace prefix: ${JSON.stringify(prefix)}.`);
                    uri = prefix;
                }
                eqname = `{${uri}}${local}`;
            }
            if (seen.has(eqname)) {
                this.fail(`duplicate attribute: ${eqname}.`);
            }
            seen.add(eqname);
            attr.uri = uri;
            attributes[name] = attr;
        }
        this.attribList = [];
    }
    processAttribsPlain() {
        const { attribList } = this;
        // eslint-disable-next-line prefer-destructuring
        const attributes = this.tag.attributes;
        for (const { name, value } of attribList) {
            if (attributes[name] !== undefined) {
                this.fail(`duplicate attribute: ${name}.`);
            }
            attributes[name] = value;
        }
        this.attribList = [];
    }
    /**
     * Handle a complete open tag. This parser code calls this once it has seen
     * the whole tag. This method checks for well-formeness and then emits
     * ``onopentag``.
     */
    openTag() {
        var _a;
        this.processAttribs();
        const { tags } = this;
        const tag = this.tag;
        tag.isSelfClosing = false;
        // There cannot be any pending text here due to the onopentagstart that was
        // necessarily emitted before we get here. So we do not check text.
        // eslint-disable-next-line no-unused-expressions
        (_a = this.openTagHandler) === null || _a === void 0 ? void 0 : _a.call(this, tag);
        tags.push(tag);
        this.state = S_TEXT;
        this.name = "";
    }
    /**
     * Handle a complete self-closing tag. This parser code calls this once it has
     * seen the whole tag. This method checks for well-formeness and then emits
     * ``onopentag`` and ``onclosetag``.
     */
    openSelfClosingTag() {
        var _a, _b, _c;
        this.processAttribs();
        const { tags } = this;
        const tag = this.tag;
        tag.isSelfClosing = true;
        // There cannot be any pending text here due to the onopentagstart that was
        // necessarily emitted before we get here. So we do not check text.
        // eslint-disable-next-line no-unused-expressions
        (_a = this.openTagHandler) === null || _a === void 0 ? void 0 : _a.call(this, tag);
        // eslint-disable-next-line no-unused-expressions
        (_b = this.closeTagHandler) === null || _b === void 0 ? void 0 : _b.call(this, tag);
        const top = this.tag = (_c = tags[tags.length - 1]) !== null && _c !== void 0 ? _c : null;
        if (top === null) {
            this.closedRoot = true;
        }
        this.state = S_TEXT;
        this.name = "";
    }
    /**
     * Handle a complete close tag. This parser code calls this once it has seen
     * the whole tag. This method checks for well-formeness and then emits
     * ``onclosetag``.
     */
    closeTag() {
        const { tags, name } = this;
        // Our state after this will be S_TEXT, no matter what, and we can clear
        // tagName now.
        this.state = S_TEXT;
        this.name = "";
        if (name === "") {
            this.fail("weird empty close tag.");
            this.text += "</>";
            return;
        }
        const handler = this.closeTagHandler;
        let l = tags.length;
        while (l-- > 0) {
            const tag = this.tag = tags.pop();
            this.topNS = tag.ns;
            // eslint-disable-next-line no-unused-expressions
            handler === null || handler === void 0 ? void 0 : handler(tag);
            if (tag.name === name) {
                break;
            }
            this.fail("unexpected close tag.");
        }
        if (l === 0) {
            this.closedRoot = true;
        }
        else if (l < 0) {
            this.fail(`unmatched closing tag: ${name}.`);
            this.text += `</${name}>`;
        }
    }
    /**
     * Resolves an entity. Makes any necessary well-formedness checks.
     *
     * @param entity The entity to resolve.
     *
     * @returns The parsed entity.
     */
    parseEntity(entity) {
        // startsWith would be significantly slower for this test.
        // eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
        if (entity[0] !== "#") {
            const defined = this.ENTITIES[entity];
            if (defined !== undefined) {
                return defined;
            }
            this.fail(this.isName(entity) ? "undefined entity." :
                "disallowed character in entity name.");
            return `&${entity};`;
        }
        let num = NaN;
        if (entity[1] === "x" && /^#x[0-9a-f]+$/i.test(entity)) {
            num = parseInt(entity.slice(2), 16);
        }
        else if (/^#[0-9]+$/.test(entity)) {
            num = parseInt(entity.slice(1), 10);
        }
        // The character reference is required to match the CHAR production.
        if (!this.isChar(num)) {
            this.fail("malformed character entity.");
            return `&${entity};`;
        }
        return String.fromCodePoint(num);
    }
}
exports.SaxesParser = SaxesParser;
//# sourceMappingURL=saxes.js.map