pdf_viewer.mjs 259 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * JavaScript code in this page
  4. *
  5. * Copyright 2024 Mozilla Foundation
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * @licend The above is the entire license notice for the
  20. * JavaScript code in this page
  21. */
  22. /******/ // The require scope
  23. /******/ var __webpack_require__ = {};
  24. /******/
  25. /************************************************************************/
  26. /******/ /* webpack/runtime/define property getters */
  27. /******/ (() => {
  28. /******/ // define getter functions for harmony exports
  29. /******/ __webpack_require__.d = (exports, definition) => {
  30. /******/ for(var key in definition) {
  31. /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
  32. /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
  33. /******/ }
  34. /******/ }
  35. /******/ };
  36. /******/ })();
  37. /******/
  38. /******/ /* webpack/runtime/hasOwnProperty shorthand */
  39. /******/ (() => {
  40. /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
  41. /******/ })();
  42. /******/
  43. /************************************************************************/
  44. var __webpack_exports__ = globalThis.pdfjsViewer = {};
  45. // EXPORTS
  46. __webpack_require__.d(__webpack_exports__, {
  47. AnnotationLayerBuilder: () => (/* reexport */ AnnotationLayerBuilder),
  48. DownloadManager: () => (/* reexport */ DownloadManager),
  49. EventBus: () => (/* reexport */ EventBus),
  50. FindState: () => (/* reexport */ FindState),
  51. GenericL10n: () => (/* reexport */ genericl10n_GenericL10n),
  52. LinkTarget: () => (/* reexport */ LinkTarget),
  53. PDFFindController: () => (/* reexport */ PDFFindController),
  54. PDFHistory: () => (/* reexport */ PDFHistory),
  55. PDFLinkService: () => (/* reexport */ PDFLinkService),
  56. PDFPageView: () => (/* reexport */ PDFPageView),
  57. PDFScriptingManager: () => (/* reexport */ PDFScriptingManagerComponents),
  58. PDFSinglePageViewer: () => (/* reexport */ PDFSinglePageViewer),
  59. PDFViewer: () => (/* reexport */ PDFViewer),
  60. ProgressBar: () => (/* reexport */ ProgressBar),
  61. RenderingStates: () => (/* reexport */ RenderingStates),
  62. ScrollMode: () => (/* reexport */ ScrollMode),
  63. SimpleLinkService: () => (/* reexport */ SimpleLinkService),
  64. SpreadMode: () => (/* reexport */ SpreadMode),
  65. StructTreeLayerBuilder: () => (/* reexport */ StructTreeLayerBuilder),
  66. TextLayerBuilder: () => (/* reexport */ TextLayerBuilder),
  67. XfaLayerBuilder: () => (/* reexport */ XfaLayerBuilder),
  68. parseQueryString: () => (/* reexport */ parseQueryString)
  69. });
  70. ;// ./web/ui_utils.js
  71. const DEFAULT_SCALE_VALUE = "auto";
  72. const DEFAULT_SCALE = 1.0;
  73. const DEFAULT_SCALE_DELTA = 1.1;
  74. const MIN_SCALE = 0.1;
  75. const MAX_SCALE = 10.0;
  76. const UNKNOWN_SCALE = 0;
  77. const MAX_AUTO_SCALE = 1.25;
  78. const SCROLLBAR_PADDING = 40;
  79. const VERTICAL_PADDING = 5;
  80. const RenderingStates = {
  81. INITIAL: 0,
  82. RUNNING: 1,
  83. PAUSED: 2,
  84. FINISHED: 3
  85. };
  86. const PresentationModeState = {
  87. UNKNOWN: 0,
  88. NORMAL: 1,
  89. CHANGING: 2,
  90. FULLSCREEN: 3
  91. };
  92. const SidebarView = {
  93. UNKNOWN: -1,
  94. NONE: 0,
  95. THUMBS: 1,
  96. OUTLINE: 2,
  97. ATTACHMENTS: 3,
  98. LAYERS: 4
  99. };
  100. const TextLayerMode = {
  101. DISABLE: 0,
  102. ENABLE: 1,
  103. ENABLE_PERMISSIONS: 2
  104. };
  105. const ScrollMode = {
  106. UNKNOWN: -1,
  107. VERTICAL: 0,
  108. HORIZONTAL: 1,
  109. WRAPPED: 2,
  110. PAGE: 3
  111. };
  112. const SpreadMode = {
  113. UNKNOWN: -1,
  114. NONE: 0,
  115. ODD: 1,
  116. EVEN: 2
  117. };
  118. const CursorTool = {
  119. SELECT: 0,
  120. HAND: 1,
  121. ZOOM: 2
  122. };
  123. const AutoPrintRegExp = /\bprint\s*\(/;
  124. function scrollIntoView(element, spot, scrollMatches = false) {
  125. let parent = element.offsetParent;
  126. if (!parent) {
  127. console.error("offsetParent is not set -- cannot scroll");
  128. return;
  129. }
  130. let offsetY = element.offsetTop + element.clientTop;
  131. let offsetX = element.offsetLeft + element.clientLeft;
  132. while (parent.clientHeight === parent.scrollHeight && parent.clientWidth === parent.scrollWidth || scrollMatches && (parent.classList.contains("markedContent") || getComputedStyle(parent).overflow === "hidden")) {
  133. offsetY += parent.offsetTop;
  134. offsetX += parent.offsetLeft;
  135. parent = parent.offsetParent;
  136. if (!parent) {
  137. return;
  138. }
  139. }
  140. if (spot) {
  141. if (spot.top !== undefined) {
  142. offsetY += spot.top;
  143. }
  144. if (spot.left !== undefined) {
  145. offsetX += spot.left;
  146. parent.scrollLeft = offsetX;
  147. }
  148. }
  149. parent.scrollTop = offsetY;
  150. }
  151. function watchScroll(viewAreaElement, callback, abortSignal = undefined) {
  152. const debounceScroll = function (evt) {
  153. if (rAF) {
  154. return;
  155. }
  156. rAF = window.requestAnimationFrame(function viewAreaElementScrolled() {
  157. rAF = null;
  158. const currentX = viewAreaElement.scrollLeft;
  159. const lastX = state.lastX;
  160. if (currentX !== lastX) {
  161. state.right = currentX > lastX;
  162. }
  163. state.lastX = currentX;
  164. const currentY = viewAreaElement.scrollTop;
  165. const lastY = state.lastY;
  166. if (currentY !== lastY) {
  167. state.down = currentY > lastY;
  168. }
  169. state.lastY = currentY;
  170. callback(state);
  171. });
  172. };
  173. const state = {
  174. right: true,
  175. down: true,
  176. lastX: viewAreaElement.scrollLeft,
  177. lastY: viewAreaElement.scrollTop,
  178. _eventHandler: debounceScroll
  179. };
  180. let rAF = null;
  181. viewAreaElement.addEventListener("scroll", debounceScroll, {
  182. useCapture: true,
  183. signal: abortSignal
  184. });
  185. abortSignal?.addEventListener("abort", () => window.cancelAnimationFrame(rAF), {
  186. once: true
  187. });
  188. return state;
  189. }
  190. function parseQueryString(query) {
  191. const params = new Map();
  192. for (const [key, value] of new URLSearchParams(query)) {
  193. params.set(key.toLowerCase(), value);
  194. }
  195. return params;
  196. }
  197. const InvisibleCharsRegExp = /[\x00-\x1F]/g;
  198. function removeNullCharacters(str, replaceInvisible = false) {
  199. if (!InvisibleCharsRegExp.test(str)) {
  200. return str;
  201. }
  202. if (replaceInvisible) {
  203. return str.replaceAll(InvisibleCharsRegExp, m => m === "\x00" ? "" : " ");
  204. }
  205. return str.replaceAll("\x00", "");
  206. }
  207. function binarySearchFirstItem(items, condition, start = 0) {
  208. let minIndex = start;
  209. let maxIndex = items.length - 1;
  210. if (maxIndex < 0 || !condition(items[maxIndex])) {
  211. return items.length;
  212. }
  213. if (condition(items[minIndex])) {
  214. return minIndex;
  215. }
  216. while (minIndex < maxIndex) {
  217. const currentIndex = minIndex + maxIndex >> 1;
  218. const currentItem = items[currentIndex];
  219. if (condition(currentItem)) {
  220. maxIndex = currentIndex;
  221. } else {
  222. minIndex = currentIndex + 1;
  223. }
  224. }
  225. return minIndex;
  226. }
  227. function approximateFraction(x) {
  228. if (Math.floor(x) === x) {
  229. return [x, 1];
  230. }
  231. const xinv = 1 / x;
  232. const limit = 8;
  233. if (xinv > limit) {
  234. return [1, limit];
  235. } else if (Math.floor(xinv) === xinv) {
  236. return [1, xinv];
  237. }
  238. const x_ = x > 1 ? xinv : x;
  239. let a = 0,
  240. b = 1,
  241. c = 1,
  242. d = 1;
  243. while (true) {
  244. const p = a + c,
  245. q = b + d;
  246. if (q > limit) {
  247. break;
  248. }
  249. if (x_ <= p / q) {
  250. c = p;
  251. d = q;
  252. } else {
  253. a = p;
  254. b = q;
  255. }
  256. }
  257. let result;
  258. if (x_ - a / b < c / d - x_) {
  259. result = x_ === x ? [a, b] : [b, a];
  260. } else {
  261. result = x_ === x ? [c, d] : [d, c];
  262. }
  263. return result;
  264. }
  265. function floorToDivide(x, div) {
  266. return x - x % div;
  267. }
  268. function getPageSizeInches({
  269. view,
  270. userUnit,
  271. rotate
  272. }) {
  273. const [x1, y1, x2, y2] = view;
  274. const changeOrientation = rotate % 180 !== 0;
  275. const width = (x2 - x1) / 72 * userUnit;
  276. const height = (y2 - y1) / 72 * userUnit;
  277. return {
  278. width: changeOrientation ? height : width,
  279. height: changeOrientation ? width : height
  280. };
  281. }
  282. function backtrackBeforeAllVisibleElements(index, views, top) {
  283. if (index < 2) {
  284. return index;
  285. }
  286. let elt = views[index].div;
  287. let pageTop = elt.offsetTop + elt.clientTop;
  288. if (pageTop >= top) {
  289. elt = views[index - 1].div;
  290. pageTop = elt.offsetTop + elt.clientTop;
  291. }
  292. for (let i = index - 2; i >= 0; --i) {
  293. elt = views[i].div;
  294. if (elt.offsetTop + elt.clientTop + elt.clientHeight <= pageTop) {
  295. break;
  296. }
  297. index = i;
  298. }
  299. return index;
  300. }
  301. function getVisibleElements({
  302. scrollEl,
  303. views,
  304. sortByVisibility = false,
  305. horizontal = false,
  306. rtl = false
  307. }) {
  308. const top = scrollEl.scrollTop,
  309. bottom = top + scrollEl.clientHeight;
  310. const left = scrollEl.scrollLeft,
  311. right = left + scrollEl.clientWidth;
  312. function isElementBottomAfterViewTop(view) {
  313. const element = view.div;
  314. const elementBottom = element.offsetTop + element.clientTop + element.clientHeight;
  315. return elementBottom > top;
  316. }
  317. function isElementNextAfterViewHorizontally(view) {
  318. const element = view.div;
  319. const elementLeft = element.offsetLeft + element.clientLeft;
  320. const elementRight = elementLeft + element.clientWidth;
  321. return rtl ? elementLeft < right : elementRight > left;
  322. }
  323. const visible = [],
  324. ids = new Set(),
  325. numViews = views.length;
  326. let firstVisibleElementInd = binarySearchFirstItem(views, horizontal ? isElementNextAfterViewHorizontally : isElementBottomAfterViewTop);
  327. if (firstVisibleElementInd > 0 && firstVisibleElementInd < numViews && !horizontal) {
  328. firstVisibleElementInd = backtrackBeforeAllVisibleElements(firstVisibleElementInd, views, top);
  329. }
  330. let lastEdge = horizontal ? right : -1;
  331. for (let i = firstVisibleElementInd; i < numViews; i++) {
  332. const view = views[i],
  333. element = view.div;
  334. const currentWidth = element.offsetLeft + element.clientLeft;
  335. const currentHeight = element.offsetTop + element.clientTop;
  336. const viewWidth = element.clientWidth,
  337. viewHeight = element.clientHeight;
  338. const viewRight = currentWidth + viewWidth;
  339. const viewBottom = currentHeight + viewHeight;
  340. if (lastEdge === -1) {
  341. if (viewBottom >= bottom) {
  342. lastEdge = viewBottom;
  343. }
  344. } else if ((horizontal ? currentWidth : currentHeight) > lastEdge) {
  345. break;
  346. }
  347. if (viewBottom <= top || currentHeight >= bottom || viewRight <= left || currentWidth >= right) {
  348. continue;
  349. }
  350. const hiddenHeight = Math.max(0, top - currentHeight) + Math.max(0, viewBottom - bottom);
  351. const hiddenWidth = Math.max(0, left - currentWidth) + Math.max(0, viewRight - right);
  352. const fractionHeight = (viewHeight - hiddenHeight) / viewHeight,
  353. fractionWidth = (viewWidth - hiddenWidth) / viewWidth;
  354. const percent = fractionHeight * fractionWidth * 100 | 0;
  355. visible.push({
  356. id: view.id,
  357. x: currentWidth,
  358. y: currentHeight,
  359. view,
  360. percent,
  361. widthPercent: fractionWidth * 100 | 0
  362. });
  363. ids.add(view.id);
  364. }
  365. const first = visible[0],
  366. last = visible.at(-1);
  367. if (sortByVisibility) {
  368. visible.sort(function (a, b) {
  369. const pc = a.percent - b.percent;
  370. if (Math.abs(pc) > 0.001) {
  371. return -pc;
  372. }
  373. return a.id - b.id;
  374. });
  375. }
  376. return {
  377. first,
  378. last,
  379. views: visible,
  380. ids
  381. };
  382. }
  383. function normalizeWheelEventDirection(evt) {
  384. let delta = Math.hypot(evt.deltaX, evt.deltaY);
  385. const angle = Math.atan2(evt.deltaY, evt.deltaX);
  386. if (-0.25 * Math.PI < angle && angle < 0.75 * Math.PI) {
  387. delta = -delta;
  388. }
  389. return delta;
  390. }
  391. function normalizeWheelEventDelta(evt) {
  392. const deltaMode = evt.deltaMode;
  393. let delta = normalizeWheelEventDirection(evt);
  394. const MOUSE_PIXELS_PER_LINE = 30;
  395. const MOUSE_LINES_PER_PAGE = 30;
  396. if (deltaMode === WheelEvent.DOM_DELTA_PIXEL) {
  397. delta /= MOUSE_PIXELS_PER_LINE * MOUSE_LINES_PER_PAGE;
  398. } else if (deltaMode === WheelEvent.DOM_DELTA_LINE) {
  399. delta /= MOUSE_LINES_PER_PAGE;
  400. }
  401. return delta;
  402. }
  403. function isValidRotation(angle) {
  404. return Number.isInteger(angle) && angle % 90 === 0;
  405. }
  406. function isValidScrollMode(mode) {
  407. return Number.isInteger(mode) && Object.values(ScrollMode).includes(mode) && mode !== ScrollMode.UNKNOWN;
  408. }
  409. function isValidSpreadMode(mode) {
  410. return Number.isInteger(mode) && Object.values(SpreadMode).includes(mode) && mode !== SpreadMode.UNKNOWN;
  411. }
  412. function isPortraitOrientation(size) {
  413. return size.width <= size.height;
  414. }
  415. const animationStarted = new Promise(function (resolve) {
  416. window.requestAnimationFrame(resolve);
  417. });
  418. const docStyle = document.documentElement.style;
  419. function clamp(v, min, max) {
  420. return Math.min(Math.max(v, min), max);
  421. }
  422. class ProgressBar {
  423. #classList = null;
  424. #disableAutoFetchTimeout = null;
  425. #percent = 0;
  426. #style = null;
  427. #visible = true;
  428. constructor(bar) {
  429. this.#classList = bar.classList;
  430. this.#style = bar.style;
  431. }
  432. get percent() {
  433. return this.#percent;
  434. }
  435. set percent(val) {
  436. this.#percent = clamp(val, 0, 100);
  437. if (isNaN(val)) {
  438. this.#classList.add("indeterminate");
  439. return;
  440. }
  441. this.#classList.remove("indeterminate");
  442. this.#style.setProperty("--progressBar-percent", `${this.#percent}%`);
  443. }
  444. setWidth(viewer) {
  445. if (!viewer) {
  446. return;
  447. }
  448. const container = viewer.parentNode;
  449. const scrollbarWidth = container.offsetWidth - viewer.offsetWidth;
  450. if (scrollbarWidth > 0) {
  451. this.#style.setProperty("--progressBar-end-offset", `${scrollbarWidth}px`);
  452. }
  453. }
  454. setDisableAutoFetch(delay = 5000) {
  455. if (this.#percent === 100 || isNaN(this.#percent)) {
  456. return;
  457. }
  458. if (this.#disableAutoFetchTimeout) {
  459. clearTimeout(this.#disableAutoFetchTimeout);
  460. }
  461. this.show();
  462. this.#disableAutoFetchTimeout = setTimeout(() => {
  463. this.#disableAutoFetchTimeout = null;
  464. this.hide();
  465. }, delay);
  466. }
  467. hide() {
  468. if (!this.#visible) {
  469. return;
  470. }
  471. this.#visible = false;
  472. this.#classList.add("hidden");
  473. }
  474. show() {
  475. if (this.#visible) {
  476. return;
  477. }
  478. this.#visible = true;
  479. this.#classList.remove("hidden");
  480. }
  481. }
  482. function getActiveOrFocusedElement() {
  483. let curRoot = document;
  484. let curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(":focus");
  485. while (curActiveOrFocused?.shadowRoot) {
  486. curRoot = curActiveOrFocused.shadowRoot;
  487. curActiveOrFocused = curRoot.activeElement || curRoot.querySelector(":focus");
  488. }
  489. return curActiveOrFocused;
  490. }
  491. function apiPageLayoutToViewerModes(layout) {
  492. let scrollMode = ScrollMode.VERTICAL,
  493. spreadMode = SpreadMode.NONE;
  494. switch (layout) {
  495. case "SinglePage":
  496. scrollMode = ScrollMode.PAGE;
  497. break;
  498. case "OneColumn":
  499. break;
  500. case "TwoPageLeft":
  501. scrollMode = ScrollMode.PAGE;
  502. case "TwoColumnLeft":
  503. spreadMode = SpreadMode.ODD;
  504. break;
  505. case "TwoPageRight":
  506. scrollMode = ScrollMode.PAGE;
  507. case "TwoColumnRight":
  508. spreadMode = SpreadMode.EVEN;
  509. break;
  510. }
  511. return {
  512. scrollMode,
  513. spreadMode
  514. };
  515. }
  516. function apiPageModeToSidebarView(mode) {
  517. switch (mode) {
  518. case "UseNone":
  519. return SidebarView.NONE;
  520. case "UseThumbs":
  521. return SidebarView.THUMBS;
  522. case "UseOutlines":
  523. return SidebarView.OUTLINE;
  524. case "UseAttachments":
  525. return SidebarView.ATTACHMENTS;
  526. case "UseOC":
  527. return SidebarView.LAYERS;
  528. }
  529. return SidebarView.NONE;
  530. }
  531. function toggleCheckedBtn(button, toggle, view = null) {
  532. button.classList.toggle("toggled", toggle);
  533. button.setAttribute("aria-checked", toggle);
  534. view?.classList.toggle("hidden", !toggle);
  535. }
  536. function toggleExpandedBtn(button, toggle, view = null) {
  537. button.classList.toggle("toggled", toggle);
  538. button.setAttribute("aria-expanded", toggle);
  539. view?.classList.toggle("hidden", !toggle);
  540. }
  541. const calcRound = function () {
  542. const e = document.createElement("div");
  543. e.style.width = "round(down, calc(1.6666666666666665 * 792px), 1px)";
  544. return e.style.width === "calc(1320px)" ? Math.fround : x => x;
  545. }();
  546. ;// ./web/pdf_find_utils.js
  547. const CharacterType = {
  548. SPACE: 0,
  549. ALPHA_LETTER: 1,
  550. PUNCT: 2,
  551. HAN_LETTER: 3,
  552. KATAKANA_LETTER: 4,
  553. HIRAGANA_LETTER: 5,
  554. HALFWIDTH_KATAKANA_LETTER: 6,
  555. THAI_LETTER: 7
  556. };
  557. function isAlphabeticalScript(charCode) {
  558. return charCode < 0x2e80;
  559. }
  560. function isAscii(charCode) {
  561. return (charCode & 0xff80) === 0;
  562. }
  563. function isAsciiAlpha(charCode) {
  564. return charCode >= 0x61 && charCode <= 0x7a || charCode >= 0x41 && charCode <= 0x5a;
  565. }
  566. function isAsciiDigit(charCode) {
  567. return charCode >= 0x30 && charCode <= 0x39;
  568. }
  569. function isAsciiSpace(charCode) {
  570. return charCode === 0x20 || charCode === 0x09 || charCode === 0x0d || charCode === 0x0a;
  571. }
  572. function isHan(charCode) {
  573. return charCode >= 0x3400 && charCode <= 0x9fff || charCode >= 0xf900 && charCode <= 0xfaff;
  574. }
  575. function isKatakana(charCode) {
  576. return charCode >= 0x30a0 && charCode <= 0x30ff;
  577. }
  578. function isHiragana(charCode) {
  579. return charCode >= 0x3040 && charCode <= 0x309f;
  580. }
  581. function isHalfwidthKatakana(charCode) {
  582. return charCode >= 0xff60 && charCode <= 0xff9f;
  583. }
  584. function isThai(charCode) {
  585. return (charCode & 0xff80) === 0x0e00;
  586. }
  587. function getCharacterType(charCode) {
  588. if (isAlphabeticalScript(charCode)) {
  589. if (isAscii(charCode)) {
  590. if (isAsciiSpace(charCode)) {
  591. return CharacterType.SPACE;
  592. } else if (isAsciiAlpha(charCode) || isAsciiDigit(charCode) || charCode === 0x5f) {
  593. return CharacterType.ALPHA_LETTER;
  594. }
  595. return CharacterType.PUNCT;
  596. } else if (isThai(charCode)) {
  597. return CharacterType.THAI_LETTER;
  598. } else if (charCode === 0xa0) {
  599. return CharacterType.SPACE;
  600. }
  601. return CharacterType.ALPHA_LETTER;
  602. }
  603. if (isHan(charCode)) {
  604. return CharacterType.HAN_LETTER;
  605. } else if (isKatakana(charCode)) {
  606. return CharacterType.KATAKANA_LETTER;
  607. } else if (isHiragana(charCode)) {
  608. return CharacterType.HIRAGANA_LETTER;
  609. } else if (isHalfwidthKatakana(charCode)) {
  610. return CharacterType.HALFWIDTH_KATAKANA_LETTER;
  611. }
  612. return CharacterType.ALPHA_LETTER;
  613. }
  614. let NormalizeWithNFKC;
  615. function getNormalizeWithNFKC() {
  616. NormalizeWithNFKC ||= ` ¨ª¯²-µ¸-º¼-¾IJ-ijĿ-ŀʼnſDŽ-njDZ-dzʰ-ʸ˘-˝ˠ-ˤʹͺ;΄-΅·ϐ-ϖϰ-ϲϴ-ϵϹևٵ-ٸक़-य़ড়-ঢ়য়ਲ਼ਸ਼ਖ਼-ਜ਼ਫ਼ଡ଼-ଢ଼ำຳໜ-ໝ༌གྷཌྷདྷབྷཛྷཀྵჼᴬ-ᴮᴰ-ᴺᴼ-ᵍᵏ-ᵪᵸᶛ-ᶿẚ-ẛάέήίόύώΆ᾽-῁ΈΉ῍-῏ΐΊ῝-῟ΰΎ῭-`ΌΏ´-῾ - ‑‗․-… ″-‴‶-‷‼‾⁇-⁉⁗ ⁰-ⁱ⁴-₎ₐ-ₜ₨℀-℃℅-ℇ℉-ℓℕ-№ℙ-ℝ℠-™ℤΩℨK-ℭℯ-ℱℳ-ℹ℻-⅀ⅅ-ⅉ⅐-ⅿ↉∬-∭∯-∰〈-〉①-⓪⨌⩴-⩶⫝̸ⱼ-ⱽⵯ⺟⻳⼀-⿕ 〶〸-〺゛-゜ゟヿㄱ-ㆎ㆒-㆟㈀-㈞㈠-㉇㉐-㉾㊀-㏿ꚜ-ꚝꝰꟲ-ꟴꟸ-ꟹꭜ-ꭟꭩ豈-嗀塚晴凞-羽蘒諸逸-都飯-舘並-龎ff-stﬓ-ﬗיִײַ-זּטּ-לּמּנּ-סּףּ-פּצּ-ﮱﯓ-ﴽﵐ-ﶏﶒ-ﷇﷰ-﷼︐-︙︰-﹄﹇-﹒﹔-﹦﹨-﹫ﹰ-ﹲﹴﹶ-ﻼ!-하-ᅦᅧ-ᅬᅭ-ᅲᅳ-ᅵ¢-₩`;
  617. return NormalizeWithNFKC;
  618. }
  619. ;// ./web/pdf_find_controller.js
  620. const FindState = {
  621. FOUND: 0,
  622. NOT_FOUND: 1,
  623. WRAPPED: 2,
  624. PENDING: 3
  625. };
  626. const FIND_TIMEOUT = 250;
  627. const MATCH_SCROLL_OFFSET_TOP = -50;
  628. const MATCH_SCROLL_OFFSET_LEFT = -400;
  629. const CHARACTERS_TO_NORMALIZE = {
  630. "\u2010": "-",
  631. "\u2018": "'",
  632. "\u2019": "'",
  633. "\u201A": "'",
  634. "\u201B": "'",
  635. "\u201C": '"',
  636. "\u201D": '"',
  637. "\u201E": '"',
  638. "\u201F": '"',
  639. "\u00BC": "1/4",
  640. "\u00BD": "1/2",
  641. "\u00BE": "3/4"
  642. };
  643. const DIACRITICS_EXCEPTION = new Set([0x3099, 0x309a, 0x094d, 0x09cd, 0x0a4d, 0x0acd, 0x0b4d, 0x0bcd, 0x0c4d, 0x0ccd, 0x0d3b, 0x0d3c, 0x0d4d, 0x0dca, 0x0e3a, 0x0eba, 0x0f84, 0x1039, 0x103a, 0x1714, 0x1734, 0x17d2, 0x1a60, 0x1b44, 0x1baa, 0x1bab, 0x1bf2, 0x1bf3, 0x2d7f, 0xa806, 0xa82c, 0xa8c4, 0xa953, 0xa9c0, 0xaaf6, 0xabed, 0x0c56, 0x0f71, 0x0f72, 0x0f7a, 0x0f7b, 0x0f7c, 0x0f7d, 0x0f80, 0x0f74]);
  644. let DIACRITICS_EXCEPTION_STR;
  645. const DIACRITICS_REG_EXP = /\p{M}+/gu;
  646. const SPECIAL_CHARS_REG_EXP = /([.*+?^${}()|[\]\\])|(\p{P})|(\s+)|(\p{M})|(\p{L})/gu;
  647. const NOT_DIACRITIC_FROM_END_REG_EXP = /([^\p{M}])\p{M}*$/u;
  648. const NOT_DIACRITIC_FROM_START_REG_EXP = /^\p{M}*([^\p{M}])/u;
  649. const SYLLABLES_REG_EXP = /[\uAC00-\uD7AF\uFA6C\uFACF-\uFAD1\uFAD5-\uFAD7]+/g;
  650. const SYLLABLES_LENGTHS = new Map();
  651. const FIRST_CHAR_SYLLABLES_REG_EXP = "[\\u1100-\\u1112\\ud7a4-\\ud7af\\ud84a\\ud84c\\ud850\\ud854\\ud857\\ud85f]";
  652. const NFKC_CHARS_TO_NORMALIZE = new Map();
  653. let noSyllablesRegExp = null;
  654. let withSyllablesRegExp = null;
  655. function normalize(text) {
  656. const syllablePositions = [];
  657. let m;
  658. while ((m = SYLLABLES_REG_EXP.exec(text)) !== null) {
  659. let {
  660. index
  661. } = m;
  662. for (const char of m[0]) {
  663. let len = SYLLABLES_LENGTHS.get(char);
  664. if (!len) {
  665. len = char.normalize("NFD").length;
  666. SYLLABLES_LENGTHS.set(char, len);
  667. }
  668. syllablePositions.push([len, index++]);
  669. }
  670. }
  671. let normalizationRegex;
  672. if (syllablePositions.length === 0 && noSyllablesRegExp) {
  673. normalizationRegex = noSyllablesRegExp;
  674. } else if (syllablePositions.length > 0 && withSyllablesRegExp) {
  675. normalizationRegex = withSyllablesRegExp;
  676. } else {
  677. const replace = Object.keys(CHARACTERS_TO_NORMALIZE).join("");
  678. const toNormalizeWithNFKC = getNormalizeWithNFKC();
  679. const CJK = "(?:\\p{Ideographic}|[\u3040-\u30FF])";
  680. const HKDiacritics = "(?:\u3099|\u309A)";
  681. const CompoundWord = "\\p{Ll}-\\n\\p{Lu}";
  682. const regexp = `([${replace}])|([${toNormalizeWithNFKC}])|(${HKDiacritics}\\n)|(\\p{M}+(?:-\\n)?)|(${CompoundWord})|(\\S-\\n)|(${CJK}\\n)|(\\n)`;
  683. if (syllablePositions.length === 0) {
  684. normalizationRegex = noSyllablesRegExp = new RegExp(regexp + "|(\\u0000)", "gum");
  685. } else {
  686. normalizationRegex = withSyllablesRegExp = new RegExp(regexp + `|(${FIRST_CHAR_SYLLABLES_REG_EXP})`, "gum");
  687. }
  688. }
  689. const rawDiacriticsPositions = [];
  690. while ((m = DIACRITICS_REG_EXP.exec(text)) !== null) {
  691. rawDiacriticsPositions.push([m[0].length, m.index]);
  692. }
  693. let normalized = text.normalize("NFD");
  694. const positions = [0, 0];
  695. let rawDiacriticsIndex = 0;
  696. let syllableIndex = 0;
  697. let shift = 0;
  698. let shiftOrigin = 0;
  699. let eol = 0;
  700. let hasDiacritics = false;
  701. normalized = normalized.replace(normalizationRegex, (match, p1, p2, p3, p4, p5, p6, p7, p8, p9, i) => {
  702. i -= shiftOrigin;
  703. if (p1) {
  704. const replacement = CHARACTERS_TO_NORMALIZE[p1];
  705. const jj = replacement.length;
  706. for (let j = 1; j < jj; j++) {
  707. positions.push(i - shift + j, shift - j);
  708. }
  709. shift -= jj - 1;
  710. return replacement;
  711. }
  712. if (p2) {
  713. let replacement = NFKC_CHARS_TO_NORMALIZE.get(p2);
  714. if (!replacement) {
  715. replacement = p2.normalize("NFKC");
  716. NFKC_CHARS_TO_NORMALIZE.set(p2, replacement);
  717. }
  718. const jj = replacement.length;
  719. for (let j = 1; j < jj; j++) {
  720. positions.push(i - shift + j, shift - j);
  721. }
  722. shift -= jj - 1;
  723. return replacement;
  724. }
  725. if (p3) {
  726. hasDiacritics = true;
  727. if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) {
  728. ++rawDiacriticsIndex;
  729. } else {
  730. positions.push(i - 1 - shift + 1, shift - 1);
  731. shift -= 1;
  732. shiftOrigin += 1;
  733. }
  734. positions.push(i - shift + 1, shift);
  735. shiftOrigin += 1;
  736. eol += 1;
  737. return p3.charAt(0);
  738. }
  739. if (p4) {
  740. const hasTrailingDashEOL = p4.endsWith("\n");
  741. const len = hasTrailingDashEOL ? p4.length - 2 : p4.length;
  742. hasDiacritics = true;
  743. let jj = len;
  744. if (i + eol === rawDiacriticsPositions[rawDiacriticsIndex]?.[1]) {
  745. jj -= rawDiacriticsPositions[rawDiacriticsIndex][0];
  746. ++rawDiacriticsIndex;
  747. }
  748. for (let j = 1; j <= jj; j++) {
  749. positions.push(i - 1 - shift + j, shift - j);
  750. }
  751. shift -= jj;
  752. shiftOrigin += jj;
  753. if (hasTrailingDashEOL) {
  754. i += len - 1;
  755. positions.push(i - shift + 1, 1 + shift);
  756. shift += 1;
  757. shiftOrigin += 1;
  758. eol += 1;
  759. return p4.slice(0, len);
  760. }
  761. return p4;
  762. }
  763. if (p5) {
  764. shiftOrigin += 1;
  765. eol += 1;
  766. return p5.replace("\n", "");
  767. }
  768. if (p6) {
  769. const len = p6.length - 2;
  770. positions.push(i - shift + len, 1 + shift);
  771. shift += 1;
  772. shiftOrigin += 1;
  773. eol += 1;
  774. return p6.slice(0, -2);
  775. }
  776. if (p7) {
  777. const len = p7.length - 1;
  778. positions.push(i - shift + len, shift);
  779. shiftOrigin += 1;
  780. eol += 1;
  781. return p7.slice(0, -1);
  782. }
  783. if (p8) {
  784. positions.push(i - shift + 1, shift - 1);
  785. shift -= 1;
  786. shiftOrigin += 1;
  787. eol += 1;
  788. return " ";
  789. }
  790. if (i + eol === syllablePositions[syllableIndex]?.[1]) {
  791. const newCharLen = syllablePositions[syllableIndex][0] - 1;
  792. ++syllableIndex;
  793. for (let j = 1; j <= newCharLen; j++) {
  794. positions.push(i - (shift - j), shift - j);
  795. }
  796. shift -= newCharLen;
  797. shiftOrigin += newCharLen;
  798. }
  799. return p9;
  800. });
  801. positions.push(normalized.length, shift);
  802. const starts = new Uint32Array(positions.length >> 1);
  803. const shifts = new Int32Array(positions.length >> 1);
  804. for (let i = 0, ii = positions.length; i < ii; i += 2) {
  805. starts[i >> 1] = positions[i];
  806. shifts[i >> 1] = positions[i + 1];
  807. }
  808. return [normalized, [starts, shifts], hasDiacritics];
  809. }
  810. function getOriginalIndex(diffs, pos, len) {
  811. if (!diffs) {
  812. return [pos, len];
  813. }
  814. const [starts, shifts] = diffs;
  815. const start = pos;
  816. const end = pos + len - 1;
  817. let i = binarySearchFirstItem(starts, x => x >= start);
  818. if (starts[i] > start) {
  819. --i;
  820. }
  821. let j = binarySearchFirstItem(starts, x => x >= end, i);
  822. if (starts[j] > end) {
  823. --j;
  824. }
  825. const oldStart = start + shifts[i];
  826. const oldEnd = end + shifts[j];
  827. const oldLen = oldEnd + 1 - oldStart;
  828. return [oldStart, oldLen];
  829. }
  830. class PDFFindController {
  831. #state = null;
  832. #updateMatchesCountOnProgress = true;
  833. #visitedPagesCount = 0;
  834. constructor({
  835. linkService,
  836. eventBus,
  837. updateMatchesCountOnProgress = true
  838. }) {
  839. this._linkService = linkService;
  840. this._eventBus = eventBus;
  841. this.#updateMatchesCountOnProgress = updateMatchesCountOnProgress;
  842. this.onIsPageVisible = null;
  843. this.#reset();
  844. eventBus._on("find", this.#onFind.bind(this));
  845. eventBus._on("findbarclose", this.#onFindBarClose.bind(this));
  846. }
  847. get highlightMatches() {
  848. return this._highlightMatches;
  849. }
  850. get pageMatches() {
  851. return this._pageMatches;
  852. }
  853. get pageMatchesLength() {
  854. return this._pageMatchesLength;
  855. }
  856. get selected() {
  857. return this._selected;
  858. }
  859. get state() {
  860. return this.#state;
  861. }
  862. setDocument(pdfDocument) {
  863. if (this._pdfDocument) {
  864. this.#reset();
  865. }
  866. if (!pdfDocument) {
  867. return;
  868. }
  869. this._pdfDocument = pdfDocument;
  870. this._firstPageCapability.resolve();
  871. }
  872. #onFind(state) {
  873. if (!state) {
  874. return;
  875. }
  876. const pdfDocument = this._pdfDocument;
  877. const {
  878. type
  879. } = state;
  880. if (this.#state === null || this.#shouldDirtyMatch(state)) {
  881. this._dirtyMatch = true;
  882. }
  883. this.#state = state;
  884. if (type !== "highlightallchange") {
  885. this.#updateUIState(FindState.PENDING);
  886. }
  887. this._firstPageCapability.promise.then(() => {
  888. if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) {
  889. return;
  890. }
  891. this.#extractText();
  892. const findbarClosed = !this._highlightMatches;
  893. const pendingTimeout = !!this._findTimeout;
  894. if (this._findTimeout) {
  895. clearTimeout(this._findTimeout);
  896. this._findTimeout = null;
  897. }
  898. if (!type) {
  899. this._findTimeout = setTimeout(() => {
  900. this.#nextMatch();
  901. this._findTimeout = null;
  902. }, FIND_TIMEOUT);
  903. } else if (this._dirtyMatch) {
  904. this.#nextMatch();
  905. } else if (type === "again") {
  906. this.#nextMatch();
  907. if (findbarClosed && this.#state.highlightAll) {
  908. this.#updateAllPages();
  909. }
  910. } else if (type === "highlightallchange") {
  911. if (pendingTimeout) {
  912. this.#nextMatch();
  913. } else {
  914. this._highlightMatches = true;
  915. }
  916. this.#updateAllPages();
  917. } else {
  918. this.#nextMatch();
  919. }
  920. });
  921. }
  922. scrollMatchIntoView({
  923. element = null,
  924. selectedLeft = 0,
  925. pageIndex = -1,
  926. matchIndex = -1
  927. }) {
  928. if (!this._scrollMatches || !element) {
  929. return;
  930. } else if (matchIndex === -1 || matchIndex !== this._selected.matchIdx) {
  931. return;
  932. } else if (pageIndex === -1 || pageIndex !== this._selected.pageIdx) {
  933. return;
  934. }
  935. this._scrollMatches = false;
  936. const spot = {
  937. top: MATCH_SCROLL_OFFSET_TOP,
  938. left: selectedLeft + MATCH_SCROLL_OFFSET_LEFT
  939. };
  940. scrollIntoView(element, spot, true);
  941. }
  942. #reset() {
  943. this._highlightMatches = false;
  944. this._scrollMatches = false;
  945. this._pdfDocument = null;
  946. this._pageMatches = [];
  947. this._pageMatchesLength = [];
  948. this.#visitedPagesCount = 0;
  949. this.#state = null;
  950. this._selected = {
  951. pageIdx: -1,
  952. matchIdx: -1
  953. };
  954. this._offset = {
  955. pageIdx: null,
  956. matchIdx: null,
  957. wrapped: false
  958. };
  959. this._extractTextPromises = [];
  960. this._pageContents = [];
  961. this._pageDiffs = [];
  962. this._hasDiacritics = [];
  963. this._matchesCountTotal = 0;
  964. this._pagesToSearch = null;
  965. this._pendingFindMatches = new Set();
  966. this._resumePageIdx = null;
  967. this._dirtyMatch = false;
  968. clearTimeout(this._findTimeout);
  969. this._findTimeout = null;
  970. this._firstPageCapability = Promise.withResolvers();
  971. }
  972. get #query() {
  973. const {
  974. query
  975. } = this.#state;
  976. if (typeof query === "string") {
  977. if (query !== this._rawQuery) {
  978. this._rawQuery = query;
  979. [this._normalizedQuery] = normalize(query);
  980. }
  981. return this._normalizedQuery;
  982. }
  983. return (query || []).filter(q => !!q).map(q => normalize(q)[0]);
  984. }
  985. #shouldDirtyMatch(state) {
  986. const newQuery = state.query,
  987. prevQuery = this.#state.query;
  988. const newType = typeof newQuery,
  989. prevType = typeof prevQuery;
  990. if (newType !== prevType) {
  991. return true;
  992. }
  993. if (newType === "string") {
  994. if (newQuery !== prevQuery) {
  995. return true;
  996. }
  997. } else if (JSON.stringify(newQuery) !== JSON.stringify(prevQuery)) {
  998. return true;
  999. }
  1000. switch (state.type) {
  1001. case "again":
  1002. const pageNumber = this._selected.pageIdx + 1;
  1003. const linkService = this._linkService;
  1004. return pageNumber >= 1 && pageNumber <= linkService.pagesCount && pageNumber !== linkService.page && !(this.onIsPageVisible?.(pageNumber) ?? true);
  1005. case "highlightallchange":
  1006. return false;
  1007. }
  1008. return true;
  1009. }
  1010. #isEntireWord(content, startIdx, length) {
  1011. let match = content.slice(0, startIdx).match(NOT_DIACRITIC_FROM_END_REG_EXP);
  1012. if (match) {
  1013. const first = content.charCodeAt(startIdx);
  1014. const limit = match[1].charCodeAt(0);
  1015. if (getCharacterType(first) === getCharacterType(limit)) {
  1016. return false;
  1017. }
  1018. }
  1019. match = content.slice(startIdx + length).match(NOT_DIACRITIC_FROM_START_REG_EXP);
  1020. if (match) {
  1021. const last = content.charCodeAt(startIdx + length - 1);
  1022. const limit = match[1].charCodeAt(0);
  1023. if (getCharacterType(last) === getCharacterType(limit)) {
  1024. return false;
  1025. }
  1026. }
  1027. return true;
  1028. }
  1029. #convertToRegExpString(query, hasDiacritics) {
  1030. const {
  1031. matchDiacritics
  1032. } = this.#state;
  1033. let isUnicode = false;
  1034. query = query.replaceAll(SPECIAL_CHARS_REG_EXP, (match, p1, p2, p3, p4, p5) => {
  1035. if (p1) {
  1036. return `[ ]*\\${p1}[ ]*`;
  1037. }
  1038. if (p2) {
  1039. return `[ ]*${p2}[ ]*`;
  1040. }
  1041. if (p3) {
  1042. return "[ ]+";
  1043. }
  1044. if (matchDiacritics) {
  1045. return p4 || p5;
  1046. }
  1047. if (p4) {
  1048. return DIACRITICS_EXCEPTION.has(p4.charCodeAt(0)) ? p4 : "";
  1049. }
  1050. if (hasDiacritics) {
  1051. isUnicode = true;
  1052. return `${p5}\\p{M}*`;
  1053. }
  1054. return p5;
  1055. });
  1056. const trailingSpaces = "[ ]*";
  1057. if (query.endsWith(trailingSpaces)) {
  1058. query = query.slice(0, query.length - trailingSpaces.length);
  1059. }
  1060. if (matchDiacritics) {
  1061. if (hasDiacritics) {
  1062. DIACRITICS_EXCEPTION_STR ||= String.fromCharCode(...DIACRITICS_EXCEPTION);
  1063. isUnicode = true;
  1064. query = `${query}(?=[${DIACRITICS_EXCEPTION_STR}]|[^\\p{M}]|$)`;
  1065. }
  1066. }
  1067. return [isUnicode, query];
  1068. }
  1069. #calculateMatch(pageIndex) {
  1070. const query = this.#query;
  1071. if (query.length === 0) {
  1072. return;
  1073. }
  1074. const pageContent = this._pageContents[pageIndex];
  1075. const matcherResult = this.match(query, pageContent, pageIndex);
  1076. const matches = this._pageMatches[pageIndex] = [];
  1077. const matchesLength = this._pageMatchesLength[pageIndex] = [];
  1078. const diffs = this._pageDiffs[pageIndex];
  1079. matcherResult?.forEach(({
  1080. index,
  1081. length
  1082. }) => {
  1083. const [matchPos, matchLen] = getOriginalIndex(diffs, index, length);
  1084. if (matchLen) {
  1085. matches.push(matchPos);
  1086. matchesLength.push(matchLen);
  1087. }
  1088. });
  1089. if (this.#state.highlightAll) {
  1090. this.#updatePage(pageIndex);
  1091. }
  1092. if (this._resumePageIdx === pageIndex) {
  1093. this._resumePageIdx = null;
  1094. this.#nextPageMatch();
  1095. }
  1096. const pageMatchesCount = matches.length;
  1097. this._matchesCountTotal += pageMatchesCount;
  1098. if (this.#updateMatchesCountOnProgress) {
  1099. if (pageMatchesCount > 0) {
  1100. this.#updateUIResultsCount();
  1101. }
  1102. } else if (++this.#visitedPagesCount === this._linkService.pagesCount) {
  1103. this.#updateUIResultsCount();
  1104. }
  1105. }
  1106. match(query, pageContent, pageIndex) {
  1107. const hasDiacritics = this._hasDiacritics[pageIndex];
  1108. let isUnicode = false;
  1109. if (typeof query === "string") {
  1110. [isUnicode, query] = this.#convertToRegExpString(query, hasDiacritics);
  1111. } else {
  1112. query = query.sort().reverse().map(q => {
  1113. const [isUnicodePart, queryPart] = this.#convertToRegExpString(q, hasDiacritics);
  1114. isUnicode ||= isUnicodePart;
  1115. return `(${queryPart})`;
  1116. }).join("|");
  1117. }
  1118. if (!query) {
  1119. return undefined;
  1120. }
  1121. const {
  1122. caseSensitive,
  1123. entireWord
  1124. } = this.#state;
  1125. const flags = `g${isUnicode ? "u" : ""}${caseSensitive ? "" : "i"}`;
  1126. query = new RegExp(query, flags);
  1127. const matches = [];
  1128. let match;
  1129. while ((match = query.exec(pageContent)) !== null) {
  1130. if (entireWord && !this.#isEntireWord(pageContent, match.index, match[0].length)) {
  1131. continue;
  1132. }
  1133. matches.push({
  1134. index: match.index,
  1135. length: match[0].length
  1136. });
  1137. }
  1138. return matches;
  1139. }
  1140. #extractText() {
  1141. if (this._extractTextPromises.length > 0) {
  1142. return;
  1143. }
  1144. let deferred = Promise.resolve();
  1145. const textOptions = {
  1146. disableNormalization: true
  1147. };
  1148. for (let i = 0, ii = this._linkService.pagesCount; i < ii; i++) {
  1149. const {
  1150. promise,
  1151. resolve
  1152. } = Promise.withResolvers();
  1153. this._extractTextPromises[i] = promise;
  1154. deferred = deferred.then(() => {
  1155. return this._pdfDocument.getPage(i + 1).then(pdfPage => pdfPage.getTextContent(textOptions)).then(textContent => {
  1156. const strBuf = [];
  1157. for (const textItem of textContent.items) {
  1158. strBuf.push(textItem.str);
  1159. if (textItem.hasEOL) {
  1160. strBuf.push("\n");
  1161. }
  1162. }
  1163. [this._pageContents[i], this._pageDiffs[i], this._hasDiacritics[i]] = normalize(strBuf.join(""));
  1164. resolve();
  1165. }, reason => {
  1166. console.error(`Unable to get text content for page ${i + 1}`, reason);
  1167. this._pageContents[i] = "";
  1168. this._pageDiffs[i] = null;
  1169. this._hasDiacritics[i] = false;
  1170. resolve();
  1171. });
  1172. });
  1173. }
  1174. }
  1175. #updatePage(index) {
  1176. if (this._scrollMatches && this._selected.pageIdx === index) {
  1177. this._linkService.page = index + 1;
  1178. }
  1179. this._eventBus.dispatch("updatetextlayermatches", {
  1180. source: this,
  1181. pageIndex: index
  1182. });
  1183. }
  1184. #updateAllPages() {
  1185. this._eventBus.dispatch("updatetextlayermatches", {
  1186. source: this,
  1187. pageIndex: -1
  1188. });
  1189. }
  1190. #nextMatch() {
  1191. const previous = this.#state.findPrevious;
  1192. const currentPageIndex = this._linkService.page - 1;
  1193. const numPages = this._linkService.pagesCount;
  1194. this._highlightMatches = true;
  1195. if (this._dirtyMatch) {
  1196. this._dirtyMatch = false;
  1197. this._selected.pageIdx = this._selected.matchIdx = -1;
  1198. this._offset.pageIdx = currentPageIndex;
  1199. this._offset.matchIdx = null;
  1200. this._offset.wrapped = false;
  1201. this._resumePageIdx = null;
  1202. this._pageMatches.length = 0;
  1203. this._pageMatchesLength.length = 0;
  1204. this.#visitedPagesCount = 0;
  1205. this._matchesCountTotal = 0;
  1206. this.#updateAllPages();
  1207. for (let i = 0; i < numPages; i++) {
  1208. if (this._pendingFindMatches.has(i)) {
  1209. continue;
  1210. }
  1211. this._pendingFindMatches.add(i);
  1212. this._extractTextPromises[i].then(() => {
  1213. this._pendingFindMatches.delete(i);
  1214. this.#calculateMatch(i);
  1215. });
  1216. }
  1217. }
  1218. const query = this.#query;
  1219. if (query.length === 0) {
  1220. this.#updateUIState(FindState.FOUND);
  1221. return;
  1222. }
  1223. if (this._resumePageIdx) {
  1224. return;
  1225. }
  1226. const offset = this._offset;
  1227. this._pagesToSearch = numPages;
  1228. if (offset.matchIdx !== null) {
  1229. const numPageMatches = this._pageMatches[offset.pageIdx].length;
  1230. if (!previous && offset.matchIdx + 1 < numPageMatches || previous && offset.matchIdx > 0) {
  1231. offset.matchIdx = previous ? offset.matchIdx - 1 : offset.matchIdx + 1;
  1232. this.#updateMatch(true);
  1233. return;
  1234. }
  1235. this.#advanceOffsetPage(previous);
  1236. }
  1237. this.#nextPageMatch();
  1238. }
  1239. #matchesReady(matches) {
  1240. const offset = this._offset;
  1241. const numMatches = matches.length;
  1242. const previous = this.#state.findPrevious;
  1243. if (numMatches) {
  1244. offset.matchIdx = previous ? numMatches - 1 : 0;
  1245. this.#updateMatch(true);
  1246. return true;
  1247. }
  1248. this.#advanceOffsetPage(previous);
  1249. if (offset.wrapped) {
  1250. offset.matchIdx = null;
  1251. if (this._pagesToSearch < 0) {
  1252. this.#updateMatch(false);
  1253. return true;
  1254. }
  1255. }
  1256. return false;
  1257. }
  1258. #nextPageMatch() {
  1259. if (this._resumePageIdx !== null) {
  1260. console.error("There can only be one pending page.");
  1261. }
  1262. let matches = null;
  1263. do {
  1264. const pageIdx = this._offset.pageIdx;
  1265. matches = this._pageMatches[pageIdx];
  1266. if (!matches) {
  1267. this._resumePageIdx = pageIdx;
  1268. break;
  1269. }
  1270. } while (!this.#matchesReady(matches));
  1271. }
  1272. #advanceOffsetPage(previous) {
  1273. const offset = this._offset;
  1274. const numPages = this._linkService.pagesCount;
  1275. offset.pageIdx = previous ? offset.pageIdx - 1 : offset.pageIdx + 1;
  1276. offset.matchIdx = null;
  1277. this._pagesToSearch--;
  1278. if (offset.pageIdx >= numPages || offset.pageIdx < 0) {
  1279. offset.pageIdx = previous ? numPages - 1 : 0;
  1280. offset.wrapped = true;
  1281. }
  1282. }
  1283. #updateMatch(found = false) {
  1284. let state = FindState.NOT_FOUND;
  1285. const wrapped = this._offset.wrapped;
  1286. this._offset.wrapped = false;
  1287. if (found) {
  1288. const previousPage = this._selected.pageIdx;
  1289. this._selected.pageIdx = this._offset.pageIdx;
  1290. this._selected.matchIdx = this._offset.matchIdx;
  1291. state = wrapped ? FindState.WRAPPED : FindState.FOUND;
  1292. if (previousPage !== -1 && previousPage !== this._selected.pageIdx) {
  1293. this.#updatePage(previousPage);
  1294. }
  1295. }
  1296. this.#updateUIState(state, this.#state.findPrevious);
  1297. if (this._selected.pageIdx !== -1) {
  1298. this._scrollMatches = true;
  1299. this.#updatePage(this._selected.pageIdx);
  1300. }
  1301. }
  1302. #onFindBarClose(evt) {
  1303. const pdfDocument = this._pdfDocument;
  1304. this._firstPageCapability.promise.then(() => {
  1305. if (!this._pdfDocument || pdfDocument && this._pdfDocument !== pdfDocument) {
  1306. return;
  1307. }
  1308. if (this._findTimeout) {
  1309. clearTimeout(this._findTimeout);
  1310. this._findTimeout = null;
  1311. }
  1312. if (this._resumePageIdx) {
  1313. this._resumePageIdx = null;
  1314. this._dirtyMatch = true;
  1315. }
  1316. this.#updateUIState(FindState.FOUND);
  1317. this._highlightMatches = false;
  1318. this.#updateAllPages();
  1319. });
  1320. }
  1321. #requestMatchesCount() {
  1322. const {
  1323. pageIdx,
  1324. matchIdx
  1325. } = this._selected;
  1326. let current = 0,
  1327. total = this._matchesCountTotal;
  1328. if (matchIdx !== -1) {
  1329. for (let i = 0; i < pageIdx; i++) {
  1330. current += this._pageMatches[i]?.length || 0;
  1331. }
  1332. current += matchIdx + 1;
  1333. }
  1334. if (current < 1 || current > total) {
  1335. current = total = 0;
  1336. }
  1337. return {
  1338. current,
  1339. total
  1340. };
  1341. }
  1342. #updateUIResultsCount() {
  1343. this._eventBus.dispatch("updatefindmatchescount", {
  1344. source: this,
  1345. matchesCount: this.#requestMatchesCount()
  1346. });
  1347. }
  1348. #updateUIState(state, previous = false) {
  1349. if (!this.#updateMatchesCountOnProgress && (this.#visitedPagesCount !== this._linkService.pagesCount || state === FindState.PENDING)) {
  1350. return;
  1351. }
  1352. this._eventBus.dispatch("updatefindcontrolstate", {
  1353. source: this,
  1354. state,
  1355. previous,
  1356. entireWord: this.#state?.entireWord ?? null,
  1357. matchesCount: this.#requestMatchesCount(),
  1358. rawQuery: this.#state?.query ?? null
  1359. });
  1360. }
  1361. }
  1362. ;// ./web/pdf_link_service.js
  1363. const DEFAULT_LINK_REL = "noopener noreferrer nofollow";
  1364. const LinkTarget = {
  1365. NONE: 0,
  1366. SELF: 1,
  1367. BLANK: 2,
  1368. PARENT: 3,
  1369. TOP: 4
  1370. };
  1371. class PDFLinkService {
  1372. externalLinkEnabled = true;
  1373. constructor({
  1374. eventBus,
  1375. externalLinkTarget = null,
  1376. externalLinkRel = null,
  1377. ignoreDestinationZoom = false
  1378. } = {}) {
  1379. this.eventBus = eventBus;
  1380. this.externalLinkTarget = externalLinkTarget;
  1381. this.externalLinkRel = externalLinkRel;
  1382. this._ignoreDestinationZoom = ignoreDestinationZoom;
  1383. this.baseUrl = null;
  1384. this.pdfDocument = null;
  1385. this.pdfViewer = null;
  1386. this.pdfHistory = null;
  1387. }
  1388. setDocument(pdfDocument, baseUrl = null) {
  1389. this.baseUrl = baseUrl;
  1390. this.pdfDocument = pdfDocument;
  1391. }
  1392. setViewer(pdfViewer) {
  1393. this.pdfViewer = pdfViewer;
  1394. }
  1395. setHistory(pdfHistory) {
  1396. this.pdfHistory = pdfHistory;
  1397. }
  1398. get pagesCount() {
  1399. return this.pdfDocument ? this.pdfDocument.numPages : 0;
  1400. }
  1401. get page() {
  1402. return this.pdfDocument ? this.pdfViewer.currentPageNumber : 1;
  1403. }
  1404. set page(value) {
  1405. if (this.pdfDocument) {
  1406. this.pdfViewer.currentPageNumber = value;
  1407. }
  1408. }
  1409. get rotation() {
  1410. return this.pdfDocument ? this.pdfViewer.pagesRotation : 0;
  1411. }
  1412. set rotation(value) {
  1413. if (this.pdfDocument) {
  1414. this.pdfViewer.pagesRotation = value;
  1415. }
  1416. }
  1417. get isInPresentationMode() {
  1418. return this.pdfDocument ? this.pdfViewer.isInPresentationMode : false;
  1419. }
  1420. async goToDestination(dest) {
  1421. if (!this.pdfDocument) {
  1422. return;
  1423. }
  1424. let namedDest, explicitDest, pageNumber;
  1425. if (typeof dest === "string") {
  1426. namedDest = dest;
  1427. explicitDest = await this.pdfDocument.getDestination(dest);
  1428. } else {
  1429. namedDest = null;
  1430. explicitDest = await dest;
  1431. }
  1432. if (!Array.isArray(explicitDest)) {
  1433. console.error(`goToDestination: "${explicitDest}" is not a valid destination array, for dest="${dest}".`);
  1434. return;
  1435. }
  1436. const [destRef] = explicitDest;
  1437. if (destRef && typeof destRef === "object") {
  1438. pageNumber = this.pdfDocument.cachedPageNumber(destRef);
  1439. if (!pageNumber) {
  1440. try {
  1441. pageNumber = (await this.pdfDocument.getPageIndex(destRef)) + 1;
  1442. } catch {
  1443. console.error(`goToDestination: "${destRef}" is not a valid page reference, for dest="${dest}".`);
  1444. return;
  1445. }
  1446. }
  1447. } else if (Number.isInteger(destRef)) {
  1448. pageNumber = destRef + 1;
  1449. }
  1450. if (!pageNumber || pageNumber < 1 || pageNumber > this.pagesCount) {
  1451. console.error(`goToDestination: "${pageNumber}" is not a valid page number, for dest="${dest}".`);
  1452. return;
  1453. }
  1454. if (this.pdfHistory) {
  1455. this.pdfHistory.pushCurrentPosition();
  1456. this.pdfHistory.push({
  1457. namedDest,
  1458. explicitDest,
  1459. pageNumber
  1460. });
  1461. }
  1462. this.pdfViewer.scrollPageIntoView({
  1463. pageNumber,
  1464. destArray: explicitDest,
  1465. ignoreDestinationZoom: this._ignoreDestinationZoom
  1466. });
  1467. }
  1468. goToPage(val) {
  1469. if (!this.pdfDocument) {
  1470. return;
  1471. }
  1472. const pageNumber = typeof val === "string" && this.pdfViewer.pageLabelToPageNumber(val) || val | 0;
  1473. if (!(Number.isInteger(pageNumber) && pageNumber > 0 && pageNumber <= this.pagesCount)) {
  1474. console.error(`PDFLinkService.goToPage: "${val}" is not a valid page.`);
  1475. return;
  1476. }
  1477. if (this.pdfHistory) {
  1478. this.pdfHistory.pushCurrentPosition();
  1479. this.pdfHistory.pushPage(pageNumber);
  1480. }
  1481. this.pdfViewer.scrollPageIntoView({
  1482. pageNumber
  1483. });
  1484. }
  1485. addLinkAttributes(link, url, newWindow = false) {
  1486. if (!url || typeof url !== "string") {
  1487. throw new Error('A valid "url" parameter must provided.');
  1488. }
  1489. const target = newWindow ? LinkTarget.BLANK : this.externalLinkTarget,
  1490. rel = this.externalLinkRel;
  1491. if (this.externalLinkEnabled) {
  1492. link.href = link.title = url;
  1493. } else {
  1494. link.href = "";
  1495. link.title = `Disabled: ${url}`;
  1496. link.onclick = () => false;
  1497. }
  1498. let targetStr = "";
  1499. switch (target) {
  1500. case LinkTarget.NONE:
  1501. break;
  1502. case LinkTarget.SELF:
  1503. targetStr = "_self";
  1504. break;
  1505. case LinkTarget.BLANK:
  1506. targetStr = "_blank";
  1507. break;
  1508. case LinkTarget.PARENT:
  1509. targetStr = "_parent";
  1510. break;
  1511. case LinkTarget.TOP:
  1512. targetStr = "_top";
  1513. break;
  1514. }
  1515. link.target = targetStr;
  1516. link.rel = typeof rel === "string" ? rel : DEFAULT_LINK_REL;
  1517. }
  1518. getDestinationHash(dest) {
  1519. if (typeof dest === "string") {
  1520. if (dest.length > 0) {
  1521. return this.getAnchorUrl("#" + escape(dest));
  1522. }
  1523. } else if (Array.isArray(dest)) {
  1524. const str = JSON.stringify(dest);
  1525. if (str.length > 0) {
  1526. return this.getAnchorUrl("#" + escape(str));
  1527. }
  1528. }
  1529. return this.getAnchorUrl("");
  1530. }
  1531. getAnchorUrl(anchor) {
  1532. return this.baseUrl ? this.baseUrl + anchor : anchor;
  1533. }
  1534. setHash(hash) {
  1535. if (!this.pdfDocument) {
  1536. return;
  1537. }
  1538. let pageNumber, dest;
  1539. if (hash.includes("=")) {
  1540. const params = parseQueryString(hash);
  1541. if (params.has("search")) {
  1542. const query = params.get("search").replaceAll('"', ""),
  1543. phrase = params.get("phrase") === "true";
  1544. this.eventBus.dispatch("findfromurlhash", {
  1545. source: this,
  1546. query: phrase ? query : query.match(/\S+/g)
  1547. });
  1548. }
  1549. if (params.has("page")) {
  1550. pageNumber = params.get("page") | 0 || 1;
  1551. }
  1552. if (params.has("zoom")) {
  1553. const zoomArgs = params.get("zoom").split(",");
  1554. const zoomArg = zoomArgs[0];
  1555. const zoomArgNumber = parseFloat(zoomArg);
  1556. if (!zoomArg.includes("Fit")) {
  1557. dest = [null, {
  1558. name: "XYZ"
  1559. }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null, zoomArgs.length > 2 ? zoomArgs[2] | 0 : null, zoomArgNumber ? zoomArgNumber / 100 : zoomArg];
  1560. } else if (zoomArg === "Fit" || zoomArg === "FitB") {
  1561. dest = [null, {
  1562. name: zoomArg
  1563. }];
  1564. } else if (zoomArg === "FitH" || zoomArg === "FitBH" || zoomArg === "FitV" || zoomArg === "FitBV") {
  1565. dest = [null, {
  1566. name: zoomArg
  1567. }, zoomArgs.length > 1 ? zoomArgs[1] | 0 : null];
  1568. } else if (zoomArg === "FitR") {
  1569. if (zoomArgs.length !== 5) {
  1570. console.error('PDFLinkService.setHash: Not enough parameters for "FitR".');
  1571. } else {
  1572. dest = [null, {
  1573. name: zoomArg
  1574. }, zoomArgs[1] | 0, zoomArgs[2] | 0, zoomArgs[3] | 0, zoomArgs[4] | 0];
  1575. }
  1576. } else {
  1577. console.error(`PDFLinkService.setHash: "${zoomArg}" is not a valid zoom value.`);
  1578. }
  1579. }
  1580. if (dest) {
  1581. this.pdfViewer.scrollPageIntoView({
  1582. pageNumber: pageNumber || this.page,
  1583. destArray: dest,
  1584. allowNegativeOffset: true
  1585. });
  1586. } else if (pageNumber) {
  1587. this.page = pageNumber;
  1588. }
  1589. if (params.has("pagemode")) {
  1590. this.eventBus.dispatch("pagemode", {
  1591. source: this,
  1592. mode: params.get("pagemode")
  1593. });
  1594. }
  1595. if (params.has("nameddest")) {
  1596. this.goToDestination(params.get("nameddest"));
  1597. }
  1598. return;
  1599. }
  1600. dest = unescape(hash);
  1601. try {
  1602. dest = JSON.parse(dest);
  1603. if (!Array.isArray(dest)) {
  1604. dest = dest.toString();
  1605. }
  1606. } catch {}
  1607. if (typeof dest === "string" || PDFLinkService.#isValidExplicitDest(dest)) {
  1608. this.goToDestination(dest);
  1609. return;
  1610. }
  1611. console.error(`PDFLinkService.setHash: "${unescape(hash)}" is not a valid destination.`);
  1612. }
  1613. executeNamedAction(action) {
  1614. if (!this.pdfDocument) {
  1615. return;
  1616. }
  1617. switch (action) {
  1618. case "GoBack":
  1619. this.pdfHistory?.back();
  1620. break;
  1621. case "GoForward":
  1622. this.pdfHistory?.forward();
  1623. break;
  1624. case "NextPage":
  1625. this.pdfViewer.nextPage();
  1626. break;
  1627. case "PrevPage":
  1628. this.pdfViewer.previousPage();
  1629. break;
  1630. case "LastPage":
  1631. this.page = this.pagesCount;
  1632. break;
  1633. case "FirstPage":
  1634. this.page = 1;
  1635. break;
  1636. default:
  1637. break;
  1638. }
  1639. this.eventBus.dispatch("namedaction", {
  1640. source: this,
  1641. action
  1642. });
  1643. }
  1644. async executeSetOCGState(action) {
  1645. if (!this.pdfDocument) {
  1646. return;
  1647. }
  1648. const pdfDocument = this.pdfDocument,
  1649. optionalContentConfig = await this.pdfViewer.optionalContentConfigPromise;
  1650. if (pdfDocument !== this.pdfDocument) {
  1651. return;
  1652. }
  1653. optionalContentConfig.setOCGState(action);
  1654. this.pdfViewer.optionalContentConfigPromise = Promise.resolve(optionalContentConfig);
  1655. }
  1656. static #isValidExplicitDest(dest) {
  1657. if (!Array.isArray(dest) || dest.length < 2) {
  1658. return false;
  1659. }
  1660. const [page, zoom, ...args] = dest;
  1661. if (!(typeof page === "object" && Number.isInteger(page?.num) && Number.isInteger(page?.gen)) && !Number.isInteger(page)) {
  1662. return false;
  1663. }
  1664. if (!(typeof zoom === "object" && typeof zoom?.name === "string")) {
  1665. return false;
  1666. }
  1667. const argsLen = args.length;
  1668. let allowNull = true;
  1669. switch (zoom.name) {
  1670. case "XYZ":
  1671. if (argsLen < 2 || argsLen > 3) {
  1672. return false;
  1673. }
  1674. break;
  1675. case "Fit":
  1676. case "FitB":
  1677. return argsLen === 0;
  1678. case "FitH":
  1679. case "FitBH":
  1680. case "FitV":
  1681. case "FitBV":
  1682. if (argsLen > 1) {
  1683. return false;
  1684. }
  1685. break;
  1686. case "FitR":
  1687. if (argsLen !== 4) {
  1688. return false;
  1689. }
  1690. allowNull = false;
  1691. break;
  1692. default:
  1693. return false;
  1694. }
  1695. for (const arg of args) {
  1696. if (!(typeof arg === "number" || allowNull && arg === null)) {
  1697. return false;
  1698. }
  1699. }
  1700. return true;
  1701. }
  1702. }
  1703. class SimpleLinkService extends PDFLinkService {
  1704. setDocument(pdfDocument, baseUrl = null) {}
  1705. }
  1706. ;// ./web/pdfjs.js
  1707. const {
  1708. AbortException,
  1709. AnnotationEditorLayer,
  1710. AnnotationEditorParamsType,
  1711. AnnotationEditorType,
  1712. AnnotationEditorUIManager,
  1713. AnnotationLayer,
  1714. AnnotationMode,
  1715. build,
  1716. ColorPicker,
  1717. createValidAbsoluteUrl,
  1718. DOMSVGFactory,
  1719. DrawLayer,
  1720. FeatureTest,
  1721. fetchData,
  1722. getDocument,
  1723. getFilenameFromUrl,
  1724. getPdfFilenameFromUrl,
  1725. getXfaPageViewport,
  1726. GlobalWorkerOptions,
  1727. ImageKind,
  1728. InvalidPDFException,
  1729. isDataScheme,
  1730. isPdfFile,
  1731. MissingPDFException,
  1732. noContextMenu,
  1733. normalizeUnicode,
  1734. OPS,
  1735. OutputScale,
  1736. PasswordResponses,
  1737. PDFDataRangeTransport,
  1738. PDFDateString,
  1739. PDFWorker,
  1740. PermissionFlag,
  1741. PixelsPerInch,
  1742. RenderingCancelledException,
  1743. setLayerDimensions,
  1744. shadow,
  1745. stopEvent,
  1746. TextLayer,
  1747. TouchManager,
  1748. UnexpectedResponseException,
  1749. Util,
  1750. VerbosityLevel,
  1751. version,
  1752. XfaLayer
  1753. } = globalThis.pdfjsLib;
  1754. ;// ./web/annotation_layer_builder.js
  1755. class AnnotationLayerBuilder {
  1756. #onAppend = null;
  1757. #eventAbortController = null;
  1758. constructor({
  1759. pdfPage,
  1760. linkService,
  1761. downloadManager,
  1762. annotationStorage = null,
  1763. imageResourcesPath = "",
  1764. renderForms = true,
  1765. enableScripting = false,
  1766. hasJSActionsPromise = null,
  1767. fieldObjectsPromise = null,
  1768. annotationCanvasMap = null,
  1769. accessibilityManager = null,
  1770. annotationEditorUIManager = null,
  1771. onAppend = null
  1772. }) {
  1773. this.pdfPage = pdfPage;
  1774. this.linkService = linkService;
  1775. this.downloadManager = downloadManager;
  1776. this.imageResourcesPath = imageResourcesPath;
  1777. this.renderForms = renderForms;
  1778. this.annotationStorage = annotationStorage;
  1779. this.enableScripting = enableScripting;
  1780. this._hasJSActionsPromise = hasJSActionsPromise || Promise.resolve(false);
  1781. this._fieldObjectsPromise = fieldObjectsPromise || Promise.resolve(null);
  1782. this._annotationCanvasMap = annotationCanvasMap;
  1783. this._accessibilityManager = accessibilityManager;
  1784. this._annotationEditorUIManager = annotationEditorUIManager;
  1785. this.#onAppend = onAppend;
  1786. this.annotationLayer = null;
  1787. this.div = null;
  1788. this._cancelled = false;
  1789. this._eventBus = linkService.eventBus;
  1790. }
  1791. async render(viewport, options, intent = "display") {
  1792. if (this.div) {
  1793. if (this._cancelled || !this.annotationLayer) {
  1794. return;
  1795. }
  1796. this.annotationLayer.update({
  1797. viewport: viewport.clone({
  1798. dontFlip: true
  1799. })
  1800. });
  1801. return;
  1802. }
  1803. const [annotations, hasJSActions, fieldObjects] = await Promise.all([this.pdfPage.getAnnotations({
  1804. intent
  1805. }), this._hasJSActionsPromise, this._fieldObjectsPromise]);
  1806. if (this._cancelled) {
  1807. return;
  1808. }
  1809. const div = this.div = document.createElement("div");
  1810. div.className = "annotationLayer";
  1811. this.#onAppend?.(div);
  1812. if (annotations.length === 0) {
  1813. this.hide();
  1814. return;
  1815. }
  1816. this.annotationLayer = new AnnotationLayer({
  1817. div,
  1818. accessibilityManager: this._accessibilityManager,
  1819. annotationCanvasMap: this._annotationCanvasMap,
  1820. annotationEditorUIManager: this._annotationEditorUIManager,
  1821. page: this.pdfPage,
  1822. viewport: viewport.clone({
  1823. dontFlip: true
  1824. }),
  1825. structTreeLayer: options?.structTreeLayer || null
  1826. });
  1827. await this.annotationLayer.render({
  1828. annotations,
  1829. imageResourcesPath: this.imageResourcesPath,
  1830. renderForms: this.renderForms,
  1831. linkService: this.linkService,
  1832. downloadManager: this.downloadManager,
  1833. annotationStorage: this.annotationStorage,
  1834. enableScripting: this.enableScripting,
  1835. hasJSActions,
  1836. fieldObjects
  1837. });
  1838. if (this.linkService.isInPresentationMode) {
  1839. this.#updatePresentationModeState(PresentationModeState.FULLSCREEN);
  1840. }
  1841. if (!this.#eventAbortController) {
  1842. this.#eventAbortController = new AbortController();
  1843. this._eventBus?._on("presentationmodechanged", evt => {
  1844. this.#updatePresentationModeState(evt.state);
  1845. }, {
  1846. signal: this.#eventAbortController.signal
  1847. });
  1848. }
  1849. }
  1850. cancel() {
  1851. this._cancelled = true;
  1852. this.#eventAbortController?.abort();
  1853. this.#eventAbortController = null;
  1854. }
  1855. hide() {
  1856. if (!this.div) {
  1857. return;
  1858. }
  1859. this.div.hidden = true;
  1860. }
  1861. hasEditableAnnotations() {
  1862. return !!this.annotationLayer?.hasEditableAnnotations();
  1863. }
  1864. #updatePresentationModeState(state) {
  1865. if (!this.div) {
  1866. return;
  1867. }
  1868. let disableFormElements = false;
  1869. switch (state) {
  1870. case PresentationModeState.FULLSCREEN:
  1871. disableFormElements = true;
  1872. break;
  1873. case PresentationModeState.NORMAL:
  1874. break;
  1875. default:
  1876. return;
  1877. }
  1878. for (const section of this.div.childNodes) {
  1879. if (section.hasAttribute("data-internal-link")) {
  1880. continue;
  1881. }
  1882. section.inert = disableFormElements;
  1883. }
  1884. }
  1885. }
  1886. ;// ./web/download_manager.js
  1887. function download(blobUrl, filename) {
  1888. const a = document.createElement("a");
  1889. if (!a.click) {
  1890. throw new Error('DownloadManager: "a.click()" is not supported.');
  1891. }
  1892. a.href = blobUrl;
  1893. a.target = "_parent";
  1894. if ("download" in a) {
  1895. a.download = filename;
  1896. }
  1897. (document.body || document.documentElement).append(a);
  1898. a.click();
  1899. a.remove();
  1900. }
  1901. class DownloadManager {
  1902. #openBlobUrls = new WeakMap();
  1903. downloadData(data, filename, contentType) {
  1904. const blobUrl = URL.createObjectURL(new Blob([data], {
  1905. type: contentType
  1906. }));
  1907. download(blobUrl, filename);
  1908. }
  1909. openOrDownloadData(data, filename, dest = null) {
  1910. const isPdfData = isPdfFile(filename);
  1911. const contentType = isPdfData ? "application/pdf" : "";
  1912. this.downloadData(data, filename, contentType);
  1913. return false;
  1914. }
  1915. download(data, url, filename) {
  1916. let blobUrl;
  1917. if (data) {
  1918. blobUrl = URL.createObjectURL(new Blob([data], {
  1919. type: "application/pdf"
  1920. }));
  1921. } else {
  1922. if (!createValidAbsoluteUrl(url, "http://example.com")) {
  1923. console.error(`download - not a valid URL: ${url}`);
  1924. return;
  1925. }
  1926. blobUrl = url + "#pdfjs.action=download";
  1927. }
  1928. download(blobUrl, filename);
  1929. }
  1930. }
  1931. ;// ./web/event_utils.js
  1932. const WaitOnType = {
  1933. EVENT: "event",
  1934. TIMEOUT: "timeout"
  1935. };
  1936. async function waitOnEventOrTimeout({
  1937. target,
  1938. name,
  1939. delay = 0
  1940. }) {
  1941. if (typeof target !== "object" || !(name && typeof name === "string") || !(Number.isInteger(delay) && delay >= 0)) {
  1942. throw new Error("waitOnEventOrTimeout - invalid parameters.");
  1943. }
  1944. const {
  1945. promise,
  1946. resolve
  1947. } = Promise.withResolvers();
  1948. const ac = new AbortController();
  1949. function handler(type) {
  1950. ac.abort();
  1951. clearTimeout(timeout);
  1952. resolve(type);
  1953. }
  1954. const evtMethod = target instanceof EventBus ? "_on" : "addEventListener";
  1955. target[evtMethod](name, handler.bind(null, WaitOnType.EVENT), {
  1956. signal: ac.signal
  1957. });
  1958. const timeout = setTimeout(handler.bind(null, WaitOnType.TIMEOUT), delay);
  1959. return promise;
  1960. }
  1961. class EventBus {
  1962. #listeners = Object.create(null);
  1963. on(eventName, listener, options = null) {
  1964. this._on(eventName, listener, {
  1965. external: true,
  1966. once: options?.once,
  1967. signal: options?.signal
  1968. });
  1969. }
  1970. off(eventName, listener, options = null) {
  1971. this._off(eventName, listener);
  1972. }
  1973. dispatch(eventName, data) {
  1974. const eventListeners = this.#listeners[eventName];
  1975. if (!eventListeners || eventListeners.length === 0) {
  1976. return;
  1977. }
  1978. let externalListeners;
  1979. for (const {
  1980. listener,
  1981. external,
  1982. once
  1983. } of eventListeners.slice(0)) {
  1984. if (once) {
  1985. this._off(eventName, listener);
  1986. }
  1987. if (external) {
  1988. (externalListeners ||= []).push(listener);
  1989. continue;
  1990. }
  1991. listener(data);
  1992. }
  1993. if (externalListeners) {
  1994. for (const listener of externalListeners) {
  1995. listener(data);
  1996. }
  1997. externalListeners = null;
  1998. }
  1999. }
  2000. _on(eventName, listener, options = null) {
  2001. let rmAbort = null;
  2002. if (options?.signal instanceof AbortSignal) {
  2003. const {
  2004. signal
  2005. } = options;
  2006. if (signal.aborted) {
  2007. console.error("Cannot use an `aborted` signal.");
  2008. return;
  2009. }
  2010. const onAbort = () => this._off(eventName, listener);
  2011. rmAbort = () => signal.removeEventListener("abort", onAbort);
  2012. signal.addEventListener("abort", onAbort);
  2013. }
  2014. const eventListeners = this.#listeners[eventName] ||= [];
  2015. eventListeners.push({
  2016. listener,
  2017. external: options?.external === true,
  2018. once: options?.once === true,
  2019. rmAbort
  2020. });
  2021. }
  2022. _off(eventName, listener, options = null) {
  2023. const eventListeners = this.#listeners[eventName];
  2024. if (!eventListeners) {
  2025. return;
  2026. }
  2027. for (let i = 0, ii = eventListeners.length; i < ii; i++) {
  2028. const evt = eventListeners[i];
  2029. if (evt.listener === listener) {
  2030. evt.rmAbort?.();
  2031. eventListeners.splice(i, 1);
  2032. return;
  2033. }
  2034. }
  2035. }
  2036. }
  2037. class FirefoxEventBus extends EventBus {
  2038. #externalServices;
  2039. #globalEventNames;
  2040. #isInAutomation;
  2041. constructor(globalEventNames, externalServices, isInAutomation) {
  2042. super();
  2043. this.#globalEventNames = globalEventNames;
  2044. this.#externalServices = externalServices;
  2045. this.#isInAutomation = isInAutomation;
  2046. }
  2047. dispatch(eventName, data) {
  2048. throw new Error("Not implemented: FirefoxEventBus.dispatch");
  2049. }
  2050. }
  2051. ;// ./node_modules/@fluent/bundle/esm/types.js
  2052. class FluentType {
  2053. constructor(value) {
  2054. this.value = value;
  2055. }
  2056. valueOf() {
  2057. return this.value;
  2058. }
  2059. }
  2060. class FluentNone extends FluentType {
  2061. constructor(value = "???") {
  2062. super(value);
  2063. }
  2064. toString(scope) {
  2065. return `{${this.value}}`;
  2066. }
  2067. }
  2068. class FluentNumber extends FluentType {
  2069. constructor(value, opts = {}) {
  2070. super(value);
  2071. this.opts = opts;
  2072. }
  2073. toString(scope) {
  2074. try {
  2075. const nf = scope.memoizeIntlObject(Intl.NumberFormat, this.opts);
  2076. return nf.format(this.value);
  2077. } catch (err) {
  2078. scope.reportError(err);
  2079. return this.value.toString(10);
  2080. }
  2081. }
  2082. }
  2083. class FluentDateTime extends FluentType {
  2084. constructor(value, opts = {}) {
  2085. super(value);
  2086. this.opts = opts;
  2087. }
  2088. toString(scope) {
  2089. try {
  2090. const dtf = scope.memoizeIntlObject(Intl.DateTimeFormat, this.opts);
  2091. return dtf.format(this.value);
  2092. } catch (err) {
  2093. scope.reportError(err);
  2094. return new Date(this.value).toISOString();
  2095. }
  2096. }
  2097. }
  2098. ;// ./node_modules/@fluent/bundle/esm/resolver.js
  2099. const MAX_PLACEABLES = 100;
  2100. const FSI = "\u2068";
  2101. const PDI = "\u2069";
  2102. function match(scope, selector, key) {
  2103. if (key === selector) {
  2104. return true;
  2105. }
  2106. if (key instanceof FluentNumber && selector instanceof FluentNumber && key.value === selector.value) {
  2107. return true;
  2108. }
  2109. if (selector instanceof FluentNumber && typeof key === "string") {
  2110. let category = scope.memoizeIntlObject(Intl.PluralRules, selector.opts).select(selector.value);
  2111. if (key === category) {
  2112. return true;
  2113. }
  2114. }
  2115. return false;
  2116. }
  2117. function getDefault(scope, variants, star) {
  2118. if (variants[star]) {
  2119. return resolvePattern(scope, variants[star].value);
  2120. }
  2121. scope.reportError(new RangeError("No default"));
  2122. return new FluentNone();
  2123. }
  2124. function getArguments(scope, args) {
  2125. const positional = [];
  2126. const named = Object.create(null);
  2127. for (const arg of args) {
  2128. if (arg.type === "narg") {
  2129. named[arg.name] = resolveExpression(scope, arg.value);
  2130. } else {
  2131. positional.push(resolveExpression(scope, arg));
  2132. }
  2133. }
  2134. return {
  2135. positional,
  2136. named
  2137. };
  2138. }
  2139. function resolveExpression(scope, expr) {
  2140. switch (expr.type) {
  2141. case "str":
  2142. return expr.value;
  2143. case "num":
  2144. return new FluentNumber(expr.value, {
  2145. minimumFractionDigits: expr.precision
  2146. });
  2147. case "var":
  2148. return resolveVariableReference(scope, expr);
  2149. case "mesg":
  2150. return resolveMessageReference(scope, expr);
  2151. case "term":
  2152. return resolveTermReference(scope, expr);
  2153. case "func":
  2154. return resolveFunctionReference(scope, expr);
  2155. case "select":
  2156. return resolveSelectExpression(scope, expr);
  2157. default:
  2158. return new FluentNone();
  2159. }
  2160. }
  2161. function resolveVariableReference(scope, {
  2162. name
  2163. }) {
  2164. let arg;
  2165. if (scope.params) {
  2166. if (Object.prototype.hasOwnProperty.call(scope.params, name)) {
  2167. arg = scope.params[name];
  2168. } else {
  2169. return new FluentNone(`$${name}`);
  2170. }
  2171. } else if (scope.args && Object.prototype.hasOwnProperty.call(scope.args, name)) {
  2172. arg = scope.args[name];
  2173. } else {
  2174. scope.reportError(new ReferenceError(`Unknown variable: $${name}`));
  2175. return new FluentNone(`$${name}`);
  2176. }
  2177. if (arg instanceof FluentType) {
  2178. return arg;
  2179. }
  2180. switch (typeof arg) {
  2181. case "string":
  2182. return arg;
  2183. case "number":
  2184. return new FluentNumber(arg);
  2185. case "object":
  2186. if (arg instanceof Date) {
  2187. return new FluentDateTime(arg.getTime());
  2188. }
  2189. default:
  2190. scope.reportError(new TypeError(`Variable type not supported: $${name}, ${typeof arg}`));
  2191. return new FluentNone(`$${name}`);
  2192. }
  2193. }
  2194. function resolveMessageReference(scope, {
  2195. name,
  2196. attr
  2197. }) {
  2198. const message = scope.bundle._messages.get(name);
  2199. if (!message) {
  2200. scope.reportError(new ReferenceError(`Unknown message: ${name}`));
  2201. return new FluentNone(name);
  2202. }
  2203. if (attr) {
  2204. const attribute = message.attributes[attr];
  2205. if (attribute) {
  2206. return resolvePattern(scope, attribute);
  2207. }
  2208. scope.reportError(new ReferenceError(`Unknown attribute: ${attr}`));
  2209. return new FluentNone(`${name}.${attr}`);
  2210. }
  2211. if (message.value) {
  2212. return resolvePattern(scope, message.value);
  2213. }
  2214. scope.reportError(new ReferenceError(`No value: ${name}`));
  2215. return new FluentNone(name);
  2216. }
  2217. function resolveTermReference(scope, {
  2218. name,
  2219. attr,
  2220. args
  2221. }) {
  2222. const id = `-${name}`;
  2223. const term = scope.bundle._terms.get(id);
  2224. if (!term) {
  2225. scope.reportError(new ReferenceError(`Unknown term: ${id}`));
  2226. return new FluentNone(id);
  2227. }
  2228. if (attr) {
  2229. const attribute = term.attributes[attr];
  2230. if (attribute) {
  2231. scope.params = getArguments(scope, args).named;
  2232. const resolved = resolvePattern(scope, attribute);
  2233. scope.params = null;
  2234. return resolved;
  2235. }
  2236. scope.reportError(new ReferenceError(`Unknown attribute: ${attr}`));
  2237. return new FluentNone(`${id}.${attr}`);
  2238. }
  2239. scope.params = getArguments(scope, args).named;
  2240. const resolved = resolvePattern(scope, term.value);
  2241. scope.params = null;
  2242. return resolved;
  2243. }
  2244. function resolveFunctionReference(scope, {
  2245. name,
  2246. args
  2247. }) {
  2248. let func = scope.bundle._functions[name];
  2249. if (!func) {
  2250. scope.reportError(new ReferenceError(`Unknown function: ${name}()`));
  2251. return new FluentNone(`${name}()`);
  2252. }
  2253. if (typeof func !== "function") {
  2254. scope.reportError(new TypeError(`Function ${name}() is not callable`));
  2255. return new FluentNone(`${name}()`);
  2256. }
  2257. try {
  2258. let resolved = getArguments(scope, args);
  2259. return func(resolved.positional, resolved.named);
  2260. } catch (err) {
  2261. scope.reportError(err);
  2262. return new FluentNone(`${name}()`);
  2263. }
  2264. }
  2265. function resolveSelectExpression(scope, {
  2266. selector,
  2267. variants,
  2268. star
  2269. }) {
  2270. let sel = resolveExpression(scope, selector);
  2271. if (sel instanceof FluentNone) {
  2272. return getDefault(scope, variants, star);
  2273. }
  2274. for (const variant of variants) {
  2275. const key = resolveExpression(scope, variant.key);
  2276. if (match(scope, sel, key)) {
  2277. return resolvePattern(scope, variant.value);
  2278. }
  2279. }
  2280. return getDefault(scope, variants, star);
  2281. }
  2282. function resolveComplexPattern(scope, ptn) {
  2283. if (scope.dirty.has(ptn)) {
  2284. scope.reportError(new RangeError("Cyclic reference"));
  2285. return new FluentNone();
  2286. }
  2287. scope.dirty.add(ptn);
  2288. const result = [];
  2289. const useIsolating = scope.bundle._useIsolating && ptn.length > 1;
  2290. for (const elem of ptn) {
  2291. if (typeof elem === "string") {
  2292. result.push(scope.bundle._transform(elem));
  2293. continue;
  2294. }
  2295. scope.placeables++;
  2296. if (scope.placeables > MAX_PLACEABLES) {
  2297. scope.dirty.delete(ptn);
  2298. throw new RangeError(`Too many placeables expanded: ${scope.placeables}, ` + `max allowed is ${MAX_PLACEABLES}`);
  2299. }
  2300. if (useIsolating) {
  2301. result.push(FSI);
  2302. }
  2303. result.push(resolveExpression(scope, elem).toString(scope));
  2304. if (useIsolating) {
  2305. result.push(PDI);
  2306. }
  2307. }
  2308. scope.dirty.delete(ptn);
  2309. return result.join("");
  2310. }
  2311. function resolvePattern(scope, value) {
  2312. if (typeof value === "string") {
  2313. return scope.bundle._transform(value);
  2314. }
  2315. return resolveComplexPattern(scope, value);
  2316. }
  2317. ;// ./node_modules/@fluent/bundle/esm/scope.js
  2318. class Scope {
  2319. constructor(bundle, errors, args) {
  2320. this.dirty = new WeakSet();
  2321. this.params = null;
  2322. this.placeables = 0;
  2323. this.bundle = bundle;
  2324. this.errors = errors;
  2325. this.args = args;
  2326. }
  2327. reportError(error) {
  2328. if (!this.errors || !(error instanceof Error)) {
  2329. throw error;
  2330. }
  2331. this.errors.push(error);
  2332. }
  2333. memoizeIntlObject(ctor, opts) {
  2334. let cache = this.bundle._intls.get(ctor);
  2335. if (!cache) {
  2336. cache = {};
  2337. this.bundle._intls.set(ctor, cache);
  2338. }
  2339. let id = JSON.stringify(opts);
  2340. if (!cache[id]) {
  2341. cache[id] = new ctor(this.bundle.locales, opts);
  2342. }
  2343. return cache[id];
  2344. }
  2345. }
  2346. ;// ./node_modules/@fluent/bundle/esm/builtins.js
  2347. function values(opts, allowed) {
  2348. const unwrapped = Object.create(null);
  2349. for (const [name, opt] of Object.entries(opts)) {
  2350. if (allowed.includes(name)) {
  2351. unwrapped[name] = opt.valueOf();
  2352. }
  2353. }
  2354. return unwrapped;
  2355. }
  2356. const NUMBER_ALLOWED = ["unitDisplay", "currencyDisplay", "useGrouping", "minimumIntegerDigits", "minimumFractionDigits", "maximumFractionDigits", "minimumSignificantDigits", "maximumSignificantDigits"];
  2357. function NUMBER(args, opts) {
  2358. let arg = args[0];
  2359. if (arg instanceof FluentNone) {
  2360. return new FluentNone(`NUMBER(${arg.valueOf()})`);
  2361. }
  2362. if (arg instanceof FluentNumber) {
  2363. return new FluentNumber(arg.valueOf(), {
  2364. ...arg.opts,
  2365. ...values(opts, NUMBER_ALLOWED)
  2366. });
  2367. }
  2368. if (arg instanceof FluentDateTime) {
  2369. return new FluentNumber(arg.valueOf(), {
  2370. ...values(opts, NUMBER_ALLOWED)
  2371. });
  2372. }
  2373. throw new TypeError("Invalid argument to NUMBER");
  2374. }
  2375. const DATETIME_ALLOWED = ["dateStyle", "timeStyle", "fractionalSecondDigits", "dayPeriod", "hour12", "weekday", "era", "year", "month", "day", "hour", "minute", "second", "timeZoneName"];
  2376. function DATETIME(args, opts) {
  2377. let arg = args[0];
  2378. if (arg instanceof FluentNone) {
  2379. return new FluentNone(`DATETIME(${arg.valueOf()})`);
  2380. }
  2381. if (arg instanceof FluentDateTime) {
  2382. return new FluentDateTime(arg.valueOf(), {
  2383. ...arg.opts,
  2384. ...values(opts, DATETIME_ALLOWED)
  2385. });
  2386. }
  2387. if (arg instanceof FluentNumber) {
  2388. return new FluentDateTime(arg.valueOf(), {
  2389. ...values(opts, DATETIME_ALLOWED)
  2390. });
  2391. }
  2392. throw new TypeError("Invalid argument to DATETIME");
  2393. }
  2394. ;// ./node_modules/@fluent/bundle/esm/memoizer.js
  2395. const cache = new Map();
  2396. function getMemoizerForLocale(locales) {
  2397. const stringLocale = Array.isArray(locales) ? locales.join(" ") : locales;
  2398. let memoizer = cache.get(stringLocale);
  2399. if (memoizer === undefined) {
  2400. memoizer = new Map();
  2401. cache.set(stringLocale, memoizer);
  2402. }
  2403. return memoizer;
  2404. }
  2405. ;// ./node_modules/@fluent/bundle/esm/bundle.js
  2406. class FluentBundle {
  2407. constructor(locales, {
  2408. functions,
  2409. useIsolating = true,
  2410. transform = v => v
  2411. } = {}) {
  2412. this._terms = new Map();
  2413. this._messages = new Map();
  2414. this.locales = Array.isArray(locales) ? locales : [locales];
  2415. this._functions = {
  2416. NUMBER: NUMBER,
  2417. DATETIME: DATETIME,
  2418. ...functions
  2419. };
  2420. this._useIsolating = useIsolating;
  2421. this._transform = transform;
  2422. this._intls = getMemoizerForLocale(locales);
  2423. }
  2424. hasMessage(id) {
  2425. return this._messages.has(id);
  2426. }
  2427. getMessage(id) {
  2428. return this._messages.get(id);
  2429. }
  2430. addResource(res, {
  2431. allowOverrides = false
  2432. } = {}) {
  2433. const errors = [];
  2434. for (let i = 0; i < res.body.length; i++) {
  2435. let entry = res.body[i];
  2436. if (entry.id.startsWith("-")) {
  2437. if (allowOverrides === false && this._terms.has(entry.id)) {
  2438. errors.push(new Error(`Attempt to override an existing term: "${entry.id}"`));
  2439. continue;
  2440. }
  2441. this._terms.set(entry.id, entry);
  2442. } else {
  2443. if (allowOverrides === false && this._messages.has(entry.id)) {
  2444. errors.push(new Error(`Attempt to override an existing message: "${entry.id}"`));
  2445. continue;
  2446. }
  2447. this._messages.set(entry.id, entry);
  2448. }
  2449. }
  2450. return errors;
  2451. }
  2452. formatPattern(pattern, args = null, errors = null) {
  2453. if (typeof pattern === "string") {
  2454. return this._transform(pattern);
  2455. }
  2456. let scope = new Scope(this, errors, args);
  2457. try {
  2458. let value = resolveComplexPattern(scope, pattern);
  2459. return value.toString(scope);
  2460. } catch (err) {
  2461. if (scope.errors && err instanceof Error) {
  2462. scope.errors.push(err);
  2463. return new FluentNone().toString(scope);
  2464. }
  2465. throw err;
  2466. }
  2467. }
  2468. }
  2469. ;// ./node_modules/@fluent/bundle/esm/resource.js
  2470. const RE_MESSAGE_START = /^(-?[a-zA-Z][\w-]*) *= */gm;
  2471. const RE_ATTRIBUTE_START = /\.([a-zA-Z][\w-]*) *= */y;
  2472. const RE_VARIANT_START = /\*?\[/y;
  2473. const RE_NUMBER_LITERAL = /(-?[0-9]+(?:\.([0-9]+))?)/y;
  2474. const RE_IDENTIFIER = /([a-zA-Z][\w-]*)/y;
  2475. const RE_REFERENCE = /([$-])?([a-zA-Z][\w-]*)(?:\.([a-zA-Z][\w-]*))?/y;
  2476. const RE_FUNCTION_NAME = /^[A-Z][A-Z0-9_-]*$/;
  2477. const RE_TEXT_RUN = /([^{}\n\r]+)/y;
  2478. const RE_STRING_RUN = /([^\\"\n\r]*)/y;
  2479. const RE_STRING_ESCAPE = /\\([\\"])/y;
  2480. const RE_UNICODE_ESCAPE = /\\u([a-fA-F0-9]{4})|\\U([a-fA-F0-9]{6})/y;
  2481. const RE_LEADING_NEWLINES = /^\n+/;
  2482. const RE_TRAILING_SPACES = / +$/;
  2483. const RE_BLANK_LINES = / *\r?\n/g;
  2484. const RE_INDENT = /( *)$/;
  2485. const TOKEN_BRACE_OPEN = /{\s*/y;
  2486. const TOKEN_BRACE_CLOSE = /\s*}/y;
  2487. const TOKEN_BRACKET_OPEN = /\[\s*/y;
  2488. const TOKEN_BRACKET_CLOSE = /\s*] */y;
  2489. const TOKEN_PAREN_OPEN = /\s*\(\s*/y;
  2490. const TOKEN_ARROW = /\s*->\s*/y;
  2491. const TOKEN_COLON = /\s*:\s*/y;
  2492. const TOKEN_COMMA = /\s*,?\s*/y;
  2493. const TOKEN_BLANK = /\s+/y;
  2494. class FluentResource {
  2495. constructor(source) {
  2496. this.body = [];
  2497. RE_MESSAGE_START.lastIndex = 0;
  2498. let cursor = 0;
  2499. while (true) {
  2500. let next = RE_MESSAGE_START.exec(source);
  2501. if (next === null) {
  2502. break;
  2503. }
  2504. cursor = RE_MESSAGE_START.lastIndex;
  2505. try {
  2506. this.body.push(parseMessage(next[1]));
  2507. } catch (err) {
  2508. if (err instanceof SyntaxError) {
  2509. continue;
  2510. }
  2511. throw err;
  2512. }
  2513. }
  2514. function test(re) {
  2515. re.lastIndex = cursor;
  2516. return re.test(source);
  2517. }
  2518. function consumeChar(char, errorClass) {
  2519. if (source[cursor] === char) {
  2520. cursor++;
  2521. return true;
  2522. }
  2523. if (errorClass) {
  2524. throw new errorClass(`Expected ${char}`);
  2525. }
  2526. return false;
  2527. }
  2528. function consumeToken(re, errorClass) {
  2529. if (test(re)) {
  2530. cursor = re.lastIndex;
  2531. return true;
  2532. }
  2533. if (errorClass) {
  2534. throw new errorClass(`Expected ${re.toString()}`);
  2535. }
  2536. return false;
  2537. }
  2538. function match(re) {
  2539. re.lastIndex = cursor;
  2540. let result = re.exec(source);
  2541. if (result === null) {
  2542. throw new SyntaxError(`Expected ${re.toString()}`);
  2543. }
  2544. cursor = re.lastIndex;
  2545. return result;
  2546. }
  2547. function match1(re) {
  2548. return match(re)[1];
  2549. }
  2550. function parseMessage(id) {
  2551. let value = parsePattern();
  2552. let attributes = parseAttributes();
  2553. if (value === null && Object.keys(attributes).length === 0) {
  2554. throw new SyntaxError("Expected message value or attributes");
  2555. }
  2556. return {
  2557. id,
  2558. value,
  2559. attributes
  2560. };
  2561. }
  2562. function parseAttributes() {
  2563. let attrs = Object.create(null);
  2564. while (test(RE_ATTRIBUTE_START)) {
  2565. let name = match1(RE_ATTRIBUTE_START);
  2566. let value = parsePattern();
  2567. if (value === null) {
  2568. throw new SyntaxError("Expected attribute value");
  2569. }
  2570. attrs[name] = value;
  2571. }
  2572. return attrs;
  2573. }
  2574. function parsePattern() {
  2575. let first;
  2576. if (test(RE_TEXT_RUN)) {
  2577. first = match1(RE_TEXT_RUN);
  2578. }
  2579. if (source[cursor] === "{" || source[cursor] === "}") {
  2580. return parsePatternElements(first ? [first] : [], Infinity);
  2581. }
  2582. let indent = parseIndent();
  2583. if (indent) {
  2584. if (first) {
  2585. return parsePatternElements([first, indent], indent.length);
  2586. }
  2587. indent.value = trim(indent.value, RE_LEADING_NEWLINES);
  2588. return parsePatternElements([indent], indent.length);
  2589. }
  2590. if (first) {
  2591. return trim(first, RE_TRAILING_SPACES);
  2592. }
  2593. return null;
  2594. }
  2595. function parsePatternElements(elements = [], commonIndent) {
  2596. while (true) {
  2597. if (test(RE_TEXT_RUN)) {
  2598. elements.push(match1(RE_TEXT_RUN));
  2599. continue;
  2600. }
  2601. if (source[cursor] === "{") {
  2602. elements.push(parsePlaceable());
  2603. continue;
  2604. }
  2605. if (source[cursor] === "}") {
  2606. throw new SyntaxError("Unbalanced closing brace");
  2607. }
  2608. let indent = parseIndent();
  2609. if (indent) {
  2610. elements.push(indent);
  2611. commonIndent = Math.min(commonIndent, indent.length);
  2612. continue;
  2613. }
  2614. break;
  2615. }
  2616. let lastIndex = elements.length - 1;
  2617. let lastElement = elements[lastIndex];
  2618. if (typeof lastElement === "string") {
  2619. elements[lastIndex] = trim(lastElement, RE_TRAILING_SPACES);
  2620. }
  2621. let baked = [];
  2622. for (let element of elements) {
  2623. if (element instanceof Indent) {
  2624. element = element.value.slice(0, element.value.length - commonIndent);
  2625. }
  2626. if (element) {
  2627. baked.push(element);
  2628. }
  2629. }
  2630. return baked;
  2631. }
  2632. function parsePlaceable() {
  2633. consumeToken(TOKEN_BRACE_OPEN, SyntaxError);
  2634. let selector = parseInlineExpression();
  2635. if (consumeToken(TOKEN_BRACE_CLOSE)) {
  2636. return selector;
  2637. }
  2638. if (consumeToken(TOKEN_ARROW)) {
  2639. let variants = parseVariants();
  2640. consumeToken(TOKEN_BRACE_CLOSE, SyntaxError);
  2641. return {
  2642. type: "select",
  2643. selector,
  2644. ...variants
  2645. };
  2646. }
  2647. throw new SyntaxError("Unclosed placeable");
  2648. }
  2649. function parseInlineExpression() {
  2650. if (source[cursor] === "{") {
  2651. return parsePlaceable();
  2652. }
  2653. if (test(RE_REFERENCE)) {
  2654. let [, sigil, name, attr = null] = match(RE_REFERENCE);
  2655. if (sigil === "$") {
  2656. return {
  2657. type: "var",
  2658. name
  2659. };
  2660. }
  2661. if (consumeToken(TOKEN_PAREN_OPEN)) {
  2662. let args = parseArguments();
  2663. if (sigil === "-") {
  2664. return {
  2665. type: "term",
  2666. name,
  2667. attr,
  2668. args
  2669. };
  2670. }
  2671. if (RE_FUNCTION_NAME.test(name)) {
  2672. return {
  2673. type: "func",
  2674. name,
  2675. args
  2676. };
  2677. }
  2678. throw new SyntaxError("Function names must be all upper-case");
  2679. }
  2680. if (sigil === "-") {
  2681. return {
  2682. type: "term",
  2683. name,
  2684. attr,
  2685. args: []
  2686. };
  2687. }
  2688. return {
  2689. type: "mesg",
  2690. name,
  2691. attr
  2692. };
  2693. }
  2694. return parseLiteral();
  2695. }
  2696. function parseArguments() {
  2697. let args = [];
  2698. while (true) {
  2699. switch (source[cursor]) {
  2700. case ")":
  2701. cursor++;
  2702. return args;
  2703. case undefined:
  2704. throw new SyntaxError("Unclosed argument list");
  2705. }
  2706. args.push(parseArgument());
  2707. consumeToken(TOKEN_COMMA);
  2708. }
  2709. }
  2710. function parseArgument() {
  2711. let expr = parseInlineExpression();
  2712. if (expr.type !== "mesg") {
  2713. return expr;
  2714. }
  2715. if (consumeToken(TOKEN_COLON)) {
  2716. return {
  2717. type: "narg",
  2718. name: expr.name,
  2719. value: parseLiteral()
  2720. };
  2721. }
  2722. return expr;
  2723. }
  2724. function parseVariants() {
  2725. let variants = [];
  2726. let count = 0;
  2727. let star;
  2728. while (test(RE_VARIANT_START)) {
  2729. if (consumeChar("*")) {
  2730. star = count;
  2731. }
  2732. let key = parseVariantKey();
  2733. let value = parsePattern();
  2734. if (value === null) {
  2735. throw new SyntaxError("Expected variant value");
  2736. }
  2737. variants[count++] = {
  2738. key,
  2739. value
  2740. };
  2741. }
  2742. if (count === 0) {
  2743. return null;
  2744. }
  2745. if (star === undefined) {
  2746. throw new SyntaxError("Expected default variant");
  2747. }
  2748. return {
  2749. variants,
  2750. star
  2751. };
  2752. }
  2753. function parseVariantKey() {
  2754. consumeToken(TOKEN_BRACKET_OPEN, SyntaxError);
  2755. let key;
  2756. if (test(RE_NUMBER_LITERAL)) {
  2757. key = parseNumberLiteral();
  2758. } else {
  2759. key = {
  2760. type: "str",
  2761. value: match1(RE_IDENTIFIER)
  2762. };
  2763. }
  2764. consumeToken(TOKEN_BRACKET_CLOSE, SyntaxError);
  2765. return key;
  2766. }
  2767. function parseLiteral() {
  2768. if (test(RE_NUMBER_LITERAL)) {
  2769. return parseNumberLiteral();
  2770. }
  2771. if (source[cursor] === '"') {
  2772. return parseStringLiteral();
  2773. }
  2774. throw new SyntaxError("Invalid expression");
  2775. }
  2776. function parseNumberLiteral() {
  2777. let [, value, fraction = ""] = match(RE_NUMBER_LITERAL);
  2778. let precision = fraction.length;
  2779. return {
  2780. type: "num",
  2781. value: parseFloat(value),
  2782. precision
  2783. };
  2784. }
  2785. function parseStringLiteral() {
  2786. consumeChar('"', SyntaxError);
  2787. let value = "";
  2788. while (true) {
  2789. value += match1(RE_STRING_RUN);
  2790. if (source[cursor] === "\\") {
  2791. value += parseEscapeSequence();
  2792. continue;
  2793. }
  2794. if (consumeChar('"')) {
  2795. return {
  2796. type: "str",
  2797. value
  2798. };
  2799. }
  2800. throw new SyntaxError("Unclosed string literal");
  2801. }
  2802. }
  2803. function parseEscapeSequence() {
  2804. if (test(RE_STRING_ESCAPE)) {
  2805. return match1(RE_STRING_ESCAPE);
  2806. }
  2807. if (test(RE_UNICODE_ESCAPE)) {
  2808. let [, codepoint4, codepoint6] = match(RE_UNICODE_ESCAPE);
  2809. let codepoint = parseInt(codepoint4 || codepoint6, 16);
  2810. return codepoint <= 0xd7ff || 0xe000 <= codepoint ? String.fromCodePoint(codepoint) : "�";
  2811. }
  2812. throw new SyntaxError("Unknown escape sequence");
  2813. }
  2814. function parseIndent() {
  2815. let start = cursor;
  2816. consumeToken(TOKEN_BLANK);
  2817. switch (source[cursor]) {
  2818. case ".":
  2819. case "[":
  2820. case "*":
  2821. case "}":
  2822. case undefined:
  2823. return false;
  2824. case "{":
  2825. return makeIndent(source.slice(start, cursor));
  2826. }
  2827. if (source[cursor - 1] === " ") {
  2828. return makeIndent(source.slice(start, cursor));
  2829. }
  2830. return false;
  2831. }
  2832. function trim(text, re) {
  2833. return text.replace(re, "");
  2834. }
  2835. function makeIndent(blank) {
  2836. let value = blank.replace(RE_BLANK_LINES, "\n");
  2837. let length = RE_INDENT.exec(blank)[1].length;
  2838. return new Indent(value, length);
  2839. }
  2840. }
  2841. }
  2842. class Indent {
  2843. constructor(value, length) {
  2844. this.value = value;
  2845. this.length = length;
  2846. }
  2847. }
  2848. ;// ./node_modules/@fluent/bundle/esm/index.js
  2849. ;// ./node_modules/@fluent/dom/esm/overlay.js
  2850. const reOverlay = /<|&#?\w+;/;
  2851. const TEXT_LEVEL_ELEMENTS = {
  2852. "http://www.w3.org/1999/xhtml": ["em", "strong", "small", "s", "cite", "q", "dfn", "abbr", "data", "time", "code", "var", "samp", "kbd", "sub", "sup", "i", "b", "u", "mark", "bdi", "bdo", "span", "br", "wbr"]
  2853. };
  2854. const LOCALIZABLE_ATTRIBUTES = {
  2855. "http://www.w3.org/1999/xhtml": {
  2856. global: ["title", "aria-label", "aria-valuetext"],
  2857. a: ["download"],
  2858. area: ["download", "alt"],
  2859. input: ["alt", "placeholder"],
  2860. menuitem: ["label"],
  2861. menu: ["label"],
  2862. optgroup: ["label"],
  2863. option: ["label"],
  2864. track: ["label"],
  2865. img: ["alt"],
  2866. textarea: ["placeholder"],
  2867. th: ["abbr"]
  2868. },
  2869. "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul": {
  2870. global: ["accesskey", "aria-label", "aria-valuetext", "label", "title", "tooltiptext"],
  2871. description: ["value"],
  2872. key: ["key", "keycode"],
  2873. label: ["value"],
  2874. textbox: ["placeholder", "value"]
  2875. }
  2876. };
  2877. function translateElement(element, translation) {
  2878. const {
  2879. value
  2880. } = translation;
  2881. if (typeof value === "string") {
  2882. if (element.localName === "title" && element.namespaceURI === "http://www.w3.org/1999/xhtml") {
  2883. element.textContent = value;
  2884. } else if (!reOverlay.test(value)) {
  2885. element.textContent = value;
  2886. } else {
  2887. const templateElement = element.ownerDocument.createElementNS("http://www.w3.org/1999/xhtml", "template");
  2888. templateElement.innerHTML = value;
  2889. overlayChildNodes(templateElement.content, element);
  2890. }
  2891. }
  2892. overlayAttributes(translation, element);
  2893. }
  2894. function overlayChildNodes(fromFragment, toElement) {
  2895. for (const childNode of fromFragment.childNodes) {
  2896. if (childNode.nodeType === childNode.TEXT_NODE) {
  2897. continue;
  2898. }
  2899. if (childNode.hasAttribute("data-l10n-name")) {
  2900. const sanitized = getNodeForNamedElement(toElement, childNode);
  2901. fromFragment.replaceChild(sanitized, childNode);
  2902. continue;
  2903. }
  2904. if (isElementAllowed(childNode)) {
  2905. const sanitized = createSanitizedElement(childNode);
  2906. fromFragment.replaceChild(sanitized, childNode);
  2907. continue;
  2908. }
  2909. console.warn(`An element of forbidden type "${childNode.localName}" was found in ` + "the translation. Only safe text-level elements and elements with " + "data-l10n-name are allowed.");
  2910. fromFragment.replaceChild(createTextNodeFromTextContent(childNode), childNode);
  2911. }
  2912. toElement.textContent = "";
  2913. toElement.appendChild(fromFragment);
  2914. }
  2915. function hasAttribute(attributes, name) {
  2916. if (!attributes) {
  2917. return false;
  2918. }
  2919. for (let attr of attributes) {
  2920. if (attr.name === name) {
  2921. return true;
  2922. }
  2923. }
  2924. return false;
  2925. }
  2926. function overlayAttributes(fromElement, toElement) {
  2927. const explicitlyAllowed = toElement.hasAttribute("data-l10n-attrs") ? toElement.getAttribute("data-l10n-attrs").split(",").map(i => i.trim()) : null;
  2928. for (const attr of Array.from(toElement.attributes)) {
  2929. if (isAttrNameLocalizable(attr.name, toElement, explicitlyAllowed) && !hasAttribute(fromElement.attributes, attr.name)) {
  2930. toElement.removeAttribute(attr.name);
  2931. }
  2932. }
  2933. if (!fromElement.attributes) {
  2934. return;
  2935. }
  2936. for (const attr of Array.from(fromElement.attributes)) {
  2937. if (isAttrNameLocalizable(attr.name, toElement, explicitlyAllowed) && toElement.getAttribute(attr.name) !== attr.value) {
  2938. toElement.setAttribute(attr.name, attr.value);
  2939. }
  2940. }
  2941. }
  2942. function getNodeForNamedElement(sourceElement, translatedChild) {
  2943. const childName = translatedChild.getAttribute("data-l10n-name");
  2944. const sourceChild = sourceElement.querySelector(`[data-l10n-name="${childName}"]`);
  2945. if (!sourceChild) {
  2946. console.warn(`An element named "${childName}" wasn't found in the source.`);
  2947. return createTextNodeFromTextContent(translatedChild);
  2948. }
  2949. if (sourceChild.localName !== translatedChild.localName) {
  2950. console.warn(`An element named "${childName}" was found in the translation ` + `but its type ${translatedChild.localName} didn't match the ` + `element found in the source (${sourceChild.localName}).`);
  2951. return createTextNodeFromTextContent(translatedChild);
  2952. }
  2953. sourceElement.removeChild(sourceChild);
  2954. const clone = sourceChild.cloneNode(false);
  2955. return shallowPopulateUsing(translatedChild, clone);
  2956. }
  2957. function createSanitizedElement(element) {
  2958. const clone = element.ownerDocument.createElement(element.localName);
  2959. return shallowPopulateUsing(element, clone);
  2960. }
  2961. function createTextNodeFromTextContent(element) {
  2962. return element.ownerDocument.createTextNode(element.textContent);
  2963. }
  2964. function isElementAllowed(element) {
  2965. const allowed = TEXT_LEVEL_ELEMENTS[element.namespaceURI];
  2966. return allowed && allowed.includes(element.localName);
  2967. }
  2968. function isAttrNameLocalizable(name, element, explicitlyAllowed = null) {
  2969. if (explicitlyAllowed && explicitlyAllowed.includes(name)) {
  2970. return true;
  2971. }
  2972. const allowed = LOCALIZABLE_ATTRIBUTES[element.namespaceURI];
  2973. if (!allowed) {
  2974. return false;
  2975. }
  2976. const attrName = name.toLowerCase();
  2977. const elemName = element.localName;
  2978. if (allowed.global.includes(attrName)) {
  2979. return true;
  2980. }
  2981. if (!allowed[elemName]) {
  2982. return false;
  2983. }
  2984. if (allowed[elemName].includes(attrName)) {
  2985. return true;
  2986. }
  2987. if (element.namespaceURI === "http://www.w3.org/1999/xhtml" && elemName === "input" && attrName === "value") {
  2988. const type = element.type.toLowerCase();
  2989. if (type === "submit" || type === "button" || type === "reset") {
  2990. return true;
  2991. }
  2992. }
  2993. return false;
  2994. }
  2995. function shallowPopulateUsing(fromElement, toElement) {
  2996. toElement.textContent = fromElement.textContent;
  2997. overlayAttributes(fromElement, toElement);
  2998. return toElement;
  2999. }
  3000. ;// ./node_modules/cached-iterable/src/cached_iterable.mjs
  3001. class CachedIterable extends Array {
  3002. static from(iterable) {
  3003. if (iterable instanceof this) {
  3004. return iterable;
  3005. }
  3006. return new this(iterable);
  3007. }
  3008. }
  3009. ;// ./node_modules/cached-iterable/src/cached_sync_iterable.mjs
  3010. class CachedSyncIterable extends CachedIterable {
  3011. constructor(iterable) {
  3012. super();
  3013. if (Symbol.iterator in Object(iterable)) {
  3014. this.iterator = iterable[Symbol.iterator]();
  3015. } else {
  3016. throw new TypeError("Argument must implement the iteration protocol.");
  3017. }
  3018. }
  3019. [Symbol.iterator]() {
  3020. const cached = this;
  3021. let cur = 0;
  3022. return {
  3023. next() {
  3024. if (cached.length <= cur) {
  3025. cached.push(cached.iterator.next());
  3026. }
  3027. return cached[cur++];
  3028. }
  3029. };
  3030. }
  3031. touchNext(count = 1) {
  3032. let idx = 0;
  3033. while (idx++ < count) {
  3034. const last = this[this.length - 1];
  3035. if (last && last.done) {
  3036. break;
  3037. }
  3038. this.push(this.iterator.next());
  3039. }
  3040. return this[this.length - 1];
  3041. }
  3042. }
  3043. ;// ./node_modules/cached-iterable/src/cached_async_iterable.mjs
  3044. class CachedAsyncIterable extends CachedIterable {
  3045. constructor(iterable) {
  3046. super();
  3047. if (Symbol.asyncIterator in Object(iterable)) {
  3048. this.iterator = iterable[Symbol.asyncIterator]();
  3049. } else if (Symbol.iterator in Object(iterable)) {
  3050. this.iterator = iterable[Symbol.iterator]();
  3051. } else {
  3052. throw new TypeError("Argument must implement the iteration protocol.");
  3053. }
  3054. }
  3055. [Symbol.asyncIterator]() {
  3056. const cached = this;
  3057. let cur = 0;
  3058. return {
  3059. async next() {
  3060. if (cached.length <= cur) {
  3061. cached.push(cached.iterator.next());
  3062. }
  3063. return cached[cur++];
  3064. }
  3065. };
  3066. }
  3067. async touchNext(count = 1) {
  3068. let idx = 0;
  3069. while (idx++ < count) {
  3070. const last = this[this.length - 1];
  3071. if (last && (await last).done) {
  3072. break;
  3073. }
  3074. this.push(this.iterator.next());
  3075. }
  3076. return this[this.length - 1];
  3077. }
  3078. }
  3079. ;// ./node_modules/cached-iterable/src/index.mjs
  3080. ;// ./node_modules/@fluent/dom/esm/localization.js
  3081. class Localization {
  3082. constructor(resourceIds = [], generateBundles) {
  3083. this.resourceIds = resourceIds;
  3084. this.generateBundles = generateBundles;
  3085. this.onChange(true);
  3086. }
  3087. addResourceIds(resourceIds, eager = false) {
  3088. this.resourceIds.push(...resourceIds);
  3089. this.onChange(eager);
  3090. return this.resourceIds.length;
  3091. }
  3092. removeResourceIds(resourceIds) {
  3093. this.resourceIds = this.resourceIds.filter(r => !resourceIds.includes(r));
  3094. this.onChange();
  3095. return this.resourceIds.length;
  3096. }
  3097. async formatWithFallback(keys, method) {
  3098. const translations = [];
  3099. let hasAtLeastOneBundle = false;
  3100. for await (const bundle of this.bundles) {
  3101. hasAtLeastOneBundle = true;
  3102. const missingIds = keysFromBundle(method, bundle, keys, translations);
  3103. if (missingIds.size === 0) {
  3104. break;
  3105. }
  3106. if (typeof console !== "undefined") {
  3107. const locale = bundle.locales[0];
  3108. const ids = Array.from(missingIds).join(", ");
  3109. console.warn(`[fluent] Missing translations in ${locale}: ${ids}`);
  3110. }
  3111. }
  3112. if (!hasAtLeastOneBundle && typeof console !== "undefined") {
  3113. console.warn(`[fluent] Request for keys failed because no resource bundles got generated.
  3114. keys: ${JSON.stringify(keys)}.
  3115. resourceIds: ${JSON.stringify(this.resourceIds)}.`);
  3116. }
  3117. return translations;
  3118. }
  3119. formatMessages(keys) {
  3120. return this.formatWithFallback(keys, messageFromBundle);
  3121. }
  3122. formatValues(keys) {
  3123. return this.formatWithFallback(keys, valueFromBundle);
  3124. }
  3125. async formatValue(id, args) {
  3126. const [val] = await this.formatValues([{
  3127. id,
  3128. args
  3129. }]);
  3130. return val;
  3131. }
  3132. handleEvent() {
  3133. this.onChange();
  3134. }
  3135. onChange(eager = false) {
  3136. this.bundles = CachedAsyncIterable.from(this.generateBundles(this.resourceIds));
  3137. if (eager) {
  3138. this.bundles.touchNext(2);
  3139. }
  3140. }
  3141. }
  3142. function valueFromBundle(bundle, errors, message, args) {
  3143. if (message.value) {
  3144. return bundle.formatPattern(message.value, args, errors);
  3145. }
  3146. return null;
  3147. }
  3148. function messageFromBundle(bundle, errors, message, args) {
  3149. const formatted = {
  3150. value: null,
  3151. attributes: null
  3152. };
  3153. if (message.value) {
  3154. formatted.value = bundle.formatPattern(message.value, args, errors);
  3155. }
  3156. let attrNames = Object.keys(message.attributes);
  3157. if (attrNames.length > 0) {
  3158. formatted.attributes = new Array(attrNames.length);
  3159. for (let [i, name] of attrNames.entries()) {
  3160. let value = bundle.formatPattern(message.attributes[name], args, errors);
  3161. formatted.attributes[i] = {
  3162. name,
  3163. value
  3164. };
  3165. }
  3166. }
  3167. return formatted;
  3168. }
  3169. function keysFromBundle(method, bundle, keys, translations) {
  3170. const messageErrors = [];
  3171. const missingIds = new Set();
  3172. keys.forEach(({
  3173. id,
  3174. args
  3175. }, i) => {
  3176. if (translations[i] !== undefined) {
  3177. return;
  3178. }
  3179. let message = bundle.getMessage(id);
  3180. if (message) {
  3181. messageErrors.length = 0;
  3182. translations[i] = method(bundle, messageErrors, message, args);
  3183. if (messageErrors.length > 0 && typeof console !== "undefined") {
  3184. const locale = bundle.locales[0];
  3185. const errors = messageErrors.join(", ");
  3186. console.warn(`[fluent][resolver] errors in ${locale}/${id}: ${errors}.`);
  3187. }
  3188. } else {
  3189. missingIds.add(id);
  3190. }
  3191. });
  3192. return missingIds;
  3193. }
  3194. ;// ./node_modules/@fluent/dom/esm/dom_localization.js
  3195. const L10NID_ATTR_NAME = "data-l10n-id";
  3196. const L10NARGS_ATTR_NAME = "data-l10n-args";
  3197. const L10N_ELEMENT_QUERY = `[${L10NID_ATTR_NAME}]`;
  3198. class DOMLocalization extends Localization {
  3199. constructor(resourceIds, generateBundles) {
  3200. super(resourceIds, generateBundles);
  3201. this.roots = new Set();
  3202. this.pendingrAF = null;
  3203. this.pendingElements = new Set();
  3204. this.windowElement = null;
  3205. this.mutationObserver = null;
  3206. this.observerConfig = {
  3207. attributes: true,
  3208. characterData: false,
  3209. childList: true,
  3210. subtree: true,
  3211. attributeFilter: [L10NID_ATTR_NAME, L10NARGS_ATTR_NAME]
  3212. };
  3213. }
  3214. onChange(eager = false) {
  3215. super.onChange(eager);
  3216. if (this.roots) {
  3217. this.translateRoots();
  3218. }
  3219. }
  3220. setAttributes(element, id, args) {
  3221. element.setAttribute(L10NID_ATTR_NAME, id);
  3222. if (args) {
  3223. element.setAttribute(L10NARGS_ATTR_NAME, JSON.stringify(args));
  3224. } else {
  3225. element.removeAttribute(L10NARGS_ATTR_NAME);
  3226. }
  3227. return element;
  3228. }
  3229. getAttributes(element) {
  3230. return {
  3231. id: element.getAttribute(L10NID_ATTR_NAME),
  3232. args: JSON.parse(element.getAttribute(L10NARGS_ATTR_NAME) || null)
  3233. };
  3234. }
  3235. connectRoot(newRoot) {
  3236. for (const root of this.roots) {
  3237. if (root === newRoot || root.contains(newRoot) || newRoot.contains(root)) {
  3238. throw new Error("Cannot add a root that overlaps with existing root.");
  3239. }
  3240. }
  3241. if (this.windowElement) {
  3242. if (this.windowElement !== newRoot.ownerDocument.defaultView) {
  3243. throw new Error(`Cannot connect a root:
  3244. DOMLocalization already has a root from a different window.`);
  3245. }
  3246. } else {
  3247. this.windowElement = newRoot.ownerDocument.defaultView;
  3248. this.mutationObserver = new this.windowElement.MutationObserver(mutations => this.translateMutations(mutations));
  3249. }
  3250. this.roots.add(newRoot);
  3251. this.mutationObserver.observe(newRoot, this.observerConfig);
  3252. }
  3253. disconnectRoot(root) {
  3254. this.roots.delete(root);
  3255. this.pauseObserving();
  3256. if (this.roots.size === 0) {
  3257. this.mutationObserver = null;
  3258. if (this.windowElement && this.pendingrAF) {
  3259. this.windowElement.cancelAnimationFrame(this.pendingrAF);
  3260. }
  3261. this.windowElement = null;
  3262. this.pendingrAF = null;
  3263. this.pendingElements.clear();
  3264. return true;
  3265. }
  3266. this.resumeObserving();
  3267. return false;
  3268. }
  3269. translateRoots() {
  3270. const roots = Array.from(this.roots);
  3271. return Promise.all(roots.map(root => this.translateFragment(root)));
  3272. }
  3273. pauseObserving() {
  3274. if (!this.mutationObserver) {
  3275. return;
  3276. }
  3277. this.translateMutations(this.mutationObserver.takeRecords());
  3278. this.mutationObserver.disconnect();
  3279. }
  3280. resumeObserving() {
  3281. if (!this.mutationObserver) {
  3282. return;
  3283. }
  3284. for (const root of this.roots) {
  3285. this.mutationObserver.observe(root, this.observerConfig);
  3286. }
  3287. }
  3288. translateMutations(mutations) {
  3289. for (const mutation of mutations) {
  3290. switch (mutation.type) {
  3291. case "attributes":
  3292. if (mutation.target.hasAttribute("data-l10n-id")) {
  3293. this.pendingElements.add(mutation.target);
  3294. }
  3295. break;
  3296. case "childList":
  3297. for (const addedNode of mutation.addedNodes) {
  3298. if (addedNode.nodeType === addedNode.ELEMENT_NODE) {
  3299. if (addedNode.childElementCount) {
  3300. for (const element of this.getTranslatables(addedNode)) {
  3301. this.pendingElements.add(element);
  3302. }
  3303. } else if (addedNode.hasAttribute(L10NID_ATTR_NAME)) {
  3304. this.pendingElements.add(addedNode);
  3305. }
  3306. }
  3307. }
  3308. break;
  3309. }
  3310. }
  3311. if (this.pendingElements.size > 0) {
  3312. if (this.pendingrAF === null) {
  3313. this.pendingrAF = this.windowElement.requestAnimationFrame(() => {
  3314. this.translateElements(Array.from(this.pendingElements));
  3315. this.pendingElements.clear();
  3316. this.pendingrAF = null;
  3317. });
  3318. }
  3319. }
  3320. }
  3321. translateFragment(frag) {
  3322. return this.translateElements(this.getTranslatables(frag));
  3323. }
  3324. async translateElements(elements) {
  3325. if (!elements.length) {
  3326. return undefined;
  3327. }
  3328. const keys = elements.map(this.getKeysForElement);
  3329. const translations = await this.formatMessages(keys);
  3330. return this.applyTranslations(elements, translations);
  3331. }
  3332. applyTranslations(elements, translations) {
  3333. this.pauseObserving();
  3334. for (let i = 0; i < elements.length; i++) {
  3335. if (translations[i] !== undefined) {
  3336. translateElement(elements[i], translations[i]);
  3337. }
  3338. }
  3339. this.resumeObserving();
  3340. }
  3341. getTranslatables(element) {
  3342. const nodes = Array.from(element.querySelectorAll(L10N_ELEMENT_QUERY));
  3343. if (typeof element.hasAttribute === "function" && element.hasAttribute(L10NID_ATTR_NAME)) {
  3344. nodes.push(element);
  3345. }
  3346. return nodes;
  3347. }
  3348. getKeysForElement(element) {
  3349. return {
  3350. id: element.getAttribute(L10NID_ATTR_NAME),
  3351. args: JSON.parse(element.getAttribute(L10NARGS_ATTR_NAME) || null)
  3352. };
  3353. }
  3354. }
  3355. ;// ./node_modules/@fluent/dom/esm/index.js
  3356. ;// ./web/l10n.js
  3357. class L10n {
  3358. #dir;
  3359. #elements;
  3360. #lang;
  3361. #l10n;
  3362. constructor({
  3363. lang,
  3364. isRTL
  3365. }, l10n = null) {
  3366. this.#lang = L10n.#fixupLangCode(lang);
  3367. this.#l10n = l10n;
  3368. this.#dir = isRTL ?? L10n.#isRTL(this.#lang) ? "rtl" : "ltr";
  3369. }
  3370. _setL10n(l10n) {
  3371. this.#l10n = l10n;
  3372. }
  3373. getLanguage() {
  3374. return this.#lang;
  3375. }
  3376. getDirection() {
  3377. return this.#dir;
  3378. }
  3379. async get(ids, args = null, fallback) {
  3380. if (Array.isArray(ids)) {
  3381. ids = ids.map(id => ({
  3382. id
  3383. }));
  3384. const messages = await this.#l10n.formatMessages(ids);
  3385. return messages.map(message => message.value);
  3386. }
  3387. const messages = await this.#l10n.formatMessages([{
  3388. id: ids,
  3389. args
  3390. }]);
  3391. return messages[0]?.value || fallback;
  3392. }
  3393. async translate(element) {
  3394. (this.#elements ||= new Set()).add(element);
  3395. try {
  3396. this.#l10n.connectRoot(element);
  3397. await this.#l10n.translateRoots();
  3398. } catch {}
  3399. }
  3400. async translateOnce(element) {
  3401. try {
  3402. await this.#l10n.translateElements([element]);
  3403. } catch (ex) {
  3404. console.error("translateOnce:", ex);
  3405. }
  3406. }
  3407. async destroy() {
  3408. if (this.#elements) {
  3409. for (const element of this.#elements) {
  3410. this.#l10n.disconnectRoot(element);
  3411. }
  3412. this.#elements.clear();
  3413. this.#elements = null;
  3414. }
  3415. this.#l10n.pauseObserving();
  3416. }
  3417. pause() {
  3418. this.#l10n.pauseObserving();
  3419. }
  3420. resume() {
  3421. this.#l10n.resumeObserving();
  3422. }
  3423. static #fixupLangCode(langCode) {
  3424. langCode = langCode?.toLowerCase() || "en-us";
  3425. const PARTIAL_LANG_CODES = {
  3426. en: "en-us",
  3427. es: "es-es",
  3428. fy: "fy-nl",
  3429. ga: "ga-ie",
  3430. gu: "gu-in",
  3431. hi: "hi-in",
  3432. hy: "hy-am",
  3433. nb: "nb-no",
  3434. ne: "ne-np",
  3435. nn: "nn-no",
  3436. pa: "pa-in",
  3437. pt: "pt-pt",
  3438. sv: "sv-se",
  3439. zh: "zh-cn"
  3440. };
  3441. return PARTIAL_LANG_CODES[langCode] || langCode;
  3442. }
  3443. static #isRTL(lang) {
  3444. const shortCode = lang.split("-", 1)[0];
  3445. return ["ar", "he", "fa", "ps", "ur"].includes(shortCode);
  3446. }
  3447. }
  3448. const GenericL10n = null;
  3449. ;// ./web/genericl10n.js
  3450. function createBundle(lang, text) {
  3451. const resource = new FluentResource(text);
  3452. const bundle = new FluentBundle(lang);
  3453. const errors = bundle.addResource(resource);
  3454. if (errors.length) {
  3455. console.error("L10n errors", errors);
  3456. }
  3457. return bundle;
  3458. }
  3459. class genericl10n_GenericL10n extends L10n {
  3460. constructor(lang) {
  3461. super({
  3462. lang
  3463. });
  3464. const generateBundles = !lang ? genericl10n_GenericL10n.#generateBundlesFallback.bind(genericl10n_GenericL10n, this.getLanguage()) : genericl10n_GenericL10n.#generateBundles.bind(genericl10n_GenericL10n, "en-us", this.getLanguage());
  3465. this._setL10n(new DOMLocalization([], generateBundles));
  3466. }
  3467. static async *#generateBundles(defaultLang, baseLang) {
  3468. const {
  3469. baseURL,
  3470. paths
  3471. } = await this.#getPaths();
  3472. const langs = [baseLang];
  3473. if (defaultLang !== baseLang) {
  3474. const shortLang = baseLang.split("-", 1)[0];
  3475. if (shortLang !== baseLang) {
  3476. langs.push(shortLang);
  3477. }
  3478. langs.push(defaultLang);
  3479. }
  3480. for (const lang of langs) {
  3481. const bundle = await this.#createBundle(lang, baseURL, paths);
  3482. if (bundle) {
  3483. yield bundle;
  3484. } else if (lang === "en-us") {
  3485. yield this.#createBundleFallback(lang);
  3486. }
  3487. }
  3488. }
  3489. static async #createBundle(lang, baseURL, paths) {
  3490. const path = paths[lang];
  3491. if (!path) {
  3492. return null;
  3493. }
  3494. const url = new URL(path, baseURL);
  3495. const text = await fetchData(url, "text");
  3496. return createBundle(lang, text);
  3497. }
  3498. static async #getPaths() {
  3499. try {
  3500. const {
  3501. href
  3502. } = document.querySelector(`link[type="application/l10n"]`);
  3503. const paths = await fetchData(href, "json");
  3504. return {
  3505. baseURL: href.replace(/[^/]*$/, "") || "./",
  3506. paths
  3507. };
  3508. } catch {}
  3509. return {
  3510. baseURL: "./",
  3511. paths: Object.create(null)
  3512. };
  3513. }
  3514. static async *#generateBundlesFallback(lang) {
  3515. yield this.#createBundleFallback(lang);
  3516. }
  3517. static async #createBundleFallback(lang) {
  3518. const text = "pdfjs-previous-button =\n .title = Previous Page\npdfjs-previous-button-label = Previous\npdfjs-next-button =\n .title = Next Page\npdfjs-next-button-label = Next\npdfjs-page-input =\n .title = Page\npdfjs-of-pages = of { $pagesCount }\npdfjs-page-of-pages = ({ $pageNumber } of { $pagesCount })\npdfjs-zoom-out-button =\n .title = Zoom Out\npdfjs-zoom-out-button-label = Zoom Out\npdfjs-zoom-in-button =\n .title = Zoom In\npdfjs-zoom-in-button-label = Zoom In\npdfjs-zoom-select =\n .title = Zoom\npdfjs-presentation-mode-button =\n .title = Switch to Presentation Mode\npdfjs-presentation-mode-button-label = Presentation Mode\npdfjs-open-file-button =\n .title = Open File\npdfjs-open-file-button-label = Open\npdfjs-print-button =\n .title = Print\npdfjs-print-button-label = Print\npdfjs-save-button =\n .title = Save\npdfjs-save-button-label = Save\npdfjs-download-button =\n .title = Download\npdfjs-download-button-label = Download\npdfjs-bookmark-button =\n .title = Current Page (View URL from Current Page)\npdfjs-bookmark-button-label = Current Page\npdfjs-tools-button =\n .title = Tools\npdfjs-tools-button-label = Tools\npdfjs-first-page-button =\n .title = Go to First Page\npdfjs-first-page-button-label = Go to First Page\npdfjs-last-page-button =\n .title = Go to Last Page\npdfjs-last-page-button-label = Go to Last Page\npdfjs-page-rotate-cw-button =\n .title = Rotate Clockwise\npdfjs-page-rotate-cw-button-label = Rotate Clockwise\npdfjs-page-rotate-ccw-button =\n .title = Rotate Counterclockwise\npdfjs-page-rotate-ccw-button-label = Rotate Counterclockwise\npdfjs-cursor-text-select-tool-button =\n .title = Enable Text Selection Tool\npdfjs-cursor-text-select-tool-button-label = Text Selection Tool\npdfjs-cursor-hand-tool-button =\n .title = Enable Hand Tool\npdfjs-cursor-hand-tool-button-label = Hand Tool\npdfjs-scroll-page-button =\n .title = Use Page Scrolling\npdfjs-scroll-page-button-label = Page Scrolling\npdfjs-scroll-vertical-button =\n .title = Use Vertical Scrolling\npdfjs-scroll-vertical-button-label = Vertical Scrolling\npdfjs-scroll-horizontal-button =\n .title = Use Horizontal Scrolling\npdfjs-scroll-horizontal-button-label = Horizontal Scrolling\npdfjs-scroll-wrapped-button =\n .title = Use Wrapped Scrolling\npdfjs-scroll-wrapped-button-label = Wrapped Scrolling\npdfjs-spread-none-button =\n .title = Do not join page spreads\npdfjs-spread-none-button-label = No Spreads\npdfjs-spread-odd-button =\n .title = Join page spreads starting with odd-numbered pages\npdfjs-spread-odd-button-label = Odd Spreads\npdfjs-spread-even-button =\n .title = Join page spreads starting with even-numbered pages\npdfjs-spread-even-button-label = Even Spreads\npdfjs-document-properties-button =\n .title = Document Properties\u2026\npdfjs-document-properties-button-label = Document Properties\u2026\npdfjs-document-properties-file-name = File name:\npdfjs-document-properties-file-size = File size:\npdfjs-document-properties-size-kb = { NUMBER($kb, maximumSignificantDigits: 3) } KB ({ $b } bytes)\npdfjs-document-properties-size-mb = { NUMBER($mb, maximumSignificantDigits: 3) } MB ({ $b } bytes)\npdfjs-document-properties-title = Title:\npdfjs-document-properties-author = Author:\npdfjs-document-properties-subject = Subject:\npdfjs-document-properties-keywords = Keywords:\npdfjs-document-properties-creation-date = Creation Date:\npdfjs-document-properties-modification-date = Modification Date:\npdfjs-document-properties-date-time-string = { DATETIME($dateObj, dateStyle: \"short\", timeStyle: \"medium\") }\npdfjs-document-properties-creator = Creator:\npdfjs-document-properties-producer = PDF Producer:\npdfjs-document-properties-version = PDF Version:\npdfjs-document-properties-page-count = Page Count:\npdfjs-document-properties-page-size = Page Size:\npdfjs-document-properties-page-size-unit-inches = in\npdfjs-document-properties-page-size-unit-millimeters = mm\npdfjs-document-properties-page-size-orientation-portrait = portrait\npdfjs-document-properties-page-size-orientation-landscape = landscape\npdfjs-document-properties-page-size-name-a-three = A3\npdfjs-document-properties-page-size-name-a-four = A4\npdfjs-document-properties-page-size-name-letter = Letter\npdfjs-document-properties-page-size-name-legal = Legal\npdfjs-document-properties-page-size-dimension-string = { $width } \xD7 { $height } { $unit } ({ $orientation })\npdfjs-document-properties-page-size-dimension-name-string = { $width } \xD7 { $height } { $unit } ({ $name }, { $orientation })\npdfjs-document-properties-linearized = Fast Web View:\npdfjs-document-properties-linearized-yes = Yes\npdfjs-document-properties-linearized-no = No\npdfjs-document-properties-close-button = Close\npdfjs-print-progress-message = Preparing document for printing\u2026\npdfjs-print-progress-percent = { $progress }%\npdfjs-print-progress-close-button = Cancel\npdfjs-printing-not-supported = Warning: Printing is not fully supported by this browser.\npdfjs-printing-not-ready = Warning: The PDF is not fully loaded for printing.\npdfjs-toggle-sidebar-button =\n .title = Toggle Sidebar\npdfjs-toggle-sidebar-notification-button =\n .title = Toggle Sidebar (document contains outline/attachments/layers)\npdfjs-toggle-sidebar-button-label = Toggle Sidebar\npdfjs-document-outline-button =\n .title = Show Document Outline (double-click to expand/collapse all items)\npdfjs-document-outline-button-label = Document Outline\npdfjs-attachments-button =\n .title = Show Attachments\npdfjs-attachments-button-label = Attachments\npdfjs-layers-button =\n .title = Show Layers (double-click to reset all layers to the default state)\npdfjs-layers-button-label = Layers\npdfjs-thumbs-button =\n .title = Show Thumbnails\npdfjs-thumbs-button-label = Thumbnails\npdfjs-current-outline-item-button =\n .title = Find Current Outline Item\npdfjs-current-outline-item-button-label = Current Outline Item\npdfjs-findbar-button =\n .title = Find in Document\npdfjs-findbar-button-label = Find\npdfjs-additional-layers = Additional Layers\npdfjs-thumb-page-title =\n .title = Page { $page }\npdfjs-thumb-page-canvas =\n .aria-label = Thumbnail of Page { $page }\npdfjs-find-input =\n .title = Find\n .placeholder = Find in document\u2026\npdfjs-find-previous-button =\n .title = Find the previous occurrence of the phrase\npdfjs-find-previous-button-label = Previous\npdfjs-find-next-button =\n .title = Find the next occurrence of the phrase\npdfjs-find-next-button-label = Next\npdfjs-find-highlight-checkbox = Highlight All\npdfjs-find-match-case-checkbox-label = Match Case\npdfjs-find-match-diacritics-checkbox-label = Match Diacritics\npdfjs-find-entire-word-checkbox-label = Whole Words\npdfjs-find-reached-top = Reached top of document, continued from bottom\npdfjs-find-reached-bottom = Reached end of document, continued from top\npdfjs-find-match-count =\n { $total ->\n [one] { $current } of { $total } match\n *[other] { $current } of { $total } matches\n }\npdfjs-find-match-count-limit =\n { $limit ->\n [one] More than { $limit } match\n *[other] More than { $limit } matches\n }\npdfjs-find-not-found = Phrase not found\npdfjs-page-scale-width = Page Width\npdfjs-page-scale-fit = Page Fit\npdfjs-page-scale-auto = Automatic Zoom\npdfjs-page-scale-actual = Actual Size\npdfjs-page-scale-percent = { $scale }%\npdfjs-page-landmark =\n .aria-label = Page { $page }\npdfjs-loading-error = An error occurred while loading the PDF.\npdfjs-invalid-file-error = Invalid or corrupted PDF file.\npdfjs-missing-file-error = Missing PDF file.\npdfjs-unexpected-response-error = Unexpected server response.\npdfjs-rendering-error = An error occurred while rendering the page.\npdfjs-annotation-date-time-string = { DATETIME($dateObj, dateStyle: \"short\", timeStyle: \"medium\") }\npdfjs-text-annotation-type =\n .alt = [{ $type } Annotation]\npdfjs-password-label = Enter the password to open this PDF file.\npdfjs-password-invalid = Invalid password. Please try again.\npdfjs-password-ok-button = OK\npdfjs-password-cancel-button = Cancel\npdfjs-web-fonts-disabled = Web fonts are disabled: unable to use embedded PDF fonts.\npdfjs-editor-free-text-button =\n .title = Text\npdfjs-editor-free-text-button-label = Text\npdfjs-editor-ink-button =\n .title = Draw\npdfjs-editor-ink-button-label = Draw\npdfjs-editor-stamp-button =\n .title = Add or edit images\npdfjs-editor-stamp-button-label = Add or edit images\npdfjs-editor-highlight-button =\n .title = Highlight\npdfjs-editor-highlight-button-label = Highlight\npdfjs-highlight-floating-button1 =\n .title = Highlight\n .aria-label = Highlight\npdfjs-highlight-floating-button-label = Highlight\npdfjs-editor-remove-ink-button =\n .title = Remove drawing\npdfjs-editor-remove-freetext-button =\n .title = Remove text\npdfjs-editor-remove-stamp-button =\n .title = Remove image\npdfjs-editor-remove-highlight-button =\n .title = Remove highlight\npdfjs-editor-free-text-color-input = Color\npdfjs-editor-free-text-size-input = Size\npdfjs-editor-ink-color-input = Color\npdfjs-editor-ink-thickness-input = Thickness\npdfjs-editor-ink-opacity-input = Opacity\npdfjs-editor-stamp-add-image-button =\n .title = Add image\npdfjs-editor-stamp-add-image-button-label = Add image\npdfjs-editor-free-highlight-thickness-input = Thickness\npdfjs-editor-free-highlight-thickness-title =\n .title = Change thickness when highlighting items other than text\npdfjs-free-text2 =\n .aria-label = Text Editor\n .default-content = Start typing\u2026\npdfjs-ink =\n .aria-label = Draw Editor\npdfjs-ink-canvas =\n .aria-label = User-created image\npdfjs-editor-alt-text-button =\n .aria-label = Alt text\npdfjs-editor-alt-text-button-label = Alt text\npdfjs-editor-alt-text-edit-button =\n .aria-label = Edit alt text\npdfjs-editor-alt-text-dialog-label = Choose an option\npdfjs-editor-alt-text-dialog-description = Alt text (alternative text) helps when people can\u2019t see the image or when it doesn\u2019t load.\npdfjs-editor-alt-text-add-description-label = Add a description\npdfjs-editor-alt-text-add-description-description = Aim for 1-2 sentences that describe the subject, setting, or actions.\npdfjs-editor-alt-text-mark-decorative-label = Mark as decorative\npdfjs-editor-alt-text-mark-decorative-description = This is used for ornamental images, like borders or watermarks.\npdfjs-editor-alt-text-cancel-button = Cancel\npdfjs-editor-alt-text-save-button = Save\npdfjs-editor-alt-text-decorative-tooltip = Marked as decorative\npdfjs-editor-alt-text-textarea =\n .placeholder = For example, \u201CA young man sits down at a table to eat a meal\u201D\npdfjs-editor-resizer-top-left =\n .aria-label = Top left corner \u2014 resize\npdfjs-editor-resizer-top-middle =\n .aria-label = Top middle \u2014 resize\npdfjs-editor-resizer-top-right =\n .aria-label = Top right corner \u2014 resize\npdfjs-editor-resizer-middle-right =\n .aria-label = Middle right \u2014 resize\npdfjs-editor-resizer-bottom-right =\n .aria-label = Bottom right corner \u2014 resize\npdfjs-editor-resizer-bottom-middle =\n .aria-label = Bottom middle \u2014 resize\npdfjs-editor-resizer-bottom-left =\n .aria-label = Bottom left corner \u2014 resize\npdfjs-editor-resizer-middle-left =\n .aria-label = Middle left \u2014 resize\npdfjs-editor-highlight-colorpicker-label = Highlight color\npdfjs-editor-colorpicker-button =\n .title = Change color\npdfjs-editor-colorpicker-dropdown =\n .aria-label = Color choices\npdfjs-editor-colorpicker-yellow =\n .title = Yellow\npdfjs-editor-colorpicker-green =\n .title = Green\npdfjs-editor-colorpicker-blue =\n .title = Blue\npdfjs-editor-colorpicker-pink =\n .title = Pink\npdfjs-editor-colorpicker-red =\n .title = Red\npdfjs-editor-highlight-show-all-button-label = Show all\npdfjs-editor-highlight-show-all-button =\n .title = Show all\npdfjs-editor-new-alt-text-dialog-edit-label = Edit alt text (image description)\npdfjs-editor-new-alt-text-dialog-add-label = Add alt text (image description)\npdfjs-editor-new-alt-text-textarea =\n .placeholder = Write your description here\u2026\npdfjs-editor-new-alt-text-description = Short description for people who can\u2019t see the image or when the image doesn\u2019t load.\npdfjs-editor-new-alt-text-disclaimer1 = This alt text was created automatically and may be inaccurate.\npdfjs-editor-new-alt-text-disclaimer-learn-more-url = Learn more\npdfjs-editor-new-alt-text-create-automatically-button-label = Create alt text automatically\npdfjs-editor-new-alt-text-not-now-button = Not now\npdfjs-editor-new-alt-text-error-title = Couldn\u2019t create alt text automatically\npdfjs-editor-new-alt-text-error-description = Please write your own alt text or try again later.\npdfjs-editor-new-alt-text-error-close-button = Close\npdfjs-editor-new-alt-text-ai-model-downloading-progress = Downloading alt text AI model ({ $downloadedSize } of { $totalSize } MB)\n .aria-valuetext = Downloading alt text AI model ({ $downloadedSize } of { $totalSize } MB)\npdfjs-editor-new-alt-text-added-button =\n .aria-label = Alt text added\npdfjs-editor-new-alt-text-added-button-label = Alt text added\npdfjs-editor-new-alt-text-missing-button =\n .aria-label = Missing alt text\npdfjs-editor-new-alt-text-missing-button-label = Missing alt text\npdfjs-editor-new-alt-text-to-review-button =\n .aria-label = Review alt text\npdfjs-editor-new-alt-text-to-review-button-label = Review alt text\npdfjs-editor-new-alt-text-generated-alt-text-with-disclaimer = Created automatically: { $generatedAltText }\npdfjs-image-alt-text-settings-button =\n .title = Image alt text settings\npdfjs-image-alt-text-settings-button-label = Image alt text settings\npdfjs-editor-alt-text-settings-dialog-label = Image alt text settings\npdfjs-editor-alt-text-settings-automatic-title = Automatic alt text\npdfjs-editor-alt-text-settings-create-model-button-label = Create alt text automatically\npdfjs-editor-alt-text-settings-create-model-description = Suggests descriptions to help people who can\u2019t see the image or when the image doesn\u2019t load.\npdfjs-editor-alt-text-settings-download-model-label = Alt text AI model ({ $totalSize } MB)\npdfjs-editor-alt-text-settings-ai-model-description = Runs locally on your device so your data stays private. Required for automatic alt text.\npdfjs-editor-alt-text-settings-delete-model-button = Delete\npdfjs-editor-alt-text-settings-download-model-button = Download\npdfjs-editor-alt-text-settings-downloading-model-button = Downloading\u2026\npdfjs-editor-alt-text-settings-editor-title = Alt text editor\npdfjs-editor-alt-text-settings-show-dialog-button-label = Show alt text editor right away when adding an image\npdfjs-editor-alt-text-settings-show-dialog-description = Helps you make sure all your images have alt text.\npdfjs-editor-alt-text-settings-close-button = Close\npdfjs-editor-undo-bar-message-highlight = Highlight removed\npdfjs-editor-undo-bar-message-freetext = Text removed\npdfjs-editor-undo-bar-message-ink = Drawing removed\npdfjs-editor-undo-bar-message-stamp = Image removed\npdfjs-editor-undo-bar-message-multiple =\n { $count ->\n [one] { $count } annotation removed\n *[other] { $count } annotations removed\n }\npdfjs-editor-undo-bar-undo-button =\n .title = Undo\npdfjs-editor-undo-bar-undo-button-label = Undo\npdfjs-editor-undo-bar-close-button =\n .title = Close\npdfjs-editor-undo-bar-close-button-label = Close";
  3519. return createBundle(lang, text);
  3520. }
  3521. }
  3522. ;// ./web/pdf_history.js
  3523. const HASH_CHANGE_TIMEOUT = 1000;
  3524. const POSITION_UPDATED_THRESHOLD = 50;
  3525. const UPDATE_VIEWAREA_TIMEOUT = 1000;
  3526. function getCurrentHash() {
  3527. return document.location.hash;
  3528. }
  3529. class PDFHistory {
  3530. #eventAbortController = null;
  3531. constructor({
  3532. linkService,
  3533. eventBus
  3534. }) {
  3535. this.linkService = linkService;
  3536. this.eventBus = eventBus;
  3537. this._initialized = false;
  3538. this._fingerprint = "";
  3539. this.reset();
  3540. this.eventBus._on("pagesinit", () => {
  3541. this._isPagesLoaded = false;
  3542. this.eventBus._on("pagesloaded", evt => {
  3543. this._isPagesLoaded = !!evt.pagesCount;
  3544. }, {
  3545. once: true
  3546. });
  3547. });
  3548. }
  3549. initialize({
  3550. fingerprint,
  3551. resetHistory = false,
  3552. updateUrl = false
  3553. }) {
  3554. if (!fingerprint || typeof fingerprint !== "string") {
  3555. console.error('PDFHistory.initialize: The "fingerprint" must be a non-empty string.');
  3556. return;
  3557. }
  3558. if (this._initialized) {
  3559. this.reset();
  3560. }
  3561. const reInitialized = this._fingerprint !== "" && this._fingerprint !== fingerprint;
  3562. this._fingerprint = fingerprint;
  3563. this._updateUrl = updateUrl === true;
  3564. this._initialized = true;
  3565. this.#bindEvents();
  3566. const state = window.history.state;
  3567. this._popStateInProgress = false;
  3568. this._blockHashChange = 0;
  3569. this._currentHash = getCurrentHash();
  3570. this._numPositionUpdates = 0;
  3571. this._uid = this._maxUid = 0;
  3572. this._destination = null;
  3573. this._position = null;
  3574. if (!this.#isValidState(state, true) || resetHistory) {
  3575. const {
  3576. hash,
  3577. page,
  3578. rotation
  3579. } = this.#parseCurrentHash(true);
  3580. if (!hash || reInitialized || resetHistory) {
  3581. this.#pushOrReplaceState(null, true);
  3582. return;
  3583. }
  3584. this.#pushOrReplaceState({
  3585. hash,
  3586. page,
  3587. rotation
  3588. }, true);
  3589. return;
  3590. }
  3591. const destination = state.destination;
  3592. this.#updateInternalState(destination, state.uid, true);
  3593. if (destination.rotation !== undefined) {
  3594. this._initialRotation = destination.rotation;
  3595. }
  3596. if (destination.dest) {
  3597. this._initialBookmark = JSON.stringify(destination.dest);
  3598. this._destination.page = null;
  3599. } else if (destination.hash) {
  3600. this._initialBookmark = destination.hash;
  3601. } else if (destination.page) {
  3602. this._initialBookmark = `page=${destination.page}`;
  3603. }
  3604. }
  3605. reset() {
  3606. if (this._initialized) {
  3607. this.#pageHide();
  3608. this._initialized = false;
  3609. this.#unbindEvents();
  3610. }
  3611. if (this._updateViewareaTimeout) {
  3612. clearTimeout(this._updateViewareaTimeout);
  3613. this._updateViewareaTimeout = null;
  3614. }
  3615. this._initialBookmark = null;
  3616. this._initialRotation = null;
  3617. }
  3618. push({
  3619. namedDest = null,
  3620. explicitDest,
  3621. pageNumber
  3622. }) {
  3623. if (!this._initialized) {
  3624. return;
  3625. }
  3626. if (namedDest && typeof namedDest !== "string") {
  3627. console.error("PDFHistory.push: " + `"${namedDest}" is not a valid namedDest parameter.`);
  3628. return;
  3629. } else if (!Array.isArray(explicitDest)) {
  3630. console.error("PDFHistory.push: " + `"${explicitDest}" is not a valid explicitDest parameter.`);
  3631. return;
  3632. } else if (!this.#isValidPage(pageNumber)) {
  3633. if (pageNumber !== null || this._destination) {
  3634. console.error("PDFHistory.push: " + `"${pageNumber}" is not a valid pageNumber parameter.`);
  3635. return;
  3636. }
  3637. }
  3638. const hash = namedDest || JSON.stringify(explicitDest);
  3639. if (!hash) {
  3640. return;
  3641. }
  3642. let forceReplace = false;
  3643. if (this._destination && (isDestHashesEqual(this._destination.hash, hash) || isDestArraysEqual(this._destination.dest, explicitDest))) {
  3644. if (this._destination.page) {
  3645. return;
  3646. }
  3647. forceReplace = true;
  3648. }
  3649. if (this._popStateInProgress && !forceReplace) {
  3650. return;
  3651. }
  3652. this.#pushOrReplaceState({
  3653. dest: explicitDest,
  3654. hash,
  3655. page: pageNumber,
  3656. rotation: this.linkService.rotation
  3657. }, forceReplace);
  3658. if (!this._popStateInProgress) {
  3659. this._popStateInProgress = true;
  3660. Promise.resolve().then(() => {
  3661. this._popStateInProgress = false;
  3662. });
  3663. }
  3664. }
  3665. pushPage(pageNumber) {
  3666. if (!this._initialized) {
  3667. return;
  3668. }
  3669. if (!this.#isValidPage(pageNumber)) {
  3670. console.error(`PDFHistory.pushPage: "${pageNumber}" is not a valid page number.`);
  3671. return;
  3672. }
  3673. if (this._destination?.page === pageNumber) {
  3674. return;
  3675. }
  3676. if (this._popStateInProgress) {
  3677. return;
  3678. }
  3679. this.#pushOrReplaceState({
  3680. dest: null,
  3681. hash: `page=${pageNumber}`,
  3682. page: pageNumber,
  3683. rotation: this.linkService.rotation
  3684. });
  3685. if (!this._popStateInProgress) {
  3686. this._popStateInProgress = true;
  3687. Promise.resolve().then(() => {
  3688. this._popStateInProgress = false;
  3689. });
  3690. }
  3691. }
  3692. pushCurrentPosition() {
  3693. if (!this._initialized || this._popStateInProgress) {
  3694. return;
  3695. }
  3696. this.#tryPushCurrentPosition();
  3697. }
  3698. back() {
  3699. if (!this._initialized || this._popStateInProgress) {
  3700. return;
  3701. }
  3702. const state = window.history.state;
  3703. if (this.#isValidState(state) && state.uid > 0) {
  3704. window.history.back();
  3705. }
  3706. }
  3707. forward() {
  3708. if (!this._initialized || this._popStateInProgress) {
  3709. return;
  3710. }
  3711. const state = window.history.state;
  3712. if (this.#isValidState(state) && state.uid < this._maxUid) {
  3713. window.history.forward();
  3714. }
  3715. }
  3716. get popStateInProgress() {
  3717. return this._initialized && (this._popStateInProgress || this._blockHashChange > 0);
  3718. }
  3719. get initialBookmark() {
  3720. return this._initialized ? this._initialBookmark : null;
  3721. }
  3722. get initialRotation() {
  3723. return this._initialized ? this._initialRotation : null;
  3724. }
  3725. #pushOrReplaceState(destination, forceReplace = false) {
  3726. const shouldReplace = forceReplace || !this._destination;
  3727. const newState = {
  3728. fingerprint: this._fingerprint,
  3729. uid: shouldReplace ? this._uid : this._uid + 1,
  3730. destination
  3731. };
  3732. this.#updateInternalState(destination, newState.uid);
  3733. let newUrl;
  3734. if (this._updateUrl && destination?.hash) {
  3735. const baseUrl = document.location.href.split("#", 1)[0];
  3736. if (!baseUrl.startsWith("file://")) {
  3737. newUrl = `${baseUrl}#${destination.hash}`;
  3738. }
  3739. }
  3740. if (shouldReplace) {
  3741. window.history.replaceState(newState, "", newUrl);
  3742. } else {
  3743. window.history.pushState(newState, "", newUrl);
  3744. }
  3745. }
  3746. #tryPushCurrentPosition(temporary = false) {
  3747. if (!this._position) {
  3748. return;
  3749. }
  3750. let position = this._position;
  3751. if (temporary) {
  3752. position = Object.assign(Object.create(null), this._position);
  3753. position.temporary = true;
  3754. }
  3755. if (!this._destination) {
  3756. this.#pushOrReplaceState(position);
  3757. return;
  3758. }
  3759. if (this._destination.temporary) {
  3760. this.#pushOrReplaceState(position, true);
  3761. return;
  3762. }
  3763. if (this._destination.hash === position.hash) {
  3764. return;
  3765. }
  3766. if (!this._destination.page && (POSITION_UPDATED_THRESHOLD <= 0 || this._numPositionUpdates <= POSITION_UPDATED_THRESHOLD)) {
  3767. return;
  3768. }
  3769. let forceReplace = false;
  3770. if (this._destination.page >= position.first && this._destination.page <= position.page) {
  3771. if (this._destination.dest !== undefined || !this._destination.first) {
  3772. return;
  3773. }
  3774. forceReplace = true;
  3775. }
  3776. this.#pushOrReplaceState(position, forceReplace);
  3777. }
  3778. #isValidPage(val) {
  3779. return Number.isInteger(val) && val > 0 && val <= this.linkService.pagesCount;
  3780. }
  3781. #isValidState(state, checkReload = false) {
  3782. if (!state) {
  3783. return false;
  3784. }
  3785. if (state.fingerprint !== this._fingerprint) {
  3786. if (checkReload) {
  3787. if (typeof state.fingerprint !== "string" || state.fingerprint.length !== this._fingerprint.length) {
  3788. return false;
  3789. }
  3790. const [perfEntry] = performance.getEntriesByType("navigation");
  3791. if (perfEntry?.type !== "reload") {
  3792. return false;
  3793. }
  3794. } else {
  3795. return false;
  3796. }
  3797. }
  3798. if (!Number.isInteger(state.uid) || state.uid < 0) {
  3799. return false;
  3800. }
  3801. if (state.destination === null || typeof state.destination !== "object") {
  3802. return false;
  3803. }
  3804. return true;
  3805. }
  3806. #updateInternalState(destination, uid, removeTemporary = false) {
  3807. if (this._updateViewareaTimeout) {
  3808. clearTimeout(this._updateViewareaTimeout);
  3809. this._updateViewareaTimeout = null;
  3810. }
  3811. if (removeTemporary && destination?.temporary) {
  3812. delete destination.temporary;
  3813. }
  3814. this._destination = destination;
  3815. this._uid = uid;
  3816. this._maxUid = Math.max(this._maxUid, uid);
  3817. this._numPositionUpdates = 0;
  3818. }
  3819. #parseCurrentHash(checkNameddest = false) {
  3820. const hash = unescape(getCurrentHash()).substring(1);
  3821. const params = parseQueryString(hash);
  3822. const nameddest = params.get("nameddest") || "";
  3823. let page = params.get("page") | 0;
  3824. if (!this.#isValidPage(page) || checkNameddest && nameddest.length > 0) {
  3825. page = null;
  3826. }
  3827. return {
  3828. hash,
  3829. page,
  3830. rotation: this.linkService.rotation
  3831. };
  3832. }
  3833. #updateViewarea({
  3834. location
  3835. }) {
  3836. if (this._updateViewareaTimeout) {
  3837. clearTimeout(this._updateViewareaTimeout);
  3838. this._updateViewareaTimeout = null;
  3839. }
  3840. this._position = {
  3841. hash: location.pdfOpenParams.substring(1),
  3842. page: this.linkService.page,
  3843. first: location.pageNumber,
  3844. rotation: location.rotation
  3845. };
  3846. if (this._popStateInProgress) {
  3847. return;
  3848. }
  3849. if (POSITION_UPDATED_THRESHOLD > 0 && this._isPagesLoaded && this._destination && !this._destination.page) {
  3850. this._numPositionUpdates++;
  3851. }
  3852. if (UPDATE_VIEWAREA_TIMEOUT > 0) {
  3853. this._updateViewareaTimeout = setTimeout(() => {
  3854. if (!this._popStateInProgress) {
  3855. this.#tryPushCurrentPosition(true);
  3856. }
  3857. this._updateViewareaTimeout = null;
  3858. }, UPDATE_VIEWAREA_TIMEOUT);
  3859. }
  3860. }
  3861. #popState({
  3862. state
  3863. }) {
  3864. const newHash = getCurrentHash(),
  3865. hashChanged = this._currentHash !== newHash;
  3866. this._currentHash = newHash;
  3867. if (!state) {
  3868. this._uid++;
  3869. const {
  3870. hash,
  3871. page,
  3872. rotation
  3873. } = this.#parseCurrentHash();
  3874. this.#pushOrReplaceState({
  3875. hash,
  3876. page,
  3877. rotation
  3878. }, true);
  3879. return;
  3880. }
  3881. if (!this.#isValidState(state)) {
  3882. return;
  3883. }
  3884. this._popStateInProgress = true;
  3885. if (hashChanged) {
  3886. this._blockHashChange++;
  3887. waitOnEventOrTimeout({
  3888. target: window,
  3889. name: "hashchange",
  3890. delay: HASH_CHANGE_TIMEOUT
  3891. }).then(() => {
  3892. this._blockHashChange--;
  3893. });
  3894. }
  3895. const destination = state.destination;
  3896. this.#updateInternalState(destination, state.uid, true);
  3897. if (isValidRotation(destination.rotation)) {
  3898. this.linkService.rotation = destination.rotation;
  3899. }
  3900. if (destination.dest) {
  3901. this.linkService.goToDestination(destination.dest);
  3902. } else if (destination.hash) {
  3903. this.linkService.setHash(destination.hash);
  3904. } else if (destination.page) {
  3905. this.linkService.page = destination.page;
  3906. }
  3907. Promise.resolve().then(() => {
  3908. this._popStateInProgress = false;
  3909. });
  3910. }
  3911. #pageHide() {
  3912. if (!this._destination || this._destination.temporary) {
  3913. this.#tryPushCurrentPosition();
  3914. }
  3915. }
  3916. #bindEvents() {
  3917. if (this.#eventAbortController) {
  3918. return;
  3919. }
  3920. this.#eventAbortController = new AbortController();
  3921. const {
  3922. signal
  3923. } = this.#eventAbortController;
  3924. this.eventBus._on("updateviewarea", this.#updateViewarea.bind(this), {
  3925. signal
  3926. });
  3927. window.addEventListener("popstate", this.#popState.bind(this), {
  3928. signal
  3929. });
  3930. window.addEventListener("pagehide", this.#pageHide.bind(this), {
  3931. signal
  3932. });
  3933. }
  3934. #unbindEvents() {
  3935. this.#eventAbortController?.abort();
  3936. this.#eventAbortController = null;
  3937. }
  3938. }
  3939. function isDestHashesEqual(destHash, pushHash) {
  3940. if (typeof destHash !== "string" || typeof pushHash !== "string") {
  3941. return false;
  3942. }
  3943. if (destHash === pushHash) {
  3944. return true;
  3945. }
  3946. const nameddest = parseQueryString(destHash).get("nameddest");
  3947. if (nameddest === pushHash) {
  3948. return true;
  3949. }
  3950. return false;
  3951. }
  3952. function isDestArraysEqual(firstDest, secondDest) {
  3953. function isEntryEqual(first, second) {
  3954. if (typeof first !== typeof second) {
  3955. return false;
  3956. }
  3957. if (Array.isArray(first) || Array.isArray(second)) {
  3958. return false;
  3959. }
  3960. if (first !== null && typeof first === "object" && second !== null) {
  3961. if (Object.keys(first).length !== Object.keys(second).length) {
  3962. return false;
  3963. }
  3964. for (const key in first) {
  3965. if (!isEntryEqual(first[key], second[key])) {
  3966. return false;
  3967. }
  3968. }
  3969. return true;
  3970. }
  3971. return first === second || Number.isNaN(first) && Number.isNaN(second);
  3972. }
  3973. if (!(Array.isArray(firstDest) && Array.isArray(secondDest))) {
  3974. return false;
  3975. }
  3976. if (firstDest.length !== secondDest.length) {
  3977. return false;
  3978. }
  3979. for (let i = 0, ii = firstDest.length; i < ii; i++) {
  3980. if (!isEntryEqual(firstDest[i], secondDest[i])) {
  3981. return false;
  3982. }
  3983. }
  3984. return true;
  3985. }
  3986. ;// ./web/annotation_editor_layer_builder.js
  3987. class AnnotationEditorLayerBuilder {
  3988. #annotationLayer = null;
  3989. #drawLayer = null;
  3990. #onAppend = null;
  3991. #structTreeLayer = null;
  3992. #textLayer = null;
  3993. #uiManager;
  3994. constructor(options) {
  3995. this.pdfPage = options.pdfPage;
  3996. this.accessibilityManager = options.accessibilityManager;
  3997. this.l10n = options.l10n;
  3998. this.l10n ||= new genericl10n_GenericL10n();
  3999. this.annotationEditorLayer = null;
  4000. this.div = null;
  4001. this._cancelled = false;
  4002. this.#uiManager = options.uiManager;
  4003. this.#annotationLayer = options.annotationLayer || null;
  4004. this.#textLayer = options.textLayer || null;
  4005. this.#drawLayer = options.drawLayer || null;
  4006. this.#onAppend = options.onAppend || null;
  4007. this.#structTreeLayer = options.structTreeLayer || null;
  4008. }
  4009. async render(viewport, intent = "display") {
  4010. if (intent !== "display") {
  4011. return;
  4012. }
  4013. if (this._cancelled) {
  4014. return;
  4015. }
  4016. const clonedViewport = viewport.clone({
  4017. dontFlip: true
  4018. });
  4019. if (this.div) {
  4020. this.annotationEditorLayer.update({
  4021. viewport: clonedViewport
  4022. });
  4023. this.show();
  4024. return;
  4025. }
  4026. const div = this.div = document.createElement("div");
  4027. div.className = "annotationEditorLayer";
  4028. div.hidden = true;
  4029. div.dir = this.#uiManager.direction;
  4030. this.#onAppend?.(div);
  4031. this.annotationEditorLayer = new AnnotationEditorLayer({
  4032. uiManager: this.#uiManager,
  4033. div,
  4034. structTreeLayer: this.#structTreeLayer,
  4035. accessibilityManager: this.accessibilityManager,
  4036. pageIndex: this.pdfPage.pageNumber - 1,
  4037. l10n: this.l10n,
  4038. viewport: clonedViewport,
  4039. annotationLayer: this.#annotationLayer,
  4040. textLayer: this.#textLayer,
  4041. drawLayer: this.#drawLayer
  4042. });
  4043. const parameters = {
  4044. viewport: clonedViewport,
  4045. div,
  4046. annotations: null,
  4047. intent
  4048. };
  4049. this.annotationEditorLayer.render(parameters);
  4050. this.show();
  4051. }
  4052. cancel() {
  4053. this._cancelled = true;
  4054. if (!this.div) {
  4055. return;
  4056. }
  4057. this.annotationEditorLayer.destroy();
  4058. }
  4059. hide() {
  4060. if (!this.div) {
  4061. return;
  4062. }
  4063. this.annotationEditorLayer.pause(true);
  4064. this.div.hidden = true;
  4065. }
  4066. show() {
  4067. if (!this.div || this.annotationEditorLayer.isInvisible) {
  4068. return;
  4069. }
  4070. this.div.hidden = false;
  4071. this.annotationEditorLayer.pause(false);
  4072. }
  4073. }
  4074. ;// ./web/app_options.js
  4075. {
  4076. var compatParams = new Map();
  4077. const userAgent = navigator.userAgent || "";
  4078. const platform = navigator.platform || "";
  4079. const maxTouchPoints = navigator.maxTouchPoints || 1;
  4080. const isAndroid = /Android/.test(userAgent);
  4081. const isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent) || platform === "MacIntel" && maxTouchPoints > 1;
  4082. (function () {
  4083. if (isIOS || isAndroid) {
  4084. compatParams.set("maxCanvasPixels", 5242880);
  4085. }
  4086. })();
  4087. (function () {
  4088. if (isAndroid) {
  4089. compatParams.set("useSystemFonts", false);
  4090. }
  4091. })();
  4092. }
  4093. const OptionKind = {
  4094. BROWSER: 0x01,
  4095. VIEWER: 0x02,
  4096. API: 0x04,
  4097. WORKER: 0x08,
  4098. EVENT_DISPATCH: 0x10,
  4099. PREFERENCE: 0x80
  4100. };
  4101. const Type = {
  4102. BOOLEAN: 0x01,
  4103. NUMBER: 0x02,
  4104. OBJECT: 0x04,
  4105. STRING: 0x08,
  4106. UNDEFINED: 0x10
  4107. };
  4108. const defaultOptions = {
  4109. allowedGlobalEvents: {
  4110. value: null,
  4111. kind: OptionKind.BROWSER
  4112. },
  4113. canvasMaxAreaInBytes: {
  4114. value: -1,
  4115. kind: OptionKind.BROWSER + OptionKind.API
  4116. },
  4117. isInAutomation: {
  4118. value: false,
  4119. kind: OptionKind.BROWSER
  4120. },
  4121. localeProperties: {
  4122. value: {
  4123. lang: navigator.language || "en-US"
  4124. },
  4125. kind: OptionKind.BROWSER
  4126. },
  4127. nimbusDataStr: {
  4128. value: "",
  4129. kind: OptionKind.BROWSER
  4130. },
  4131. supportsCaretBrowsingMode: {
  4132. value: false,
  4133. kind: OptionKind.BROWSER
  4134. },
  4135. supportsDocumentFonts: {
  4136. value: true,
  4137. kind: OptionKind.BROWSER
  4138. },
  4139. supportsIntegratedFind: {
  4140. value: false,
  4141. kind: OptionKind.BROWSER
  4142. },
  4143. supportsMouseWheelZoomCtrlKey: {
  4144. value: true,
  4145. kind: OptionKind.BROWSER
  4146. },
  4147. supportsMouseWheelZoomMetaKey: {
  4148. value: true,
  4149. kind: OptionKind.BROWSER
  4150. },
  4151. supportsPinchToZoom: {
  4152. value: true,
  4153. kind: OptionKind.BROWSER
  4154. },
  4155. toolbarDensity: {
  4156. value: 0,
  4157. kind: OptionKind.BROWSER + OptionKind.EVENT_DISPATCH
  4158. },
  4159. altTextLearnMoreUrl: {
  4160. value: "",
  4161. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4162. },
  4163. annotationEditorMode: {
  4164. value: 0,
  4165. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4166. },
  4167. annotationMode: {
  4168. value: 2,
  4169. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4170. },
  4171. cursorToolOnLoad: {
  4172. value: 0,
  4173. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4174. },
  4175. debuggerSrc: {
  4176. value: "./debugger.mjs",
  4177. kind: OptionKind.VIEWER
  4178. },
  4179. defaultZoomDelay: {
  4180. value: 400,
  4181. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4182. },
  4183. defaultZoomValue: {
  4184. value: "",
  4185. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4186. },
  4187. disableHistory: {
  4188. value: false,
  4189. kind: OptionKind.VIEWER
  4190. },
  4191. disablePageLabels: {
  4192. value: false,
  4193. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4194. },
  4195. enableAltText: {
  4196. value: false,
  4197. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4198. },
  4199. enableAltTextModelDownload: {
  4200. value: true,
  4201. kind: OptionKind.VIEWER + OptionKind.PREFERENCE + OptionKind.EVENT_DISPATCH
  4202. },
  4203. enableGuessAltText: {
  4204. value: true,
  4205. kind: OptionKind.VIEWER + OptionKind.PREFERENCE + OptionKind.EVENT_DISPATCH
  4206. },
  4207. enableHighlightFloatingButton: {
  4208. value: false,
  4209. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4210. },
  4211. enableNewAltTextWhenAddingImage: {
  4212. value: true,
  4213. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4214. },
  4215. enablePermissions: {
  4216. value: false,
  4217. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4218. },
  4219. enablePrintAutoRotate: {
  4220. value: true,
  4221. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4222. },
  4223. enableScripting: {
  4224. value: true,
  4225. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4226. },
  4227. enableUpdatedAddImage: {
  4228. value: false,
  4229. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4230. },
  4231. externalLinkRel: {
  4232. value: "noopener noreferrer nofollow",
  4233. kind: OptionKind.VIEWER
  4234. },
  4235. externalLinkTarget: {
  4236. value: 0,
  4237. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4238. },
  4239. highlightEditorColors: {
  4240. value: "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F",
  4241. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4242. },
  4243. historyUpdateUrl: {
  4244. value: false,
  4245. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4246. },
  4247. ignoreDestinationZoom: {
  4248. value: false,
  4249. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4250. },
  4251. imageResourcesPath: {
  4252. value: "./images/",
  4253. kind: OptionKind.VIEWER
  4254. },
  4255. maxCanvasPixels: {
  4256. value: 2 ** 25,
  4257. kind: OptionKind.VIEWER
  4258. },
  4259. forcePageColors: {
  4260. value: false,
  4261. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4262. },
  4263. pageColorsBackground: {
  4264. value: "Canvas",
  4265. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4266. },
  4267. pageColorsForeground: {
  4268. value: "CanvasText",
  4269. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4270. },
  4271. pdfBugEnabled: {
  4272. value: false,
  4273. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4274. },
  4275. printResolution: {
  4276. value: 150,
  4277. kind: OptionKind.VIEWER
  4278. },
  4279. sidebarViewOnLoad: {
  4280. value: -1,
  4281. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4282. },
  4283. scrollModeOnLoad: {
  4284. value: -1,
  4285. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4286. },
  4287. spreadModeOnLoad: {
  4288. value: -1,
  4289. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4290. },
  4291. textLayerMode: {
  4292. value: 1,
  4293. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4294. },
  4295. viewOnLoad: {
  4296. value: 0,
  4297. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4298. },
  4299. cMapPacked: {
  4300. value: true,
  4301. kind: OptionKind.API
  4302. },
  4303. cMapUrl: {
  4304. value: "../web/cmaps/",
  4305. kind: OptionKind.API
  4306. },
  4307. disableAutoFetch: {
  4308. value: false,
  4309. kind: OptionKind.API + OptionKind.PREFERENCE
  4310. },
  4311. disableFontFace: {
  4312. value: false,
  4313. kind: OptionKind.API + OptionKind.PREFERENCE
  4314. },
  4315. disableRange: {
  4316. value: false,
  4317. kind: OptionKind.API + OptionKind.PREFERENCE
  4318. },
  4319. disableStream: {
  4320. value: false,
  4321. kind: OptionKind.API + OptionKind.PREFERENCE
  4322. },
  4323. docBaseUrl: {
  4324. value: "",
  4325. kind: OptionKind.API
  4326. },
  4327. enableHWA: {
  4328. value: true,
  4329. kind: OptionKind.API + OptionKind.VIEWER + OptionKind.PREFERENCE
  4330. },
  4331. enableXfa: {
  4332. value: true,
  4333. kind: OptionKind.API + OptionKind.PREFERENCE
  4334. },
  4335. fontExtraProperties: {
  4336. value: false,
  4337. kind: OptionKind.API
  4338. },
  4339. isEvalSupported: {
  4340. value: true,
  4341. kind: OptionKind.API
  4342. },
  4343. isOffscreenCanvasSupported: {
  4344. value: true,
  4345. kind: OptionKind.API
  4346. },
  4347. maxImageSize: {
  4348. value: -1,
  4349. kind: OptionKind.API
  4350. },
  4351. pdfBug: {
  4352. value: false,
  4353. kind: OptionKind.API
  4354. },
  4355. standardFontDataUrl: {
  4356. value: "../web/standard_fonts/",
  4357. kind: OptionKind.API
  4358. },
  4359. useSystemFonts: {
  4360. value: undefined,
  4361. kind: OptionKind.API,
  4362. type: Type.BOOLEAN + Type.UNDEFINED
  4363. },
  4364. verbosity: {
  4365. value: 1,
  4366. kind: OptionKind.API
  4367. },
  4368. workerPort: {
  4369. value: null,
  4370. kind: OptionKind.WORKER
  4371. },
  4372. workerSrc: {
  4373. value: "../build/pdf.worker.mjs",
  4374. kind: OptionKind.WORKER
  4375. }
  4376. };
  4377. {
  4378. defaultOptions.defaultUrl = {
  4379. value: "compressed.tracemonkey-pldi-09.pdf",
  4380. kind: OptionKind.VIEWER
  4381. };
  4382. defaultOptions.sandboxBundleSrc = {
  4383. value: "../build/pdf.sandbox.mjs",
  4384. kind: OptionKind.VIEWER
  4385. };
  4386. defaultOptions.viewerCssTheme = {
  4387. value: 0,
  4388. kind: OptionKind.VIEWER + OptionKind.PREFERENCE
  4389. };
  4390. defaultOptions.enableFakeMLManager = {
  4391. value: true,
  4392. kind: OptionKind.VIEWER
  4393. };
  4394. }
  4395. {
  4396. defaultOptions.disablePreferences = {
  4397. value: false,
  4398. kind: OptionKind.VIEWER
  4399. };
  4400. }
  4401. class AppOptions {
  4402. static eventBus;
  4403. static #opts = new Map();
  4404. static {
  4405. for (const name in defaultOptions) {
  4406. this.#opts.set(name, defaultOptions[name].value);
  4407. }
  4408. for (const [name, value] of compatParams) {
  4409. this.#opts.set(name, value);
  4410. }
  4411. this._hasInvokedSet = false;
  4412. this._checkDisablePreferences = () => {
  4413. if (this.get("disablePreferences")) {
  4414. return true;
  4415. }
  4416. if (this._hasInvokedSet) {
  4417. console.warn("The Preferences may override manually set AppOptions; " + 'please use the "disablePreferences"-option to prevent that.');
  4418. }
  4419. return false;
  4420. };
  4421. }
  4422. static get(name) {
  4423. return this.#opts.get(name);
  4424. }
  4425. static getAll(kind = null, defaultOnly = false) {
  4426. const options = Object.create(null);
  4427. for (const name in defaultOptions) {
  4428. const defaultOpt = defaultOptions[name];
  4429. if (kind && !(kind & defaultOpt.kind)) {
  4430. continue;
  4431. }
  4432. options[name] = !defaultOnly ? this.#opts.get(name) : defaultOpt.value;
  4433. }
  4434. return options;
  4435. }
  4436. static set(name, value) {
  4437. this.setAll({
  4438. [name]: value
  4439. });
  4440. }
  4441. static setAll(options, prefs = false) {
  4442. this._hasInvokedSet ||= true;
  4443. let events;
  4444. for (const name in options) {
  4445. const defaultOpt = defaultOptions[name],
  4446. userOpt = options[name];
  4447. if (!defaultOpt || !(typeof userOpt === typeof defaultOpt.value || Type[(typeof userOpt).toUpperCase()] & defaultOpt.type)) {
  4448. continue;
  4449. }
  4450. const {
  4451. kind
  4452. } = defaultOpt;
  4453. if (prefs && !(kind & OptionKind.BROWSER || kind & OptionKind.PREFERENCE)) {
  4454. continue;
  4455. }
  4456. if (this.eventBus && kind & OptionKind.EVENT_DISPATCH) {
  4457. (events ||= new Map()).set(name, userOpt);
  4458. }
  4459. this.#opts.set(name, userOpt);
  4460. }
  4461. if (events) {
  4462. for (const [name, value] of events) {
  4463. this.eventBus.dispatch(name.toLowerCase(), {
  4464. source: this,
  4465. value
  4466. });
  4467. }
  4468. }
  4469. }
  4470. }
  4471. ;// ./web/draw_layer_builder.js
  4472. class DrawLayerBuilder {
  4473. #drawLayer = null;
  4474. constructor(options) {
  4475. this.pageIndex = options.pageIndex;
  4476. }
  4477. async render(intent = "display") {
  4478. if (intent !== "display" || this.#drawLayer || this._cancelled) {
  4479. return;
  4480. }
  4481. this.#drawLayer = new DrawLayer({
  4482. pageIndex: this.pageIndex
  4483. });
  4484. }
  4485. cancel() {
  4486. this._cancelled = true;
  4487. if (!this.#drawLayer) {
  4488. return;
  4489. }
  4490. this.#drawLayer.destroy();
  4491. this.#drawLayer = null;
  4492. }
  4493. setParent(parent) {
  4494. this.#drawLayer?.setParent(parent);
  4495. }
  4496. getDrawLayer() {
  4497. return this.#drawLayer;
  4498. }
  4499. }
  4500. ;// ./web/struct_tree_layer_builder.js
  4501. const PDF_ROLE_TO_HTML_ROLE = {
  4502. Document: null,
  4503. DocumentFragment: null,
  4504. Part: "group",
  4505. Sect: "group",
  4506. Div: "group",
  4507. Aside: "note",
  4508. NonStruct: "none",
  4509. P: null,
  4510. H: "heading",
  4511. Title: null,
  4512. FENote: "note",
  4513. Sub: "group",
  4514. Lbl: null,
  4515. Span: null,
  4516. Em: null,
  4517. Strong: null,
  4518. Link: "link",
  4519. Annot: "note",
  4520. Form: "form",
  4521. Ruby: null,
  4522. RB: null,
  4523. RT: null,
  4524. RP: null,
  4525. Warichu: null,
  4526. WT: null,
  4527. WP: null,
  4528. L: "list",
  4529. LI: "listitem",
  4530. LBody: null,
  4531. Table: "table",
  4532. TR: "row",
  4533. TH: "columnheader",
  4534. TD: "cell",
  4535. THead: "columnheader",
  4536. TBody: null,
  4537. TFoot: null,
  4538. Caption: null,
  4539. Figure: "figure",
  4540. Formula: null,
  4541. Artifact: null
  4542. };
  4543. const HEADING_PATTERN = /^H(\d+)$/;
  4544. class StructTreeLayerBuilder {
  4545. #promise;
  4546. #treeDom = null;
  4547. #treePromise;
  4548. #elementAttributes = new Map();
  4549. #rawDims;
  4550. #elementsToAddToTextLayer = null;
  4551. constructor(pdfPage, rawDims) {
  4552. this.#promise = pdfPage.getStructTree();
  4553. this.#rawDims = rawDims;
  4554. }
  4555. async render() {
  4556. if (this.#treePromise) {
  4557. return this.#treePromise;
  4558. }
  4559. const {
  4560. promise,
  4561. resolve,
  4562. reject
  4563. } = Promise.withResolvers();
  4564. this.#treePromise = promise;
  4565. try {
  4566. this.#treeDom = this.#walk(await this.#promise);
  4567. } catch (ex) {
  4568. reject(ex);
  4569. }
  4570. this.#promise = null;
  4571. this.#treeDom?.classList.add("structTree");
  4572. resolve(this.#treeDom);
  4573. return promise;
  4574. }
  4575. async getAriaAttributes(annotationId) {
  4576. try {
  4577. await this.render();
  4578. return this.#elementAttributes.get(annotationId);
  4579. } catch {}
  4580. return null;
  4581. }
  4582. hide() {
  4583. if (this.#treeDom && !this.#treeDom.hidden) {
  4584. this.#treeDom.hidden = true;
  4585. }
  4586. }
  4587. show() {
  4588. if (this.#treeDom?.hidden) {
  4589. this.#treeDom.hidden = false;
  4590. }
  4591. }
  4592. #setAttributes(structElement, htmlElement) {
  4593. const {
  4594. alt,
  4595. id,
  4596. lang
  4597. } = structElement;
  4598. if (alt !== undefined) {
  4599. let added = false;
  4600. const label = removeNullCharacters(alt);
  4601. for (const child of structElement.children) {
  4602. if (child.type === "annotation") {
  4603. let attrs = this.#elementAttributes.get(child.id);
  4604. if (!attrs) {
  4605. attrs = new Map();
  4606. this.#elementAttributes.set(child.id, attrs);
  4607. }
  4608. attrs.set("aria-label", label);
  4609. added = true;
  4610. }
  4611. }
  4612. if (!added) {
  4613. htmlElement.setAttribute("aria-label", label);
  4614. }
  4615. }
  4616. if (id !== undefined) {
  4617. htmlElement.setAttribute("aria-owns", id);
  4618. }
  4619. if (lang !== undefined) {
  4620. htmlElement.setAttribute("lang", removeNullCharacters(lang, true));
  4621. }
  4622. }
  4623. #addImageInTextLayer(node, element) {
  4624. const {
  4625. alt,
  4626. bbox,
  4627. children
  4628. } = node;
  4629. const child = children?.[0];
  4630. if (!this.#rawDims || !alt || !bbox || child?.type !== "content") {
  4631. return false;
  4632. }
  4633. const {
  4634. id
  4635. } = child;
  4636. if (!id) {
  4637. return false;
  4638. }
  4639. element.setAttribute("aria-owns", id);
  4640. const img = document.createElement("span");
  4641. (this.#elementsToAddToTextLayer ||= new Map()).set(id, img);
  4642. img.setAttribute("role", "img");
  4643. img.setAttribute("aria-label", removeNullCharacters(alt));
  4644. const {
  4645. pageHeight,
  4646. pageX,
  4647. pageY
  4648. } = this.#rawDims;
  4649. const calc = "calc(var(--scale-factor)*";
  4650. const {
  4651. style
  4652. } = img;
  4653. style.width = `${calc}${bbox[2] - bbox[0]}px)`;
  4654. style.height = `${calc}${bbox[3] - bbox[1]}px)`;
  4655. style.left = `${calc}${bbox[0] - pageX}px)`;
  4656. style.top = `${calc}${pageHeight - bbox[3] + pageY}px)`;
  4657. return true;
  4658. }
  4659. addElementsToTextLayer() {
  4660. if (!this.#elementsToAddToTextLayer) {
  4661. return;
  4662. }
  4663. for (const [id, img] of this.#elementsToAddToTextLayer) {
  4664. document.getElementById(id)?.append(img);
  4665. }
  4666. this.#elementsToAddToTextLayer.clear();
  4667. this.#elementsToAddToTextLayer = null;
  4668. }
  4669. #walk(node) {
  4670. if (!node) {
  4671. return null;
  4672. }
  4673. const element = document.createElement("span");
  4674. if ("role" in node) {
  4675. const {
  4676. role
  4677. } = node;
  4678. const match = role.match(HEADING_PATTERN);
  4679. if (match) {
  4680. element.setAttribute("role", "heading");
  4681. element.setAttribute("aria-level", match[1]);
  4682. } else if (PDF_ROLE_TO_HTML_ROLE[role]) {
  4683. element.setAttribute("role", PDF_ROLE_TO_HTML_ROLE[role]);
  4684. }
  4685. if (role === "Figure" && this.#addImageInTextLayer(node, element)) {
  4686. return element;
  4687. }
  4688. }
  4689. this.#setAttributes(node, element);
  4690. if (node.children) {
  4691. if (node.children.length === 1 && "id" in node.children[0]) {
  4692. this.#setAttributes(node.children[0], element);
  4693. } else {
  4694. for (const kid of node.children) {
  4695. element.append(this.#walk(kid));
  4696. }
  4697. }
  4698. }
  4699. return element;
  4700. }
  4701. }
  4702. ;// ./web/text_accessibility.js
  4703. class TextAccessibilityManager {
  4704. #enabled = false;
  4705. #textChildren = null;
  4706. #textNodes = new Map();
  4707. #waitingElements = new Map();
  4708. setTextMapping(textDivs) {
  4709. this.#textChildren = textDivs;
  4710. }
  4711. static #compareElementPositions(e1, e2) {
  4712. const rect1 = e1.getBoundingClientRect();
  4713. const rect2 = e2.getBoundingClientRect();
  4714. if (rect1.width === 0 && rect1.height === 0) {
  4715. return +1;
  4716. }
  4717. if (rect2.width === 0 && rect2.height === 0) {
  4718. return -1;
  4719. }
  4720. const top1 = rect1.y;
  4721. const bot1 = rect1.y + rect1.height;
  4722. const mid1 = rect1.y + rect1.height / 2;
  4723. const top2 = rect2.y;
  4724. const bot2 = rect2.y + rect2.height;
  4725. const mid2 = rect2.y + rect2.height / 2;
  4726. if (mid1 <= top2 && mid2 >= bot1) {
  4727. return -1;
  4728. }
  4729. if (mid2 <= top1 && mid1 >= bot2) {
  4730. return +1;
  4731. }
  4732. const centerX1 = rect1.x + rect1.width / 2;
  4733. const centerX2 = rect2.x + rect2.width / 2;
  4734. return centerX1 - centerX2;
  4735. }
  4736. enable() {
  4737. if (this.#enabled) {
  4738. throw new Error("TextAccessibilityManager is already enabled.");
  4739. }
  4740. if (!this.#textChildren) {
  4741. throw new Error("Text divs and strings have not been set.");
  4742. }
  4743. this.#enabled = true;
  4744. this.#textChildren = this.#textChildren.slice();
  4745. this.#textChildren.sort(TextAccessibilityManager.#compareElementPositions);
  4746. if (this.#textNodes.size > 0) {
  4747. const textChildren = this.#textChildren;
  4748. for (const [id, nodeIndex] of this.#textNodes) {
  4749. const element = document.getElementById(id);
  4750. if (!element) {
  4751. this.#textNodes.delete(id);
  4752. continue;
  4753. }
  4754. this.#addIdToAriaOwns(id, textChildren[nodeIndex]);
  4755. }
  4756. }
  4757. for (const [element, isRemovable] of this.#waitingElements) {
  4758. this.addPointerInTextLayer(element, isRemovable);
  4759. }
  4760. this.#waitingElements.clear();
  4761. }
  4762. disable() {
  4763. if (!this.#enabled) {
  4764. return;
  4765. }
  4766. this.#waitingElements.clear();
  4767. this.#textChildren = null;
  4768. this.#enabled = false;
  4769. }
  4770. removePointerInTextLayer(element) {
  4771. if (!this.#enabled) {
  4772. this.#waitingElements.delete(element);
  4773. return;
  4774. }
  4775. const children = this.#textChildren;
  4776. if (!children || children.length === 0) {
  4777. return;
  4778. }
  4779. const {
  4780. id
  4781. } = element;
  4782. const nodeIndex = this.#textNodes.get(id);
  4783. if (nodeIndex === undefined) {
  4784. return;
  4785. }
  4786. const node = children[nodeIndex];
  4787. this.#textNodes.delete(id);
  4788. let owns = node.getAttribute("aria-owns");
  4789. if (owns?.includes(id)) {
  4790. owns = owns.split(" ").filter(x => x !== id).join(" ");
  4791. if (owns) {
  4792. node.setAttribute("aria-owns", owns);
  4793. } else {
  4794. node.removeAttribute("aria-owns");
  4795. node.setAttribute("role", "presentation");
  4796. }
  4797. }
  4798. }
  4799. #addIdToAriaOwns(id, node) {
  4800. const owns = node.getAttribute("aria-owns");
  4801. if (!owns?.includes(id)) {
  4802. node.setAttribute("aria-owns", owns ? `${owns} ${id}` : id);
  4803. }
  4804. node.removeAttribute("role");
  4805. }
  4806. addPointerInTextLayer(element, isRemovable) {
  4807. const {
  4808. id
  4809. } = element;
  4810. if (!id) {
  4811. return null;
  4812. }
  4813. if (!this.#enabled) {
  4814. this.#waitingElements.set(element, isRemovable);
  4815. return null;
  4816. }
  4817. if (isRemovable) {
  4818. this.removePointerInTextLayer(element);
  4819. }
  4820. const children = this.#textChildren;
  4821. if (!children || children.length === 0) {
  4822. return null;
  4823. }
  4824. const index = binarySearchFirstItem(children, node => TextAccessibilityManager.#compareElementPositions(element, node) < 0);
  4825. const nodeIndex = Math.max(0, index - 1);
  4826. const child = children[nodeIndex];
  4827. this.#addIdToAriaOwns(id, child);
  4828. this.#textNodes.set(id, nodeIndex);
  4829. const parent = child.parentNode;
  4830. return parent?.classList.contains("markedContent") ? parent.id : null;
  4831. }
  4832. moveElementInDOM(container, element, contentElement, isRemovable) {
  4833. const id = this.addPointerInTextLayer(contentElement, isRemovable);
  4834. if (!container.hasChildNodes()) {
  4835. container.append(element);
  4836. return id;
  4837. }
  4838. const children = Array.from(container.childNodes).filter(node => node !== element);
  4839. if (children.length === 0) {
  4840. return id;
  4841. }
  4842. const elementToCompare = contentElement || element;
  4843. const index = binarySearchFirstItem(children, node => TextAccessibilityManager.#compareElementPositions(elementToCompare, node) < 0);
  4844. if (index === 0) {
  4845. children[0].before(element);
  4846. } else {
  4847. children[index - 1].after(element);
  4848. }
  4849. return id;
  4850. }
  4851. }
  4852. ;// ./web/text_highlighter.js
  4853. class TextHighlighter {
  4854. #eventAbortController = null;
  4855. constructor({
  4856. findController,
  4857. eventBus,
  4858. pageIndex
  4859. }) {
  4860. this.findController = findController;
  4861. this.matches = [];
  4862. this.eventBus = eventBus;
  4863. this.pageIdx = pageIndex;
  4864. this.textDivs = null;
  4865. this.textContentItemsStr = null;
  4866. this.enabled = false;
  4867. }
  4868. setTextMapping(divs, texts) {
  4869. this.textDivs = divs;
  4870. this.textContentItemsStr = texts;
  4871. }
  4872. enable() {
  4873. if (!this.textDivs || !this.textContentItemsStr) {
  4874. throw new Error("Text divs and strings have not been set.");
  4875. }
  4876. if (this.enabled) {
  4877. throw new Error("TextHighlighter is already enabled.");
  4878. }
  4879. this.enabled = true;
  4880. if (!this.#eventAbortController) {
  4881. this.#eventAbortController = new AbortController();
  4882. this.eventBus._on("updatetextlayermatches", evt => {
  4883. if (evt.pageIndex === this.pageIdx || evt.pageIndex === -1) {
  4884. this._updateMatches();
  4885. }
  4886. }, {
  4887. signal: this.#eventAbortController.signal
  4888. });
  4889. }
  4890. this._updateMatches();
  4891. }
  4892. disable() {
  4893. if (!this.enabled) {
  4894. return;
  4895. }
  4896. this.enabled = false;
  4897. this.#eventAbortController?.abort();
  4898. this.#eventAbortController = null;
  4899. this._updateMatches(true);
  4900. }
  4901. _convertMatches(matches, matchesLength) {
  4902. if (!matches) {
  4903. return [];
  4904. }
  4905. const {
  4906. textContentItemsStr
  4907. } = this;
  4908. let i = 0,
  4909. iIndex = 0;
  4910. const end = textContentItemsStr.length - 1;
  4911. const result = [];
  4912. for (let m = 0, mm = matches.length; m < mm; m++) {
  4913. let matchIdx = matches[m];
  4914. while (i !== end && matchIdx >= iIndex + textContentItemsStr[i].length) {
  4915. iIndex += textContentItemsStr[i].length;
  4916. i++;
  4917. }
  4918. if (i === textContentItemsStr.length) {
  4919. console.error("Could not find a matching mapping");
  4920. }
  4921. const match = {
  4922. begin: {
  4923. divIdx: i,
  4924. offset: matchIdx - iIndex
  4925. }
  4926. };
  4927. matchIdx += matchesLength[m];
  4928. while (i !== end && matchIdx > iIndex + textContentItemsStr[i].length) {
  4929. iIndex += textContentItemsStr[i].length;
  4930. i++;
  4931. }
  4932. match.end = {
  4933. divIdx: i,
  4934. offset: matchIdx - iIndex
  4935. };
  4936. result.push(match);
  4937. }
  4938. return result;
  4939. }
  4940. _renderMatches(matches) {
  4941. if (matches.length === 0) {
  4942. return;
  4943. }
  4944. const {
  4945. findController,
  4946. pageIdx
  4947. } = this;
  4948. const {
  4949. textContentItemsStr,
  4950. textDivs
  4951. } = this;
  4952. const isSelectedPage = pageIdx === findController.selected.pageIdx;
  4953. const selectedMatchIdx = findController.selected.matchIdx;
  4954. const highlightAll = findController.state.highlightAll;
  4955. let prevEnd = null;
  4956. const infinity = {
  4957. divIdx: -1,
  4958. offset: undefined
  4959. };
  4960. function beginText(begin, className) {
  4961. const divIdx = begin.divIdx;
  4962. textDivs[divIdx].textContent = "";
  4963. return appendTextToDiv(divIdx, 0, begin.offset, className);
  4964. }
  4965. function appendTextToDiv(divIdx, fromOffset, toOffset, className) {
  4966. let div = textDivs[divIdx];
  4967. if (div.nodeType === Node.TEXT_NODE) {
  4968. const span = document.createElement("span");
  4969. div.before(span);
  4970. span.append(div);
  4971. textDivs[divIdx] = span;
  4972. div = span;
  4973. }
  4974. const content = textContentItemsStr[divIdx].substring(fromOffset, toOffset);
  4975. const node = document.createTextNode(content);
  4976. if (className) {
  4977. const span = document.createElement("span");
  4978. span.className = `${className} appended`;
  4979. span.append(node);
  4980. div.append(span);
  4981. if (className.includes("selected")) {
  4982. const {
  4983. left
  4984. } = span.getClientRects()[0];
  4985. const parentLeft = div.getBoundingClientRect().left;
  4986. return left - parentLeft;
  4987. }
  4988. return 0;
  4989. }
  4990. div.append(node);
  4991. return 0;
  4992. }
  4993. let i0 = selectedMatchIdx,
  4994. i1 = i0 + 1;
  4995. if (highlightAll) {
  4996. i0 = 0;
  4997. i1 = matches.length;
  4998. } else if (!isSelectedPage) {
  4999. return;
  5000. }
  5001. let lastDivIdx = -1;
  5002. let lastOffset = -1;
  5003. for (let i = i0; i < i1; i++) {
  5004. const match = matches[i];
  5005. const begin = match.begin;
  5006. if (begin.divIdx === lastDivIdx && begin.offset === lastOffset) {
  5007. continue;
  5008. }
  5009. lastDivIdx = begin.divIdx;
  5010. lastOffset = begin.offset;
  5011. const end = match.end;
  5012. const isSelected = isSelectedPage && i === selectedMatchIdx;
  5013. const highlightSuffix = isSelected ? " selected" : "";
  5014. let selectedLeft = 0;
  5015. if (!prevEnd || begin.divIdx !== prevEnd.divIdx) {
  5016. if (prevEnd !== null) {
  5017. appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
  5018. }
  5019. beginText(begin);
  5020. } else {
  5021. appendTextToDiv(prevEnd.divIdx, prevEnd.offset, begin.offset);
  5022. }
  5023. if (begin.divIdx === end.divIdx) {
  5024. selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, end.offset, "highlight" + highlightSuffix);
  5025. } else {
  5026. selectedLeft = appendTextToDiv(begin.divIdx, begin.offset, infinity.offset, "highlight begin" + highlightSuffix);
  5027. for (let n0 = begin.divIdx + 1, n1 = end.divIdx; n0 < n1; n0++) {
  5028. textDivs[n0].className = "highlight middle" + highlightSuffix;
  5029. }
  5030. beginText(end, "highlight end" + highlightSuffix);
  5031. }
  5032. prevEnd = end;
  5033. if (isSelected) {
  5034. findController.scrollMatchIntoView({
  5035. element: textDivs[begin.divIdx],
  5036. selectedLeft,
  5037. pageIndex: pageIdx,
  5038. matchIndex: selectedMatchIdx
  5039. });
  5040. }
  5041. }
  5042. if (prevEnd) {
  5043. appendTextToDiv(prevEnd.divIdx, prevEnd.offset, infinity.offset);
  5044. }
  5045. }
  5046. _updateMatches(reset = false) {
  5047. if (!this.enabled && !reset) {
  5048. return;
  5049. }
  5050. const {
  5051. findController,
  5052. matches,
  5053. pageIdx
  5054. } = this;
  5055. const {
  5056. textContentItemsStr,
  5057. textDivs
  5058. } = this;
  5059. let clearedUntilDivIdx = -1;
  5060. for (const match of matches) {
  5061. const begin = Math.max(clearedUntilDivIdx, match.begin.divIdx);
  5062. for (let n = begin, end = match.end.divIdx; n <= end; n++) {
  5063. const div = textDivs[n];
  5064. div.textContent = textContentItemsStr[n];
  5065. div.className = "";
  5066. }
  5067. clearedUntilDivIdx = match.end.divIdx + 1;
  5068. }
  5069. if (!findController?.highlightMatches || reset) {
  5070. return;
  5071. }
  5072. const pageMatches = findController.pageMatches[pageIdx] || null;
  5073. const pageMatchesLength = findController.pageMatchesLength[pageIdx] || null;
  5074. this.matches = this._convertMatches(pageMatches, pageMatchesLength);
  5075. this._renderMatches(this.matches);
  5076. }
  5077. }
  5078. ;// ./web/text_layer_builder.js
  5079. class TextLayerBuilder {
  5080. #enablePermissions = false;
  5081. #onAppend = null;
  5082. #renderingDone = false;
  5083. #textLayer = null;
  5084. static #textLayers = new Map();
  5085. static #selectionChangeAbortController = null;
  5086. constructor({
  5087. pdfPage,
  5088. highlighter = null,
  5089. accessibilityManager = null,
  5090. enablePermissions = false,
  5091. onAppend = null
  5092. }) {
  5093. this.pdfPage = pdfPage;
  5094. this.highlighter = highlighter;
  5095. this.accessibilityManager = accessibilityManager;
  5096. this.#enablePermissions = enablePermissions === true;
  5097. this.#onAppend = onAppend;
  5098. this.div = document.createElement("div");
  5099. this.div.tabIndex = 0;
  5100. this.div.className = "textLayer";
  5101. }
  5102. async render(viewport, textContentParams = null) {
  5103. if (this.#renderingDone && this.#textLayer) {
  5104. this.#textLayer.update({
  5105. viewport,
  5106. onBefore: this.hide.bind(this)
  5107. });
  5108. this.show();
  5109. return;
  5110. }
  5111. this.cancel();
  5112. this.#textLayer = new TextLayer({
  5113. textContentSource: this.pdfPage.streamTextContent(textContentParams || {
  5114. includeMarkedContent: true,
  5115. disableNormalization: true
  5116. }),
  5117. container: this.div,
  5118. viewport
  5119. });
  5120. const {
  5121. textDivs,
  5122. textContentItemsStr
  5123. } = this.#textLayer;
  5124. this.highlighter?.setTextMapping(textDivs, textContentItemsStr);
  5125. this.accessibilityManager?.setTextMapping(textDivs);
  5126. await this.#textLayer.render();
  5127. this.#renderingDone = true;
  5128. const endOfContent = document.createElement("div");
  5129. endOfContent.className = "endOfContent";
  5130. this.div.append(endOfContent);
  5131. this.#bindMouse(endOfContent);
  5132. this.#onAppend?.(this.div);
  5133. this.highlighter?.enable();
  5134. this.accessibilityManager?.enable();
  5135. }
  5136. hide() {
  5137. if (!this.div.hidden && this.#renderingDone) {
  5138. this.highlighter?.disable();
  5139. this.div.hidden = true;
  5140. }
  5141. }
  5142. show() {
  5143. if (this.div.hidden && this.#renderingDone) {
  5144. this.div.hidden = false;
  5145. this.highlighter?.enable();
  5146. }
  5147. }
  5148. cancel() {
  5149. this.#textLayer?.cancel();
  5150. this.#textLayer = null;
  5151. this.highlighter?.disable();
  5152. this.accessibilityManager?.disable();
  5153. TextLayerBuilder.#removeGlobalSelectionListener(this.div);
  5154. }
  5155. #bindMouse(end) {
  5156. const {
  5157. div
  5158. } = this;
  5159. div.addEventListener("mousedown", () => {
  5160. div.classList.add("selecting");
  5161. });
  5162. div.addEventListener("copy", event => {
  5163. if (!this.#enablePermissions) {
  5164. const selection = document.getSelection();
  5165. event.clipboardData.setData("text/plain", removeNullCharacters(normalizeUnicode(selection.toString())));
  5166. }
  5167. stopEvent(event);
  5168. });
  5169. TextLayerBuilder.#textLayers.set(div, end);
  5170. TextLayerBuilder.#enableGlobalSelectionListener();
  5171. }
  5172. static #removeGlobalSelectionListener(textLayerDiv) {
  5173. this.#textLayers.delete(textLayerDiv);
  5174. if (this.#textLayers.size === 0) {
  5175. this.#selectionChangeAbortController?.abort();
  5176. this.#selectionChangeAbortController = null;
  5177. }
  5178. }
  5179. static #enableGlobalSelectionListener() {
  5180. if (this.#selectionChangeAbortController) {
  5181. return;
  5182. }
  5183. this.#selectionChangeAbortController = new AbortController();
  5184. const {
  5185. signal
  5186. } = this.#selectionChangeAbortController;
  5187. const reset = (end, textLayer) => {
  5188. textLayer.append(end);
  5189. end.style.width = "";
  5190. end.style.height = "";
  5191. textLayer.classList.remove("selecting");
  5192. };
  5193. let isPointerDown = false;
  5194. document.addEventListener("pointerdown", () => {
  5195. isPointerDown = true;
  5196. }, {
  5197. signal
  5198. });
  5199. document.addEventListener("pointerup", () => {
  5200. isPointerDown = false;
  5201. this.#textLayers.forEach(reset);
  5202. }, {
  5203. signal
  5204. });
  5205. window.addEventListener("blur", () => {
  5206. isPointerDown = false;
  5207. this.#textLayers.forEach(reset);
  5208. }, {
  5209. signal
  5210. });
  5211. document.addEventListener("keyup", () => {
  5212. if (!isPointerDown) {
  5213. this.#textLayers.forEach(reset);
  5214. }
  5215. }, {
  5216. signal
  5217. });
  5218. var isFirefox, prevRange;
  5219. document.addEventListener("selectionchange", () => {
  5220. const selection = document.getSelection();
  5221. if (selection.rangeCount === 0) {
  5222. this.#textLayers.forEach(reset);
  5223. return;
  5224. }
  5225. const activeTextLayers = new Set();
  5226. for (let i = 0; i < selection.rangeCount; i++) {
  5227. const range = selection.getRangeAt(i);
  5228. for (const textLayerDiv of this.#textLayers.keys()) {
  5229. if (!activeTextLayers.has(textLayerDiv) && range.intersectsNode(textLayerDiv)) {
  5230. activeTextLayers.add(textLayerDiv);
  5231. }
  5232. }
  5233. }
  5234. for (const [textLayerDiv, endDiv] of this.#textLayers) {
  5235. if (activeTextLayers.has(textLayerDiv)) {
  5236. textLayerDiv.classList.add("selecting");
  5237. } else {
  5238. reset(endDiv, textLayerDiv);
  5239. }
  5240. }
  5241. isFirefox ??= getComputedStyle(this.#textLayers.values().next().value).getPropertyValue("-moz-user-select") === "none";
  5242. if (isFirefox) {
  5243. return;
  5244. }
  5245. const range = selection.getRangeAt(0);
  5246. const modifyStart = prevRange && (range.compareBoundaryPoints(Range.END_TO_END, prevRange) === 0 || range.compareBoundaryPoints(Range.START_TO_END, prevRange) === 0);
  5247. let anchor = modifyStart ? range.startContainer : range.endContainer;
  5248. if (anchor.nodeType === Node.TEXT_NODE) {
  5249. anchor = anchor.parentNode;
  5250. }
  5251. const parentTextLayer = anchor.parentElement?.closest(".textLayer");
  5252. const endDiv = this.#textLayers.get(parentTextLayer);
  5253. if (endDiv) {
  5254. endDiv.style.width = parentTextLayer.style.width;
  5255. endDiv.style.height = parentTextLayer.style.height;
  5256. anchor.parentElement.insertBefore(endDiv, modifyStart ? anchor : anchor.nextSibling);
  5257. }
  5258. prevRange = range.cloneRange();
  5259. }, {
  5260. signal
  5261. });
  5262. }
  5263. }
  5264. ;// ./web/xfa_layer_builder.js
  5265. class XfaLayerBuilder {
  5266. constructor({
  5267. pdfPage,
  5268. annotationStorage = null,
  5269. linkService,
  5270. xfaHtml = null
  5271. }) {
  5272. this.pdfPage = pdfPage;
  5273. this.annotationStorage = annotationStorage;
  5274. this.linkService = linkService;
  5275. this.xfaHtml = xfaHtml;
  5276. this.div = null;
  5277. this._cancelled = false;
  5278. }
  5279. async render(viewport, intent = "display") {
  5280. if (intent === "print") {
  5281. const parameters = {
  5282. viewport: viewport.clone({
  5283. dontFlip: true
  5284. }),
  5285. div: this.div,
  5286. xfaHtml: this.xfaHtml,
  5287. annotationStorage: this.annotationStorage,
  5288. linkService: this.linkService,
  5289. intent
  5290. };
  5291. this.div = document.createElement("div");
  5292. parameters.div = this.div;
  5293. return XfaLayer.render(parameters);
  5294. }
  5295. const xfaHtml = await this.pdfPage.getXfa();
  5296. if (this._cancelled || !xfaHtml) {
  5297. return {
  5298. textDivs: []
  5299. };
  5300. }
  5301. const parameters = {
  5302. viewport: viewport.clone({
  5303. dontFlip: true
  5304. }),
  5305. div: this.div,
  5306. xfaHtml,
  5307. annotationStorage: this.annotationStorage,
  5308. linkService: this.linkService,
  5309. intent
  5310. };
  5311. if (this.div) {
  5312. return XfaLayer.update(parameters);
  5313. }
  5314. this.div = document.createElement("div");
  5315. parameters.div = this.div;
  5316. return XfaLayer.render(parameters);
  5317. }
  5318. cancel() {
  5319. this._cancelled = true;
  5320. }
  5321. hide() {
  5322. if (!this.div) {
  5323. return;
  5324. }
  5325. this.div.hidden = true;
  5326. }
  5327. }
  5328. ;// ./web/pdf_page_view.js
  5329. const DEFAULT_LAYER_PROPERTIES = {
  5330. annotationEditorUIManager: null,
  5331. annotationStorage: null,
  5332. downloadManager: null,
  5333. enableScripting: false,
  5334. fieldObjectsPromise: null,
  5335. findController: null,
  5336. hasJSActionsPromise: null,
  5337. get linkService() {
  5338. return new SimpleLinkService();
  5339. }
  5340. };
  5341. const LAYERS_ORDER = new Map([["canvasWrapper", 0], ["textLayer", 1], ["annotationLayer", 2], ["annotationEditorLayer", 3], ["xfaLayer", 3]]);
  5342. class PDFPageView {
  5343. #annotationMode = AnnotationMode.ENABLE_FORMS;
  5344. #canvasWrapper = null;
  5345. #enableHWA = false;
  5346. #hasRestrictedScaling = false;
  5347. #isEditing = false;
  5348. #layerProperties = null;
  5349. #loadingId = null;
  5350. #originalViewport = null;
  5351. #previousRotation = null;
  5352. #scaleRoundX = 1;
  5353. #scaleRoundY = 1;
  5354. #renderError = null;
  5355. #renderingState = RenderingStates.INITIAL;
  5356. #textLayerMode = TextLayerMode.ENABLE;
  5357. #useThumbnailCanvas = {
  5358. directDrawing: true,
  5359. initialOptionalContent: true,
  5360. regularAnnotations: true
  5361. };
  5362. #layers = [null, null, null, null];
  5363. constructor(options) {
  5364. const container = options.container;
  5365. const defaultViewport = options.defaultViewport;
  5366. this.id = options.id;
  5367. this.renderingId = "page" + this.id;
  5368. this.#layerProperties = options.layerProperties || DEFAULT_LAYER_PROPERTIES;
  5369. this.pdfPage = null;
  5370. this.pageLabel = null;
  5371. this.rotation = 0;
  5372. this.scale = options.scale || DEFAULT_SCALE;
  5373. this.viewport = defaultViewport;
  5374. this.pdfPageRotate = defaultViewport.rotation;
  5375. this._optionalContentConfigPromise = options.optionalContentConfigPromise || null;
  5376. this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
  5377. this.#annotationMode = options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
  5378. this.imageResourcesPath = options.imageResourcesPath || "";
  5379. this.maxCanvasPixels = options.maxCanvasPixels ?? AppOptions.get("maxCanvasPixels");
  5380. this.pageColors = options.pageColors || null;
  5381. this.#enableHWA = options.enableHWA || false;
  5382. this.eventBus = options.eventBus;
  5383. this.renderingQueue = options.renderingQueue;
  5384. this.l10n = options.l10n;
  5385. this.l10n ||= new genericl10n_GenericL10n();
  5386. this.renderTask = null;
  5387. this.resume = null;
  5388. this._isStandalone = !this.renderingQueue?.hasViewer();
  5389. this._container = container;
  5390. this._annotationCanvasMap = null;
  5391. this.annotationLayer = null;
  5392. this.annotationEditorLayer = null;
  5393. this.textLayer = null;
  5394. this.xfaLayer = null;
  5395. this.structTreeLayer = null;
  5396. this.drawLayer = null;
  5397. const div = document.createElement("div");
  5398. div.className = "page";
  5399. div.setAttribute("data-page-number", this.id);
  5400. div.setAttribute("role", "region");
  5401. div.setAttribute("data-l10n-id", "pdfjs-page-landmark");
  5402. div.setAttribute("data-l10n-args", JSON.stringify({
  5403. page: this.id
  5404. }));
  5405. this.div = div;
  5406. this.#setDimensions();
  5407. container?.append(div);
  5408. if (this._isStandalone) {
  5409. container?.style.setProperty("--scale-factor", this.scale * PixelsPerInch.PDF_TO_CSS_UNITS);
  5410. if (this.pageColors?.background) {
  5411. container?.style.setProperty("--page-bg-color", this.pageColors.background);
  5412. }
  5413. const {
  5414. optionalContentConfigPromise
  5415. } = options;
  5416. if (optionalContentConfigPromise) {
  5417. optionalContentConfigPromise.then(optionalContentConfig => {
  5418. if (optionalContentConfigPromise !== this._optionalContentConfigPromise) {
  5419. return;
  5420. }
  5421. this.#useThumbnailCanvas.initialOptionalContent = optionalContentConfig.hasInitialVisibility;
  5422. });
  5423. }
  5424. if (!options.l10n) {
  5425. this.l10n.translate(this.div);
  5426. }
  5427. }
  5428. }
  5429. #addLayer(div, name) {
  5430. const pos = LAYERS_ORDER.get(name);
  5431. const oldDiv = this.#layers[pos];
  5432. this.#layers[pos] = div;
  5433. if (oldDiv) {
  5434. oldDiv.replaceWith(div);
  5435. return;
  5436. }
  5437. for (let i = pos - 1; i >= 0; i--) {
  5438. const layer = this.#layers[i];
  5439. if (layer) {
  5440. layer.after(div);
  5441. return;
  5442. }
  5443. }
  5444. this.div.prepend(div);
  5445. }
  5446. get renderingState() {
  5447. return this.#renderingState;
  5448. }
  5449. set renderingState(state) {
  5450. if (state === this.#renderingState) {
  5451. return;
  5452. }
  5453. this.#renderingState = state;
  5454. if (this.#loadingId) {
  5455. clearTimeout(this.#loadingId);
  5456. this.#loadingId = null;
  5457. }
  5458. switch (state) {
  5459. case RenderingStates.PAUSED:
  5460. this.div.classList.remove("loading");
  5461. break;
  5462. case RenderingStates.RUNNING:
  5463. this.div.classList.add("loadingIcon");
  5464. this.#loadingId = setTimeout(() => {
  5465. this.div.classList.add("loading");
  5466. this.#loadingId = null;
  5467. }, 0);
  5468. break;
  5469. case RenderingStates.INITIAL:
  5470. case RenderingStates.FINISHED:
  5471. this.div.classList.remove("loadingIcon", "loading");
  5472. break;
  5473. }
  5474. }
  5475. #setDimensions() {
  5476. const {
  5477. viewport
  5478. } = this;
  5479. if (this.pdfPage) {
  5480. if (this.#previousRotation === viewport.rotation) {
  5481. return;
  5482. }
  5483. this.#previousRotation = viewport.rotation;
  5484. }
  5485. setLayerDimensions(this.div, viewport, true, false);
  5486. }
  5487. setPdfPage(pdfPage) {
  5488. if (this._isStandalone && (this.pageColors?.foreground === "CanvasText" || this.pageColors?.background === "Canvas")) {
  5489. this._container?.style.setProperty("--hcm-highlight-filter", pdfPage.filterFactory.addHighlightHCMFilter("highlight", "CanvasText", "Canvas", "HighlightText", "Highlight"));
  5490. this._container?.style.setProperty("--hcm-highlight-selected-filter", pdfPage.filterFactory.addHighlightHCMFilter("highlight_selected", "CanvasText", "Canvas", "HighlightText", "Highlight"));
  5491. }
  5492. this.pdfPage = pdfPage;
  5493. this.pdfPageRotate = pdfPage.rotate;
  5494. const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
  5495. this.viewport = pdfPage.getViewport({
  5496. scale: this.scale * PixelsPerInch.PDF_TO_CSS_UNITS,
  5497. rotation: totalRotation
  5498. });
  5499. this.#setDimensions();
  5500. this.reset();
  5501. }
  5502. destroy() {
  5503. this.reset();
  5504. this.pdfPage?.cleanup();
  5505. }
  5506. hasEditableAnnotations() {
  5507. return !!this.annotationLayer?.hasEditableAnnotations();
  5508. }
  5509. get _textHighlighter() {
  5510. return shadow(this, "_textHighlighter", new TextHighlighter({
  5511. pageIndex: this.id - 1,
  5512. eventBus: this.eventBus,
  5513. findController: this.#layerProperties.findController
  5514. }));
  5515. }
  5516. #dispatchLayerRendered(name, error) {
  5517. this.eventBus.dispatch(name, {
  5518. source: this,
  5519. pageNumber: this.id,
  5520. error
  5521. });
  5522. }
  5523. async #renderAnnotationLayer() {
  5524. let error = null;
  5525. try {
  5526. await this.annotationLayer.render(this.viewport, {
  5527. structTreeLayer: this.structTreeLayer
  5528. }, "display");
  5529. } catch (ex) {
  5530. console.error("#renderAnnotationLayer:", ex);
  5531. error = ex;
  5532. } finally {
  5533. this.#dispatchLayerRendered("annotationlayerrendered", error);
  5534. }
  5535. }
  5536. async #renderAnnotationEditorLayer() {
  5537. let error = null;
  5538. try {
  5539. await this.annotationEditorLayer.render(this.viewport, "display");
  5540. } catch (ex) {
  5541. console.error("#renderAnnotationEditorLayer:", ex);
  5542. error = ex;
  5543. } finally {
  5544. this.#dispatchLayerRendered("annotationeditorlayerrendered", error);
  5545. }
  5546. }
  5547. async #renderDrawLayer() {
  5548. try {
  5549. await this.drawLayer.render("display");
  5550. } catch (ex) {
  5551. console.error("#renderDrawLayer:", ex);
  5552. }
  5553. }
  5554. async #renderXfaLayer() {
  5555. let error = null;
  5556. try {
  5557. const result = await this.xfaLayer.render(this.viewport, "display");
  5558. if (result?.textDivs && this._textHighlighter) {
  5559. this.#buildXfaTextContentItems(result.textDivs);
  5560. }
  5561. } catch (ex) {
  5562. console.error("#renderXfaLayer:", ex);
  5563. error = ex;
  5564. } finally {
  5565. if (this.xfaLayer?.div) {
  5566. this.l10n.pause();
  5567. this.#addLayer(this.xfaLayer.div, "xfaLayer");
  5568. this.l10n.resume();
  5569. }
  5570. this.#dispatchLayerRendered("xfalayerrendered", error);
  5571. }
  5572. }
  5573. async #renderTextLayer() {
  5574. if (!this.textLayer) {
  5575. return;
  5576. }
  5577. let error = null;
  5578. try {
  5579. await this.textLayer.render(this.viewport);
  5580. } catch (ex) {
  5581. if (ex instanceof AbortException) {
  5582. return;
  5583. }
  5584. console.error("#renderTextLayer:", ex);
  5585. error = ex;
  5586. }
  5587. this.#dispatchLayerRendered("textlayerrendered", error);
  5588. this.#renderStructTreeLayer();
  5589. }
  5590. async #renderStructTreeLayer() {
  5591. if (!this.textLayer) {
  5592. return;
  5593. }
  5594. const treeDom = await this.structTreeLayer?.render();
  5595. if (treeDom) {
  5596. this.l10n.pause();
  5597. this.structTreeLayer?.addElementsToTextLayer();
  5598. if (this.canvas && treeDom.parentNode !== this.canvas) {
  5599. this.canvas.append(treeDom);
  5600. }
  5601. this.l10n.resume();
  5602. }
  5603. this.structTreeLayer?.show();
  5604. }
  5605. async #buildXfaTextContentItems(textDivs) {
  5606. const text = await this.pdfPage.getTextContent();
  5607. const items = [];
  5608. for (const item of text.items) {
  5609. items.push(item.str);
  5610. }
  5611. this._textHighlighter.setTextMapping(textDivs, items);
  5612. this._textHighlighter.enable();
  5613. }
  5614. #resetCanvas() {
  5615. const {
  5616. canvas
  5617. } = this;
  5618. if (!canvas) {
  5619. return;
  5620. }
  5621. canvas.remove();
  5622. canvas.width = canvas.height = 0;
  5623. this.canvas = null;
  5624. this.#originalViewport = null;
  5625. }
  5626. reset({
  5627. keepAnnotationLayer = false,
  5628. keepAnnotationEditorLayer = false,
  5629. keepXfaLayer = false,
  5630. keepTextLayer = false,
  5631. keepCanvasWrapper = false
  5632. } = {}) {
  5633. this.cancelRendering({
  5634. keepAnnotationLayer,
  5635. keepAnnotationEditorLayer,
  5636. keepXfaLayer,
  5637. keepTextLayer
  5638. });
  5639. this.renderingState = RenderingStates.INITIAL;
  5640. const div = this.div;
  5641. const childNodes = div.childNodes,
  5642. annotationLayerNode = keepAnnotationLayer && this.annotationLayer?.div || null,
  5643. annotationEditorLayerNode = keepAnnotationEditorLayer && this.annotationEditorLayer?.div || null,
  5644. xfaLayerNode = keepXfaLayer && this.xfaLayer?.div || null,
  5645. textLayerNode = keepTextLayer && this.textLayer?.div || null,
  5646. canvasWrapperNode = keepCanvasWrapper && this.#canvasWrapper || null;
  5647. for (let i = childNodes.length - 1; i >= 0; i--) {
  5648. const node = childNodes[i];
  5649. switch (node) {
  5650. case annotationLayerNode:
  5651. case annotationEditorLayerNode:
  5652. case xfaLayerNode:
  5653. case textLayerNode:
  5654. case canvasWrapperNode:
  5655. continue;
  5656. }
  5657. node.remove();
  5658. const layerIndex = this.#layers.indexOf(node);
  5659. if (layerIndex >= 0) {
  5660. this.#layers[layerIndex] = null;
  5661. }
  5662. }
  5663. div.removeAttribute("data-loaded");
  5664. if (annotationLayerNode) {
  5665. this.annotationLayer.hide();
  5666. }
  5667. if (annotationEditorLayerNode) {
  5668. this.annotationEditorLayer.hide();
  5669. }
  5670. if (xfaLayerNode) {
  5671. this.xfaLayer.hide();
  5672. }
  5673. if (textLayerNode) {
  5674. this.textLayer.hide();
  5675. }
  5676. this.structTreeLayer?.hide();
  5677. if (!keepCanvasWrapper && this.#canvasWrapper) {
  5678. this.#canvasWrapper = null;
  5679. this.#resetCanvas();
  5680. }
  5681. }
  5682. toggleEditingMode(isEditing) {
  5683. if (!this.hasEditableAnnotations()) {
  5684. return;
  5685. }
  5686. this.#isEditing = isEditing;
  5687. this.reset({
  5688. keepAnnotationLayer: true,
  5689. keepAnnotationEditorLayer: true,
  5690. keepXfaLayer: true,
  5691. keepTextLayer: true,
  5692. keepCanvasWrapper: true
  5693. });
  5694. }
  5695. update({
  5696. scale = 0,
  5697. rotation = null,
  5698. optionalContentConfigPromise = null,
  5699. drawingDelay = -1
  5700. }) {
  5701. this.scale = scale || this.scale;
  5702. if (typeof rotation === "number") {
  5703. this.rotation = rotation;
  5704. }
  5705. if (optionalContentConfigPromise instanceof Promise) {
  5706. this._optionalContentConfigPromise = optionalContentConfigPromise;
  5707. optionalContentConfigPromise.then(optionalContentConfig => {
  5708. if (optionalContentConfigPromise !== this._optionalContentConfigPromise) {
  5709. return;
  5710. }
  5711. this.#useThumbnailCanvas.initialOptionalContent = optionalContentConfig.hasInitialVisibility;
  5712. });
  5713. }
  5714. this.#useThumbnailCanvas.directDrawing = true;
  5715. const totalRotation = (this.rotation + this.pdfPageRotate) % 360;
  5716. this.viewport = this.viewport.clone({
  5717. scale: this.scale * PixelsPerInch.PDF_TO_CSS_UNITS,
  5718. rotation: totalRotation
  5719. });
  5720. this.#setDimensions();
  5721. if (this._isStandalone) {
  5722. this._container?.style.setProperty("--scale-factor", this.viewport.scale);
  5723. }
  5724. if (this.canvas) {
  5725. let onlyCssZoom = false;
  5726. if (this.#hasRestrictedScaling) {
  5727. if (this.maxCanvasPixels === 0) {
  5728. onlyCssZoom = true;
  5729. } else if (this.maxCanvasPixels > 0) {
  5730. const {
  5731. width,
  5732. height
  5733. } = this.viewport;
  5734. const {
  5735. sx,
  5736. sy
  5737. } = this.outputScale;
  5738. onlyCssZoom = (Math.floor(width) * sx | 0) * (Math.floor(height) * sy | 0) > this.maxCanvasPixels;
  5739. }
  5740. }
  5741. const postponeDrawing = drawingDelay >= 0 && drawingDelay < 1000;
  5742. if (postponeDrawing || onlyCssZoom) {
  5743. if (postponeDrawing && !onlyCssZoom && this.renderingState !== RenderingStates.FINISHED) {
  5744. this.cancelRendering({
  5745. keepAnnotationLayer: true,
  5746. keepAnnotationEditorLayer: true,
  5747. keepXfaLayer: true,
  5748. keepTextLayer: true,
  5749. cancelExtraDelay: drawingDelay
  5750. });
  5751. this.renderingState = RenderingStates.FINISHED;
  5752. this.#useThumbnailCanvas.directDrawing = false;
  5753. }
  5754. this.cssTransform({
  5755. redrawAnnotationLayer: true,
  5756. redrawAnnotationEditorLayer: true,
  5757. redrawXfaLayer: true,
  5758. redrawTextLayer: !postponeDrawing,
  5759. hideTextLayer: postponeDrawing
  5760. });
  5761. if (postponeDrawing) {
  5762. return;
  5763. }
  5764. this.eventBus.dispatch("pagerendered", {
  5765. source: this,
  5766. pageNumber: this.id,
  5767. cssTransform: true,
  5768. timestamp: performance.now(),
  5769. error: this.#renderError
  5770. });
  5771. return;
  5772. }
  5773. }
  5774. this.cssTransform({});
  5775. this.reset({
  5776. keepAnnotationLayer: true,
  5777. keepAnnotationEditorLayer: true,
  5778. keepXfaLayer: true,
  5779. keepTextLayer: true,
  5780. keepCanvasWrapper: true
  5781. });
  5782. }
  5783. cancelRendering({
  5784. keepAnnotationLayer = false,
  5785. keepAnnotationEditorLayer = false,
  5786. keepXfaLayer = false,
  5787. keepTextLayer = false,
  5788. cancelExtraDelay = 0
  5789. } = {}) {
  5790. if (this.renderTask) {
  5791. this.renderTask.cancel(cancelExtraDelay);
  5792. this.renderTask = null;
  5793. }
  5794. this.resume = null;
  5795. if (this.textLayer && (!keepTextLayer || !this.textLayer.div)) {
  5796. this.textLayer.cancel();
  5797. this.textLayer = null;
  5798. }
  5799. if (this.annotationLayer && (!keepAnnotationLayer || !this.annotationLayer.div)) {
  5800. this.annotationLayer.cancel();
  5801. this.annotationLayer = null;
  5802. this._annotationCanvasMap = null;
  5803. }
  5804. if (this.structTreeLayer && !this.textLayer) {
  5805. this.structTreeLayer = null;
  5806. }
  5807. if (this.annotationEditorLayer && (!keepAnnotationEditorLayer || !this.annotationEditorLayer.div)) {
  5808. if (this.drawLayer) {
  5809. this.drawLayer.cancel();
  5810. this.drawLayer = null;
  5811. }
  5812. this.annotationEditorLayer.cancel();
  5813. this.annotationEditorLayer = null;
  5814. }
  5815. if (this.xfaLayer && (!keepXfaLayer || !this.xfaLayer.div)) {
  5816. this.xfaLayer.cancel();
  5817. this.xfaLayer = null;
  5818. this._textHighlighter?.disable();
  5819. }
  5820. }
  5821. cssTransform({
  5822. redrawAnnotationLayer = false,
  5823. redrawAnnotationEditorLayer = false,
  5824. redrawXfaLayer = false,
  5825. redrawTextLayer = false,
  5826. hideTextLayer = false
  5827. }) {
  5828. const {
  5829. canvas
  5830. } = this;
  5831. if (!canvas) {
  5832. return;
  5833. }
  5834. const originalViewport = this.#originalViewport;
  5835. if (this.viewport !== originalViewport) {
  5836. const relativeRotation = (360 + this.viewport.rotation - originalViewport.rotation) % 360;
  5837. if (relativeRotation === 90 || relativeRotation === 270) {
  5838. const {
  5839. width,
  5840. height
  5841. } = this.viewport;
  5842. const scaleX = height / width;
  5843. const scaleY = width / height;
  5844. canvas.style.transform = `rotate(${relativeRotation}deg) scale(${scaleX},${scaleY})`;
  5845. } else {
  5846. canvas.style.transform = relativeRotation === 0 ? "" : `rotate(${relativeRotation}deg)`;
  5847. }
  5848. }
  5849. if (redrawAnnotationLayer && this.annotationLayer) {
  5850. this.#renderAnnotationLayer();
  5851. }
  5852. if (redrawAnnotationEditorLayer && this.annotationEditorLayer) {
  5853. if (this.drawLayer) {
  5854. this.#renderDrawLayer();
  5855. }
  5856. this.#renderAnnotationEditorLayer();
  5857. }
  5858. if (redrawXfaLayer && this.xfaLayer) {
  5859. this.#renderXfaLayer();
  5860. }
  5861. if (this.textLayer) {
  5862. if (hideTextLayer) {
  5863. this.textLayer.hide();
  5864. this.structTreeLayer?.hide();
  5865. } else if (redrawTextLayer) {
  5866. this.#renderTextLayer();
  5867. }
  5868. }
  5869. }
  5870. get width() {
  5871. return this.viewport.width;
  5872. }
  5873. get height() {
  5874. return this.viewport.height;
  5875. }
  5876. getPagePoint(x, y) {
  5877. return this.viewport.convertToPdfPoint(x, y);
  5878. }
  5879. async #finishRenderTask(renderTask, error = null) {
  5880. if (renderTask === this.renderTask) {
  5881. this.renderTask = null;
  5882. }
  5883. if (error instanceof RenderingCancelledException) {
  5884. this.#renderError = null;
  5885. return;
  5886. }
  5887. this.#renderError = error;
  5888. this.renderingState = RenderingStates.FINISHED;
  5889. this.#useThumbnailCanvas.regularAnnotations = !renderTask.separateAnnots;
  5890. this.eventBus.dispatch("pagerendered", {
  5891. source: this,
  5892. pageNumber: this.id,
  5893. cssTransform: false,
  5894. timestamp: performance.now(),
  5895. error: this.#renderError
  5896. });
  5897. if (error) {
  5898. throw error;
  5899. }
  5900. }
  5901. async draw() {
  5902. if (this.renderingState !== RenderingStates.INITIAL) {
  5903. console.error("Must be in new state before drawing");
  5904. this.reset();
  5905. }
  5906. const {
  5907. div,
  5908. l10n,
  5909. pageColors,
  5910. pdfPage,
  5911. viewport
  5912. } = this;
  5913. if (!pdfPage) {
  5914. this.renderingState = RenderingStates.FINISHED;
  5915. throw new Error("pdfPage is not loaded");
  5916. }
  5917. this.renderingState = RenderingStates.RUNNING;
  5918. let canvasWrapper = this.#canvasWrapper;
  5919. if (!canvasWrapper) {
  5920. canvasWrapper = this.#canvasWrapper = document.createElement("div");
  5921. canvasWrapper.classList.add("canvasWrapper");
  5922. this.#addLayer(canvasWrapper, "canvasWrapper");
  5923. }
  5924. if (!this.textLayer && this.#textLayerMode !== TextLayerMode.DISABLE && !pdfPage.isPureXfa) {
  5925. this._accessibilityManager ||= new TextAccessibilityManager();
  5926. this.textLayer = new TextLayerBuilder({
  5927. pdfPage,
  5928. highlighter: this._textHighlighter,
  5929. accessibilityManager: this._accessibilityManager,
  5930. enablePermissions: this.#textLayerMode === TextLayerMode.ENABLE_PERMISSIONS,
  5931. onAppend: textLayerDiv => {
  5932. this.l10n.pause();
  5933. this.#addLayer(textLayerDiv, "textLayer");
  5934. this.l10n.resume();
  5935. }
  5936. });
  5937. }
  5938. if (!this.annotationLayer && this.#annotationMode !== AnnotationMode.DISABLE) {
  5939. const {
  5940. annotationStorage,
  5941. annotationEditorUIManager,
  5942. downloadManager,
  5943. enableScripting,
  5944. fieldObjectsPromise,
  5945. hasJSActionsPromise,
  5946. linkService
  5947. } = this.#layerProperties;
  5948. this._annotationCanvasMap ||= new Map();
  5949. this.annotationLayer = new AnnotationLayerBuilder({
  5950. pdfPage,
  5951. annotationStorage,
  5952. imageResourcesPath: this.imageResourcesPath,
  5953. renderForms: this.#annotationMode === AnnotationMode.ENABLE_FORMS,
  5954. linkService,
  5955. downloadManager,
  5956. enableScripting,
  5957. hasJSActionsPromise,
  5958. fieldObjectsPromise,
  5959. annotationCanvasMap: this._annotationCanvasMap,
  5960. accessibilityManager: this._accessibilityManager,
  5961. annotationEditorUIManager,
  5962. onAppend: annotationLayerDiv => {
  5963. this.#addLayer(annotationLayerDiv, "annotationLayer");
  5964. }
  5965. });
  5966. }
  5967. const renderContinueCallback = cont => {
  5968. showCanvas?.(false);
  5969. if (this.renderingQueue && !this.renderingQueue.isHighestPriority(this)) {
  5970. this.renderingState = RenderingStates.PAUSED;
  5971. this.resume = () => {
  5972. this.renderingState = RenderingStates.RUNNING;
  5973. cont();
  5974. };
  5975. return;
  5976. }
  5977. cont();
  5978. };
  5979. const {
  5980. width,
  5981. height
  5982. } = viewport;
  5983. const canvas = document.createElement("canvas");
  5984. canvas.setAttribute("role", "presentation");
  5985. const hasHCM = !!(pageColors?.background && pageColors?.foreground);
  5986. const prevCanvas = this.canvas;
  5987. const updateOnFirstShow = !prevCanvas && !hasHCM;
  5988. this.canvas = canvas;
  5989. this.#originalViewport = viewport;
  5990. let showCanvas = isLastShow => {
  5991. if (updateOnFirstShow) {
  5992. canvasWrapper.prepend(canvas);
  5993. showCanvas = null;
  5994. return;
  5995. }
  5996. if (!isLastShow) {
  5997. return;
  5998. }
  5999. if (prevCanvas) {
  6000. prevCanvas.replaceWith(canvas);
  6001. prevCanvas.width = prevCanvas.height = 0;
  6002. } else {
  6003. canvasWrapper.prepend(canvas);
  6004. }
  6005. showCanvas = null;
  6006. };
  6007. const ctx = canvas.getContext("2d", {
  6008. alpha: false,
  6009. willReadFrequently: !this.#enableHWA
  6010. });
  6011. const outputScale = this.outputScale = new OutputScale();
  6012. if (this.maxCanvasPixels === 0) {
  6013. const invScale = 1 / this.scale;
  6014. outputScale.sx *= invScale;
  6015. outputScale.sy *= invScale;
  6016. this.#hasRestrictedScaling = true;
  6017. } else if (this.maxCanvasPixels > 0) {
  6018. const pixelsInViewport = width * height;
  6019. const maxScale = Math.sqrt(this.maxCanvasPixels / pixelsInViewport);
  6020. if (outputScale.sx > maxScale || outputScale.sy > maxScale) {
  6021. outputScale.sx = maxScale;
  6022. outputScale.sy = maxScale;
  6023. this.#hasRestrictedScaling = true;
  6024. } else {
  6025. this.#hasRestrictedScaling = false;
  6026. }
  6027. }
  6028. const sfx = approximateFraction(outputScale.sx);
  6029. const sfy = approximateFraction(outputScale.sy);
  6030. const canvasWidth = canvas.width = floorToDivide(calcRound(width * outputScale.sx), sfx[0]);
  6031. const canvasHeight = canvas.height = floorToDivide(calcRound(height * outputScale.sy), sfy[0]);
  6032. const pageWidth = floorToDivide(calcRound(width), sfx[1]);
  6033. const pageHeight = floorToDivide(calcRound(height), sfy[1]);
  6034. outputScale.sx = canvasWidth / pageWidth;
  6035. outputScale.sy = canvasHeight / pageHeight;
  6036. if (this.#scaleRoundX !== sfx[1]) {
  6037. div.style.setProperty("--scale-round-x", `${sfx[1]}px`);
  6038. this.#scaleRoundX = sfx[1];
  6039. }
  6040. if (this.#scaleRoundY !== sfy[1]) {
  6041. div.style.setProperty("--scale-round-y", `${sfy[1]}px`);
  6042. this.#scaleRoundY = sfy[1];
  6043. }
  6044. const transform = outputScale.scaled ? [outputScale.sx, 0, 0, outputScale.sy, 0, 0] : null;
  6045. const renderContext = {
  6046. canvasContext: ctx,
  6047. transform,
  6048. viewport,
  6049. annotationMode: this.#annotationMode,
  6050. optionalContentConfigPromise: this._optionalContentConfigPromise,
  6051. annotationCanvasMap: this._annotationCanvasMap,
  6052. pageColors,
  6053. isEditing: this.#isEditing
  6054. };
  6055. const renderTask = this.renderTask = pdfPage.render(renderContext);
  6056. renderTask.onContinue = renderContinueCallback;
  6057. const resultPromise = renderTask.promise.then(async () => {
  6058. showCanvas?.(true);
  6059. await this.#finishRenderTask(renderTask);
  6060. this.structTreeLayer ||= new StructTreeLayerBuilder(pdfPage, viewport.rawDims);
  6061. this.#renderTextLayer();
  6062. if (this.annotationLayer) {
  6063. await this.#renderAnnotationLayer();
  6064. }
  6065. const {
  6066. annotationEditorUIManager
  6067. } = this.#layerProperties;
  6068. if (!annotationEditorUIManager) {
  6069. return;
  6070. }
  6071. this.drawLayer ||= new DrawLayerBuilder({
  6072. pageIndex: this.id
  6073. });
  6074. await this.#renderDrawLayer();
  6075. this.drawLayer.setParent(canvasWrapper);
  6076. this.annotationEditorLayer ||= new AnnotationEditorLayerBuilder({
  6077. uiManager: annotationEditorUIManager,
  6078. pdfPage,
  6079. l10n,
  6080. structTreeLayer: this.structTreeLayer,
  6081. accessibilityManager: this._accessibilityManager,
  6082. annotationLayer: this.annotationLayer?.annotationLayer,
  6083. textLayer: this.textLayer,
  6084. drawLayer: this.drawLayer.getDrawLayer(),
  6085. onAppend: annotationEditorLayerDiv => {
  6086. this.#addLayer(annotationEditorLayerDiv, "annotationEditorLayer");
  6087. }
  6088. });
  6089. this.#renderAnnotationEditorLayer();
  6090. }, error => {
  6091. if (!(error instanceof RenderingCancelledException)) {
  6092. showCanvas?.(true);
  6093. } else {
  6094. prevCanvas?.remove();
  6095. this.#resetCanvas();
  6096. }
  6097. return this.#finishRenderTask(renderTask, error);
  6098. });
  6099. if (pdfPage.isPureXfa) {
  6100. if (!this.xfaLayer) {
  6101. const {
  6102. annotationStorage,
  6103. linkService
  6104. } = this.#layerProperties;
  6105. this.xfaLayer = new XfaLayerBuilder({
  6106. pdfPage,
  6107. annotationStorage,
  6108. linkService
  6109. });
  6110. }
  6111. this.#renderXfaLayer();
  6112. }
  6113. div.setAttribute("data-loaded", true);
  6114. this.eventBus.dispatch("pagerender", {
  6115. source: this,
  6116. pageNumber: this.id
  6117. });
  6118. return resultPromise;
  6119. }
  6120. setPageLabel(label) {
  6121. this.pageLabel = typeof label === "string" ? label : null;
  6122. this.div.setAttribute("data-l10n-args", JSON.stringify({
  6123. page: this.pageLabel ?? this.id
  6124. }));
  6125. if (this.pageLabel !== null) {
  6126. this.div.setAttribute("data-page-label", this.pageLabel);
  6127. } else {
  6128. this.div.removeAttribute("data-page-label");
  6129. }
  6130. }
  6131. get thumbnailCanvas() {
  6132. const {
  6133. directDrawing,
  6134. initialOptionalContent,
  6135. regularAnnotations
  6136. } = this.#useThumbnailCanvas;
  6137. return directDrawing && initialOptionalContent && regularAnnotations ? this.canvas : null;
  6138. }
  6139. }
  6140. ;// ./web/generic_scripting.js
  6141. async function docProperties(pdfDocument) {
  6142. const url = "",
  6143. baseUrl = url.split("#", 1)[0];
  6144. let {
  6145. info,
  6146. metadata,
  6147. contentDispositionFilename,
  6148. contentLength
  6149. } = await pdfDocument.getMetadata();
  6150. if (!contentLength) {
  6151. const {
  6152. length
  6153. } = await pdfDocument.getDownloadInfo();
  6154. contentLength = length;
  6155. }
  6156. return {
  6157. ...info,
  6158. baseURL: baseUrl,
  6159. filesize: contentLength,
  6160. filename: contentDispositionFilename || getPdfFilenameFromUrl(url),
  6161. metadata: metadata?.getRaw(),
  6162. authors: metadata?.get("dc:creator"),
  6163. numPages: pdfDocument.numPages,
  6164. URL: url
  6165. };
  6166. }
  6167. class GenericScripting {
  6168. constructor(sandboxBundleSrc) {
  6169. this._ready = new Promise((resolve, reject) => {
  6170. const sandbox = import(/*webpackIgnore: true*/sandboxBundleSrc);
  6171. sandbox.then(pdfjsSandbox => {
  6172. resolve(pdfjsSandbox.QuickJSSandbox());
  6173. }).catch(reject);
  6174. });
  6175. }
  6176. async createSandbox(data) {
  6177. const sandbox = await this._ready;
  6178. sandbox.create(data);
  6179. }
  6180. async dispatchEventInSandbox(event) {
  6181. const sandbox = await this._ready;
  6182. setTimeout(() => sandbox.dispatchEvent(event), 0);
  6183. }
  6184. async destroySandbox() {
  6185. const sandbox = await this._ready;
  6186. sandbox.nukeSandbox();
  6187. }
  6188. }
  6189. ;// ./web/pdf_scripting_manager.js
  6190. class PDFScriptingManager {
  6191. #closeCapability = null;
  6192. #destroyCapability = null;
  6193. #docProperties = null;
  6194. #eventAbortController = null;
  6195. #eventBus = null;
  6196. #externalServices = null;
  6197. #pdfDocument = null;
  6198. #pdfViewer = null;
  6199. #ready = false;
  6200. #scripting = null;
  6201. #willPrintCapability = null;
  6202. constructor({
  6203. eventBus,
  6204. externalServices = null,
  6205. docProperties = null
  6206. }) {
  6207. this.#eventBus = eventBus;
  6208. this.#externalServices = externalServices;
  6209. this.#docProperties = docProperties;
  6210. }
  6211. setViewer(pdfViewer) {
  6212. this.#pdfViewer = pdfViewer;
  6213. }
  6214. async setDocument(pdfDocument) {
  6215. if (this.#pdfDocument) {
  6216. await this.#destroyScripting();
  6217. }
  6218. this.#pdfDocument = pdfDocument;
  6219. if (!pdfDocument) {
  6220. return;
  6221. }
  6222. const [objects, calculationOrder, docActions] = await Promise.all([pdfDocument.getFieldObjects(), pdfDocument.getCalculationOrderIds(), pdfDocument.getJSActions()]);
  6223. if (!objects && !docActions) {
  6224. await this.#destroyScripting();
  6225. return;
  6226. }
  6227. if (pdfDocument !== this.#pdfDocument) {
  6228. return;
  6229. }
  6230. try {
  6231. this.#scripting = this.#initScripting();
  6232. } catch (error) {
  6233. console.error("setDocument:", error);
  6234. await this.#destroyScripting();
  6235. return;
  6236. }
  6237. const eventBus = this.#eventBus;
  6238. this.#eventAbortController = new AbortController();
  6239. const {
  6240. signal
  6241. } = this.#eventAbortController;
  6242. eventBus._on("updatefromsandbox", event => {
  6243. if (event?.source === window) {
  6244. this.#updateFromSandbox(event.detail);
  6245. }
  6246. }, {
  6247. signal
  6248. });
  6249. eventBus._on("dispatcheventinsandbox", event => {
  6250. this.#scripting?.dispatchEventInSandbox(event.detail);
  6251. }, {
  6252. signal
  6253. });
  6254. eventBus._on("pagechanging", ({
  6255. pageNumber,
  6256. previous
  6257. }) => {
  6258. if (pageNumber === previous) {
  6259. return;
  6260. }
  6261. this.#dispatchPageClose(previous);
  6262. this.#dispatchPageOpen(pageNumber);
  6263. }, {
  6264. signal
  6265. });
  6266. eventBus._on("pagerendered", ({
  6267. pageNumber
  6268. }) => {
  6269. if (!this._pageOpenPending.has(pageNumber)) {
  6270. return;
  6271. }
  6272. if (pageNumber !== this.#pdfViewer.currentPageNumber) {
  6273. return;
  6274. }
  6275. this.#dispatchPageOpen(pageNumber);
  6276. }, {
  6277. signal
  6278. });
  6279. eventBus._on("pagesdestroy", async () => {
  6280. await this.#dispatchPageClose(this.#pdfViewer.currentPageNumber);
  6281. await this.#scripting?.dispatchEventInSandbox({
  6282. id: "doc",
  6283. name: "WillClose"
  6284. });
  6285. this.#closeCapability?.resolve();
  6286. }, {
  6287. signal
  6288. });
  6289. try {
  6290. const docProperties = await this.#docProperties(pdfDocument);
  6291. if (pdfDocument !== this.#pdfDocument) {
  6292. return;
  6293. }
  6294. await this.#scripting.createSandbox({
  6295. objects,
  6296. calculationOrder,
  6297. appInfo: {
  6298. platform: navigator.platform,
  6299. language: navigator.language
  6300. },
  6301. docInfo: {
  6302. ...docProperties,
  6303. actions: docActions
  6304. }
  6305. });
  6306. eventBus.dispatch("sandboxcreated", {
  6307. source: this
  6308. });
  6309. } catch (error) {
  6310. console.error("setDocument:", error);
  6311. await this.#destroyScripting();
  6312. return;
  6313. }
  6314. await this.#scripting?.dispatchEventInSandbox({
  6315. id: "doc",
  6316. name: "Open"
  6317. });
  6318. await this.#dispatchPageOpen(this.#pdfViewer.currentPageNumber, true);
  6319. Promise.resolve().then(() => {
  6320. if (pdfDocument === this.#pdfDocument) {
  6321. this.#ready = true;
  6322. }
  6323. });
  6324. }
  6325. async dispatchWillSave() {
  6326. return this.#scripting?.dispatchEventInSandbox({
  6327. id: "doc",
  6328. name: "WillSave"
  6329. });
  6330. }
  6331. async dispatchDidSave() {
  6332. return this.#scripting?.dispatchEventInSandbox({
  6333. id: "doc",
  6334. name: "DidSave"
  6335. });
  6336. }
  6337. async dispatchWillPrint() {
  6338. if (!this.#scripting) {
  6339. return;
  6340. }
  6341. await this.#willPrintCapability?.promise;
  6342. this.#willPrintCapability = Promise.withResolvers();
  6343. try {
  6344. await this.#scripting.dispatchEventInSandbox({
  6345. id: "doc",
  6346. name: "WillPrint"
  6347. });
  6348. } catch (ex) {
  6349. this.#willPrintCapability.resolve();
  6350. this.#willPrintCapability = null;
  6351. throw ex;
  6352. }
  6353. await this.#willPrintCapability.promise;
  6354. }
  6355. async dispatchDidPrint() {
  6356. return this.#scripting?.dispatchEventInSandbox({
  6357. id: "doc",
  6358. name: "DidPrint"
  6359. });
  6360. }
  6361. get destroyPromise() {
  6362. return this.#destroyCapability?.promise || null;
  6363. }
  6364. get ready() {
  6365. return this.#ready;
  6366. }
  6367. get _pageOpenPending() {
  6368. return shadow(this, "_pageOpenPending", new Set());
  6369. }
  6370. get _visitedPages() {
  6371. return shadow(this, "_visitedPages", new Map());
  6372. }
  6373. async #updateFromSandbox(detail) {
  6374. const pdfViewer = this.#pdfViewer;
  6375. const isInPresentationMode = pdfViewer.isInPresentationMode || pdfViewer.isChangingPresentationMode;
  6376. const {
  6377. id,
  6378. siblings,
  6379. command,
  6380. value
  6381. } = detail;
  6382. if (!id) {
  6383. switch (command) {
  6384. case "clear":
  6385. console.clear();
  6386. break;
  6387. case "error":
  6388. console.error(value);
  6389. break;
  6390. case "layout":
  6391. if (!isInPresentationMode) {
  6392. const modes = apiPageLayoutToViewerModes(value);
  6393. pdfViewer.spreadMode = modes.spreadMode;
  6394. }
  6395. break;
  6396. case "page-num":
  6397. pdfViewer.currentPageNumber = value + 1;
  6398. break;
  6399. case "print":
  6400. await pdfViewer.pagesPromise;
  6401. this.#eventBus.dispatch("print", {
  6402. source: this
  6403. });
  6404. break;
  6405. case "println":
  6406. console.log(value);
  6407. break;
  6408. case "zoom":
  6409. if (!isInPresentationMode) {
  6410. pdfViewer.currentScaleValue = value;
  6411. }
  6412. break;
  6413. case "SaveAs":
  6414. this.#eventBus.dispatch("download", {
  6415. source: this
  6416. });
  6417. break;
  6418. case "FirstPage":
  6419. pdfViewer.currentPageNumber = 1;
  6420. break;
  6421. case "LastPage":
  6422. pdfViewer.currentPageNumber = pdfViewer.pagesCount;
  6423. break;
  6424. case "NextPage":
  6425. pdfViewer.nextPage();
  6426. break;
  6427. case "PrevPage":
  6428. pdfViewer.previousPage();
  6429. break;
  6430. case "ZoomViewIn":
  6431. if (!isInPresentationMode) {
  6432. pdfViewer.increaseScale();
  6433. }
  6434. break;
  6435. case "ZoomViewOut":
  6436. if (!isInPresentationMode) {
  6437. pdfViewer.decreaseScale();
  6438. }
  6439. break;
  6440. case "WillPrintFinished":
  6441. this.#willPrintCapability?.resolve();
  6442. this.#willPrintCapability = null;
  6443. break;
  6444. }
  6445. return;
  6446. }
  6447. if (isInPresentationMode && detail.focus) {
  6448. return;
  6449. }
  6450. delete detail.id;
  6451. delete detail.siblings;
  6452. const ids = siblings ? [id, ...siblings] : [id];
  6453. for (const elementId of ids) {
  6454. const element = document.querySelector(`[data-element-id="${elementId}"]`);
  6455. if (element) {
  6456. element.dispatchEvent(new CustomEvent("updatefromsandbox", {
  6457. detail
  6458. }));
  6459. } else {
  6460. this.#pdfDocument?.annotationStorage.setValue(elementId, detail);
  6461. }
  6462. }
  6463. }
  6464. async #dispatchPageOpen(pageNumber, initialize = false) {
  6465. const pdfDocument = this.#pdfDocument,
  6466. visitedPages = this._visitedPages;
  6467. if (initialize) {
  6468. this.#closeCapability = Promise.withResolvers();
  6469. }
  6470. if (!this.#closeCapability) {
  6471. return;
  6472. }
  6473. const pageView = this.#pdfViewer.getPageView(pageNumber - 1);
  6474. if (pageView?.renderingState !== RenderingStates.FINISHED) {
  6475. this._pageOpenPending.add(pageNumber);
  6476. return;
  6477. }
  6478. this._pageOpenPending.delete(pageNumber);
  6479. const actionsPromise = (async () => {
  6480. const actions = await (!visitedPages.has(pageNumber) ? pageView.pdfPage?.getJSActions() : null);
  6481. if (pdfDocument !== this.#pdfDocument) {
  6482. return;
  6483. }
  6484. await this.#scripting?.dispatchEventInSandbox({
  6485. id: "page",
  6486. name: "PageOpen",
  6487. pageNumber,
  6488. actions
  6489. });
  6490. })();
  6491. visitedPages.set(pageNumber, actionsPromise);
  6492. }
  6493. async #dispatchPageClose(pageNumber) {
  6494. const pdfDocument = this.#pdfDocument,
  6495. visitedPages = this._visitedPages;
  6496. if (!this.#closeCapability) {
  6497. return;
  6498. }
  6499. if (this._pageOpenPending.has(pageNumber)) {
  6500. return;
  6501. }
  6502. const actionsPromise = visitedPages.get(pageNumber);
  6503. if (!actionsPromise) {
  6504. return;
  6505. }
  6506. visitedPages.set(pageNumber, null);
  6507. await actionsPromise;
  6508. if (pdfDocument !== this.#pdfDocument) {
  6509. return;
  6510. }
  6511. await this.#scripting?.dispatchEventInSandbox({
  6512. id: "page",
  6513. name: "PageClose",
  6514. pageNumber
  6515. });
  6516. }
  6517. #initScripting() {
  6518. this.#destroyCapability = Promise.withResolvers();
  6519. if (this.#scripting) {
  6520. throw new Error("#initScripting: Scripting already exists.");
  6521. }
  6522. return this.#externalServices.createScripting();
  6523. }
  6524. async #destroyScripting() {
  6525. if (!this.#scripting) {
  6526. this.#pdfDocument = null;
  6527. this.#destroyCapability?.resolve();
  6528. return;
  6529. }
  6530. if (this.#closeCapability) {
  6531. await Promise.race([this.#closeCapability.promise, new Promise(resolve => {
  6532. setTimeout(resolve, 1000);
  6533. })]).catch(() => {});
  6534. this.#closeCapability = null;
  6535. }
  6536. this.#pdfDocument = null;
  6537. try {
  6538. await this.#scripting.destroySandbox();
  6539. } catch {}
  6540. this.#willPrintCapability?.reject(new Error("Scripting destroyed."));
  6541. this.#willPrintCapability = null;
  6542. this.#eventAbortController?.abort();
  6543. this.#eventAbortController = null;
  6544. this._pageOpenPending.clear();
  6545. this._visitedPages.clear();
  6546. this.#scripting = null;
  6547. this.#ready = false;
  6548. this.#destroyCapability?.resolve();
  6549. }
  6550. }
  6551. ;// ./web/pdf_scripting_manager.component.js
  6552. class PDFScriptingManagerComponents extends PDFScriptingManager {
  6553. constructor(options) {
  6554. if (!options.externalServices) {
  6555. window.addEventListener("updatefromsandbox", event => {
  6556. options.eventBus.dispatch("updatefromsandbox", {
  6557. source: window,
  6558. detail: event.detail
  6559. });
  6560. });
  6561. }
  6562. options.externalServices ||= {
  6563. createScripting: () => new GenericScripting(options.sandboxBundleSrc)
  6564. };
  6565. options.docProperties ||= pdfDocument => docProperties(pdfDocument);
  6566. super(options);
  6567. }
  6568. }
  6569. ;// ./web/pdf_rendering_queue.js
  6570. const CLEANUP_TIMEOUT = 30000;
  6571. class PDFRenderingQueue {
  6572. constructor() {
  6573. this.pdfViewer = null;
  6574. this.pdfThumbnailViewer = null;
  6575. this.onIdle = null;
  6576. this.highestPriorityPage = null;
  6577. this.idleTimeout = null;
  6578. this.printing = false;
  6579. this.isThumbnailViewEnabled = false;
  6580. Object.defineProperty(this, "hasViewer", {
  6581. value: () => !!this.pdfViewer
  6582. });
  6583. }
  6584. setViewer(pdfViewer) {
  6585. this.pdfViewer = pdfViewer;
  6586. }
  6587. setThumbnailViewer(pdfThumbnailViewer) {
  6588. this.pdfThumbnailViewer = pdfThumbnailViewer;
  6589. }
  6590. isHighestPriority(view) {
  6591. return this.highestPriorityPage === view.renderingId;
  6592. }
  6593. renderHighestPriority(currentlyVisiblePages) {
  6594. if (this.idleTimeout) {
  6595. clearTimeout(this.idleTimeout);
  6596. this.idleTimeout = null;
  6597. }
  6598. if (this.pdfViewer.forceRendering(currentlyVisiblePages)) {
  6599. return;
  6600. }
  6601. if (this.isThumbnailViewEnabled && this.pdfThumbnailViewer?.forceRendering()) {
  6602. return;
  6603. }
  6604. if (this.printing) {
  6605. return;
  6606. }
  6607. if (this.onIdle) {
  6608. this.idleTimeout = setTimeout(this.onIdle.bind(this), CLEANUP_TIMEOUT);
  6609. }
  6610. }
  6611. getHighestPriority(visible, views, scrolledDown, preRenderExtra = false) {
  6612. const visibleViews = visible.views,
  6613. numVisible = visibleViews.length;
  6614. if (numVisible === 0) {
  6615. return null;
  6616. }
  6617. for (let i = 0; i < numVisible; i++) {
  6618. const view = visibleViews[i].view;
  6619. if (!this.isViewFinished(view)) {
  6620. return view;
  6621. }
  6622. }
  6623. const firstId = visible.first.id,
  6624. lastId = visible.last.id;
  6625. if (lastId - firstId + 1 > numVisible) {
  6626. const visibleIds = visible.ids;
  6627. for (let i = 1, ii = lastId - firstId; i < ii; i++) {
  6628. const holeId = scrolledDown ? firstId + i : lastId - i;
  6629. if (visibleIds.has(holeId)) {
  6630. continue;
  6631. }
  6632. const holeView = views[holeId - 1];
  6633. if (!this.isViewFinished(holeView)) {
  6634. return holeView;
  6635. }
  6636. }
  6637. }
  6638. let preRenderIndex = scrolledDown ? lastId : firstId - 2;
  6639. let preRenderView = views[preRenderIndex];
  6640. if (preRenderView && !this.isViewFinished(preRenderView)) {
  6641. return preRenderView;
  6642. }
  6643. if (preRenderExtra) {
  6644. preRenderIndex += scrolledDown ? 1 : -1;
  6645. preRenderView = views[preRenderIndex];
  6646. if (preRenderView && !this.isViewFinished(preRenderView)) {
  6647. return preRenderView;
  6648. }
  6649. }
  6650. return null;
  6651. }
  6652. isViewFinished(view) {
  6653. return view.renderingState === RenderingStates.FINISHED;
  6654. }
  6655. renderView(view) {
  6656. switch (view.renderingState) {
  6657. case RenderingStates.FINISHED:
  6658. return false;
  6659. case RenderingStates.PAUSED:
  6660. this.highestPriorityPage = view.renderingId;
  6661. view.resume();
  6662. break;
  6663. case RenderingStates.RUNNING:
  6664. this.highestPriorityPage = view.renderingId;
  6665. break;
  6666. case RenderingStates.INITIAL:
  6667. this.highestPriorityPage = view.renderingId;
  6668. view.draw().finally(() => {
  6669. this.renderHighestPriority();
  6670. }).catch(reason => {
  6671. if (reason instanceof RenderingCancelledException) {
  6672. return;
  6673. }
  6674. console.error("renderView:", reason);
  6675. });
  6676. break;
  6677. }
  6678. return true;
  6679. }
  6680. }
  6681. ;// ./web/pdf_viewer.js
  6682. const DEFAULT_CACHE_SIZE = 10;
  6683. const PagesCountLimit = {
  6684. FORCE_SCROLL_MODE_PAGE: 10000,
  6685. FORCE_LAZY_PAGE_INIT: 5000,
  6686. PAUSE_EAGER_PAGE_INIT: 250
  6687. };
  6688. function isValidAnnotationEditorMode(mode) {
  6689. return Object.values(AnnotationEditorType).includes(mode) && mode !== AnnotationEditorType.DISABLE;
  6690. }
  6691. class PDFPageViewBuffer {
  6692. #buf = new Set();
  6693. #size = 0;
  6694. constructor(size) {
  6695. this.#size = size;
  6696. }
  6697. push(view) {
  6698. const buf = this.#buf;
  6699. if (buf.has(view)) {
  6700. buf.delete(view);
  6701. }
  6702. buf.add(view);
  6703. if (buf.size > this.#size) {
  6704. this.#destroyFirstView();
  6705. }
  6706. }
  6707. resize(newSize, idsToKeep = null) {
  6708. this.#size = newSize;
  6709. const buf = this.#buf;
  6710. if (idsToKeep) {
  6711. const ii = buf.size;
  6712. let i = 1;
  6713. for (const view of buf) {
  6714. if (idsToKeep.has(view.id)) {
  6715. buf.delete(view);
  6716. buf.add(view);
  6717. }
  6718. if (++i > ii) {
  6719. break;
  6720. }
  6721. }
  6722. }
  6723. while (buf.size > this.#size) {
  6724. this.#destroyFirstView();
  6725. }
  6726. }
  6727. has(view) {
  6728. return this.#buf.has(view);
  6729. }
  6730. [Symbol.iterator]() {
  6731. return this.#buf.keys();
  6732. }
  6733. #destroyFirstView() {
  6734. const firstView = this.#buf.keys().next().value;
  6735. firstView?.destroy();
  6736. this.#buf.delete(firstView);
  6737. }
  6738. }
  6739. class PDFViewer {
  6740. #buffer = null;
  6741. #altTextManager = null;
  6742. #annotationEditorHighlightColors = null;
  6743. #annotationEditorMode = AnnotationEditorType.NONE;
  6744. #annotationEditorUIManager = null;
  6745. #annotationMode = AnnotationMode.ENABLE_FORMS;
  6746. #containerTopLeft = null;
  6747. #editorUndoBar = null;
  6748. #enableHWA = false;
  6749. #enableHighlightFloatingButton = false;
  6750. #enablePermissions = false;
  6751. #enableUpdatedAddImage = false;
  6752. #enableNewAltTextWhenAddingImage = false;
  6753. #eventAbortController = null;
  6754. #mlManager = null;
  6755. #switchAnnotationEditorModeAC = null;
  6756. #switchAnnotationEditorModeTimeoutId = null;
  6757. #getAllTextInProgress = false;
  6758. #hiddenCopyElement = null;
  6759. #interruptCopyCondition = false;
  6760. #previousContainerHeight = 0;
  6761. #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this));
  6762. #scrollModePageState = null;
  6763. #scaleTimeoutId = null;
  6764. #supportsPinchToZoom = true;
  6765. #textLayerMode = TextLayerMode.ENABLE;
  6766. constructor(options) {
  6767. const viewerVersion = "4.10.38";
  6768. if (version !== viewerVersion) {
  6769. throw new Error(`The API version "${version}" does not match the Viewer version "${viewerVersion}".`);
  6770. }
  6771. this.container = options.container;
  6772. this.viewer = options.viewer || options.container.firstElementChild;
  6773. if (this.container?.tagName !== "DIV" || this.viewer?.tagName !== "DIV") {
  6774. throw new Error("Invalid `container` and/or `viewer` option.");
  6775. }
  6776. if (this.container.offsetParent && getComputedStyle(this.container).position !== "absolute") {
  6777. throw new Error("The `container` must be absolutely positioned.");
  6778. }
  6779. this.#resizeObserver.observe(this.container);
  6780. this.eventBus = options.eventBus;
  6781. this.linkService = options.linkService || new SimpleLinkService();
  6782. this.downloadManager = options.downloadManager || null;
  6783. this.findController = options.findController || null;
  6784. this.#altTextManager = options.altTextManager || null;
  6785. this.#editorUndoBar = options.editorUndoBar || null;
  6786. if (this.findController) {
  6787. this.findController.onIsPageVisible = pageNumber => this._getVisiblePages().ids.has(pageNumber);
  6788. }
  6789. this._scriptingManager = options.scriptingManager || null;
  6790. this.#textLayerMode = options.textLayerMode ?? TextLayerMode.ENABLE;
  6791. this.#annotationMode = options.annotationMode ?? AnnotationMode.ENABLE_FORMS;
  6792. this.#annotationEditorMode = options.annotationEditorMode ?? AnnotationEditorType.NONE;
  6793. this.#annotationEditorHighlightColors = options.annotationEditorHighlightColors || null;
  6794. this.#enableHighlightFloatingButton = options.enableHighlightFloatingButton === true;
  6795. this.#enableUpdatedAddImage = options.enableUpdatedAddImage === true;
  6796. this.#enableNewAltTextWhenAddingImage = options.enableNewAltTextWhenAddingImage === true;
  6797. this.imageResourcesPath = options.imageResourcesPath || "";
  6798. this.enablePrintAutoRotate = options.enablePrintAutoRotate || false;
  6799. this.removePageBorders = options.removePageBorders || false;
  6800. this.maxCanvasPixels = options.maxCanvasPixels;
  6801. this.l10n = options.l10n;
  6802. this.l10n ||= new genericl10n_GenericL10n();
  6803. this.#enablePermissions = options.enablePermissions || false;
  6804. this.pageColors = options.pageColors || null;
  6805. this.#mlManager = options.mlManager || null;
  6806. this.#enableHWA = options.enableHWA || false;
  6807. this.#supportsPinchToZoom = options.supportsPinchToZoom !== false;
  6808. this.defaultRenderingQueue = !options.renderingQueue;
  6809. if (this.defaultRenderingQueue) {
  6810. this.renderingQueue = new PDFRenderingQueue();
  6811. this.renderingQueue.setViewer(this);
  6812. } else {
  6813. this.renderingQueue = options.renderingQueue;
  6814. }
  6815. const {
  6816. abortSignal
  6817. } = options;
  6818. abortSignal?.addEventListener("abort", () => {
  6819. this.#resizeObserver.disconnect();
  6820. this.#resizeObserver = null;
  6821. }, {
  6822. once: true
  6823. });
  6824. this.scroll = watchScroll(this.container, this._scrollUpdate.bind(this), abortSignal);
  6825. this.presentationModeState = PresentationModeState.UNKNOWN;
  6826. this._resetView();
  6827. if (this.removePageBorders) {
  6828. this.viewer.classList.add("removePageBorders");
  6829. }
  6830. this.#updateContainerHeightCss();
  6831. this.eventBus._on("thumbnailrendered", ({
  6832. pageNumber,
  6833. pdfPage
  6834. }) => {
  6835. const pageView = this._pages[pageNumber - 1];
  6836. if (!this.#buffer.has(pageView)) {
  6837. pdfPage?.cleanup();
  6838. }
  6839. });
  6840. if (!options.l10n) {
  6841. this.l10n.translate(this.container);
  6842. }
  6843. }
  6844. get pagesCount() {
  6845. return this._pages.length;
  6846. }
  6847. getPageView(index) {
  6848. return this._pages[index];
  6849. }
  6850. getCachedPageViews() {
  6851. return new Set(this.#buffer);
  6852. }
  6853. get pageViewsReady() {
  6854. return this._pages.every(pageView => pageView?.pdfPage);
  6855. }
  6856. get renderForms() {
  6857. return this.#annotationMode === AnnotationMode.ENABLE_FORMS;
  6858. }
  6859. get enableScripting() {
  6860. return !!this._scriptingManager;
  6861. }
  6862. get currentPageNumber() {
  6863. return this._currentPageNumber;
  6864. }
  6865. set currentPageNumber(val) {
  6866. if (!Number.isInteger(val)) {
  6867. throw new Error("Invalid page number.");
  6868. }
  6869. if (!this.pdfDocument) {
  6870. return;
  6871. }
  6872. if (!this._setCurrentPageNumber(val, true)) {
  6873. console.error(`currentPageNumber: "${val}" is not a valid page.`);
  6874. }
  6875. }
  6876. _setCurrentPageNumber(val, resetCurrentPageView = false) {
  6877. if (this._currentPageNumber === val) {
  6878. if (resetCurrentPageView) {
  6879. this.#resetCurrentPageView();
  6880. }
  6881. return true;
  6882. }
  6883. if (!(0 < val && val <= this.pagesCount)) {
  6884. return false;
  6885. }
  6886. const previous = this._currentPageNumber;
  6887. this._currentPageNumber = val;
  6888. this.eventBus.dispatch("pagechanging", {
  6889. source: this,
  6890. pageNumber: val,
  6891. pageLabel: this._pageLabels?.[val - 1] ?? null,
  6892. previous
  6893. });
  6894. if (resetCurrentPageView) {
  6895. this.#resetCurrentPageView();
  6896. }
  6897. return true;
  6898. }
  6899. get currentPageLabel() {
  6900. return this._pageLabels?.[this._currentPageNumber - 1] ?? null;
  6901. }
  6902. set currentPageLabel(val) {
  6903. if (!this.pdfDocument) {
  6904. return;
  6905. }
  6906. let page = val | 0;
  6907. if (this._pageLabels) {
  6908. const i = this._pageLabels.indexOf(val);
  6909. if (i >= 0) {
  6910. page = i + 1;
  6911. }
  6912. }
  6913. if (!this._setCurrentPageNumber(page, true)) {
  6914. console.error(`currentPageLabel: "${val}" is not a valid page.`);
  6915. }
  6916. }
  6917. get currentScale() {
  6918. return this._currentScale !== UNKNOWN_SCALE ? this._currentScale : DEFAULT_SCALE;
  6919. }
  6920. set currentScale(val) {
  6921. if (isNaN(val)) {
  6922. throw new Error("Invalid numeric scale.");
  6923. }
  6924. if (!this.pdfDocument) {
  6925. return;
  6926. }
  6927. this.#setScale(val, {
  6928. noScroll: false
  6929. });
  6930. }
  6931. get currentScaleValue() {
  6932. return this._currentScaleValue;
  6933. }
  6934. set currentScaleValue(val) {
  6935. if (!this.pdfDocument) {
  6936. return;
  6937. }
  6938. this.#setScale(val, {
  6939. noScroll: false
  6940. });
  6941. }
  6942. get pagesRotation() {
  6943. return this._pagesRotation;
  6944. }
  6945. set pagesRotation(rotation) {
  6946. if (!isValidRotation(rotation)) {
  6947. throw new Error("Invalid pages rotation angle.");
  6948. }
  6949. if (!this.pdfDocument) {
  6950. return;
  6951. }
  6952. rotation %= 360;
  6953. if (rotation < 0) {
  6954. rotation += 360;
  6955. }
  6956. if (this._pagesRotation === rotation) {
  6957. return;
  6958. }
  6959. this._pagesRotation = rotation;
  6960. const pageNumber = this._currentPageNumber;
  6961. this.refresh(true, {
  6962. rotation
  6963. });
  6964. if (this._currentScaleValue) {
  6965. this.#setScale(this._currentScaleValue, {
  6966. noScroll: true
  6967. });
  6968. }
  6969. this.eventBus.dispatch("rotationchanging", {
  6970. source: this,
  6971. pagesRotation: rotation,
  6972. pageNumber
  6973. });
  6974. if (this.defaultRenderingQueue) {
  6975. this.update();
  6976. }
  6977. }
  6978. get firstPagePromise() {
  6979. return this.pdfDocument ? this._firstPageCapability.promise : null;
  6980. }
  6981. get onePageRendered() {
  6982. return this.pdfDocument ? this._onePageRenderedCapability.promise : null;
  6983. }
  6984. get pagesPromise() {
  6985. return this.pdfDocument ? this._pagesCapability.promise : null;
  6986. }
  6987. get _layerProperties() {
  6988. const self = this;
  6989. return shadow(this, "_layerProperties", {
  6990. get annotationEditorUIManager() {
  6991. return self.#annotationEditorUIManager;
  6992. },
  6993. get annotationStorage() {
  6994. return self.pdfDocument?.annotationStorage;
  6995. },
  6996. get downloadManager() {
  6997. return self.downloadManager;
  6998. },
  6999. get enableScripting() {
  7000. return !!self._scriptingManager;
  7001. },
  7002. get fieldObjectsPromise() {
  7003. return self.pdfDocument?.getFieldObjects();
  7004. },
  7005. get findController() {
  7006. return self.findController;
  7007. },
  7008. get hasJSActionsPromise() {
  7009. return self.pdfDocument?.hasJSActions();
  7010. },
  7011. get linkService() {
  7012. return self.linkService;
  7013. }
  7014. });
  7015. }
  7016. #initializePermissions(permissions) {
  7017. const params = {
  7018. annotationEditorMode: this.#annotationEditorMode,
  7019. annotationMode: this.#annotationMode,
  7020. textLayerMode: this.#textLayerMode
  7021. };
  7022. if (!permissions) {
  7023. return params;
  7024. }
  7025. if (!permissions.includes(PermissionFlag.COPY) && this.#textLayerMode === TextLayerMode.ENABLE) {
  7026. params.textLayerMode = TextLayerMode.ENABLE_PERMISSIONS;
  7027. }
  7028. if (!permissions.includes(PermissionFlag.MODIFY_CONTENTS)) {
  7029. params.annotationEditorMode = AnnotationEditorType.DISABLE;
  7030. }
  7031. if (!permissions.includes(PermissionFlag.MODIFY_ANNOTATIONS) && !permissions.includes(PermissionFlag.FILL_INTERACTIVE_FORMS) && this.#annotationMode === AnnotationMode.ENABLE_FORMS) {
  7032. params.annotationMode = AnnotationMode.ENABLE;
  7033. }
  7034. return params;
  7035. }
  7036. async #onePageRenderedOrForceFetch(signal) {
  7037. if (document.visibilityState === "hidden" || !this.container.offsetParent || this._getVisiblePages().views.length === 0) {
  7038. return;
  7039. }
  7040. const hiddenCapability = Promise.withResolvers(),
  7041. ac = new AbortController();
  7042. document.addEventListener("visibilitychange", () => {
  7043. if (document.visibilityState === "hidden") {
  7044. hiddenCapability.resolve();
  7045. }
  7046. }, {
  7047. signal: typeof AbortSignal.any === "function" ? AbortSignal.any([signal, ac.signal]) : signal
  7048. });
  7049. await Promise.race([this._onePageRenderedCapability.promise, hiddenCapability.promise]);
  7050. ac.abort();
  7051. }
  7052. async getAllText() {
  7053. const texts = [];
  7054. const buffer = [];
  7055. for (let pageNum = 1, pagesCount = this.pdfDocument.numPages; pageNum <= pagesCount; ++pageNum) {
  7056. if (this.#interruptCopyCondition) {
  7057. return null;
  7058. }
  7059. buffer.length = 0;
  7060. const page = await this.pdfDocument.getPage(pageNum);
  7061. const {
  7062. items
  7063. } = await page.getTextContent();
  7064. for (const item of items) {
  7065. if (item.str) {
  7066. buffer.push(item.str);
  7067. }
  7068. if (item.hasEOL) {
  7069. buffer.push("\n");
  7070. }
  7071. }
  7072. texts.push(removeNullCharacters(buffer.join("")));
  7073. }
  7074. return texts.join("\n");
  7075. }
  7076. #copyCallback(textLayerMode, event) {
  7077. const selection = document.getSelection();
  7078. const {
  7079. focusNode,
  7080. anchorNode
  7081. } = selection;
  7082. if (anchorNode && focusNode && selection.containsNode(this.#hiddenCopyElement)) {
  7083. if (this.#getAllTextInProgress || textLayerMode === TextLayerMode.ENABLE_PERMISSIONS) {
  7084. stopEvent(event);
  7085. return;
  7086. }
  7087. this.#getAllTextInProgress = true;
  7088. const {
  7089. classList
  7090. } = this.viewer;
  7091. classList.add("copyAll");
  7092. const ac = new AbortController();
  7093. window.addEventListener("keydown", ev => this.#interruptCopyCondition = ev.key === "Escape", {
  7094. signal: ac.signal
  7095. });
  7096. this.getAllText().then(async text => {
  7097. if (text !== null) {
  7098. await navigator.clipboard.writeText(text);
  7099. }
  7100. }).catch(reason => {
  7101. console.warn(`Something goes wrong when extracting the text: ${reason.message}`);
  7102. }).finally(() => {
  7103. this.#getAllTextInProgress = false;
  7104. this.#interruptCopyCondition = false;
  7105. ac.abort();
  7106. classList.remove("copyAll");
  7107. });
  7108. stopEvent(event);
  7109. }
  7110. }
  7111. setDocument(pdfDocument) {
  7112. if (this.pdfDocument) {
  7113. this.eventBus.dispatch("pagesdestroy", {
  7114. source: this
  7115. });
  7116. this._cancelRendering();
  7117. this._resetView();
  7118. this.findController?.setDocument(null);
  7119. this._scriptingManager?.setDocument(null);
  7120. this.#annotationEditorUIManager?.destroy();
  7121. this.#annotationEditorUIManager = null;
  7122. }
  7123. this.pdfDocument = pdfDocument;
  7124. if (!pdfDocument) {
  7125. return;
  7126. }
  7127. const pagesCount = pdfDocument.numPages;
  7128. const firstPagePromise = pdfDocument.getPage(1);
  7129. const optionalContentConfigPromise = pdfDocument.getOptionalContentConfig({
  7130. intent: "display"
  7131. });
  7132. const permissionsPromise = this.#enablePermissions ? pdfDocument.getPermissions() : Promise.resolve();
  7133. const {
  7134. eventBus,
  7135. pageColors,
  7136. viewer
  7137. } = this;
  7138. this.#eventAbortController = new AbortController();
  7139. const {
  7140. signal
  7141. } = this.#eventAbortController;
  7142. if (pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) {
  7143. console.warn("Forcing PAGE-scrolling for performance reasons, given the length of the document.");
  7144. const mode = this._scrollMode = ScrollMode.PAGE;
  7145. eventBus.dispatch("scrollmodechanged", {
  7146. source: this,
  7147. mode
  7148. });
  7149. }
  7150. this._pagesCapability.promise.then(() => {
  7151. eventBus.dispatch("pagesloaded", {
  7152. source: this,
  7153. pagesCount
  7154. });
  7155. }, () => {});
  7156. const onBeforeDraw = evt => {
  7157. const pageView = this._pages[evt.pageNumber - 1];
  7158. if (!pageView) {
  7159. return;
  7160. }
  7161. this.#buffer.push(pageView);
  7162. };
  7163. eventBus._on("pagerender", onBeforeDraw, {
  7164. signal
  7165. });
  7166. const onAfterDraw = evt => {
  7167. if (evt.cssTransform) {
  7168. return;
  7169. }
  7170. this._onePageRenderedCapability.resolve({
  7171. timestamp: evt.timestamp
  7172. });
  7173. eventBus._off("pagerendered", onAfterDraw);
  7174. };
  7175. eventBus._on("pagerendered", onAfterDraw, {
  7176. signal
  7177. });
  7178. Promise.all([firstPagePromise, permissionsPromise]).then(([firstPdfPage, permissions]) => {
  7179. if (pdfDocument !== this.pdfDocument) {
  7180. return;
  7181. }
  7182. this._firstPageCapability.resolve(firstPdfPage);
  7183. this._optionalContentConfigPromise = optionalContentConfigPromise;
  7184. const {
  7185. annotationEditorMode,
  7186. annotationMode,
  7187. textLayerMode
  7188. } = this.#initializePermissions(permissions);
  7189. if (textLayerMode !== TextLayerMode.DISABLE) {
  7190. const element = this.#hiddenCopyElement = document.createElement("div");
  7191. element.id = "hiddenCopyElement";
  7192. viewer.before(element);
  7193. }
  7194. if (typeof AbortSignal.any === "function" && annotationEditorMode !== AnnotationEditorType.DISABLE) {
  7195. const mode = annotationEditorMode;
  7196. if (pdfDocument.isPureXfa) {
  7197. console.warn("Warning: XFA-editing is not implemented.");
  7198. } else if (isValidAnnotationEditorMode(mode)) {
  7199. this.#annotationEditorUIManager = new AnnotationEditorUIManager(this.container, viewer, this.#altTextManager, eventBus, pdfDocument, pageColors, this.#annotationEditorHighlightColors, this.#enableHighlightFloatingButton, this.#enableUpdatedAddImage, this.#enableNewAltTextWhenAddingImage, this.#mlManager, this.#editorUndoBar, this.#supportsPinchToZoom);
  7200. eventBus.dispatch("annotationeditoruimanager", {
  7201. source: this,
  7202. uiManager: this.#annotationEditorUIManager
  7203. });
  7204. if (mode !== AnnotationEditorType.NONE) {
  7205. if (mode === AnnotationEditorType.STAMP) {
  7206. this.#mlManager?.loadModel("altText");
  7207. }
  7208. this.#annotationEditorUIManager.updateMode(mode);
  7209. }
  7210. } else {
  7211. console.error(`Invalid AnnotationEditor mode: ${mode}`);
  7212. }
  7213. }
  7214. const viewerElement = this._scrollMode === ScrollMode.PAGE ? null : viewer;
  7215. const scale = this.currentScale;
  7216. const viewport = firstPdfPage.getViewport({
  7217. scale: scale * PixelsPerInch.PDF_TO_CSS_UNITS
  7218. });
  7219. viewer.style.setProperty("--scale-factor", viewport.scale);
  7220. if (pageColors?.background) {
  7221. viewer.style.setProperty("--page-bg-color", pageColors.background);
  7222. }
  7223. if (pageColors?.foreground === "CanvasText" || pageColors?.background === "Canvas") {
  7224. viewer.style.setProperty("--hcm-highlight-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight", "CanvasText", "Canvas", "HighlightText", "Highlight"));
  7225. viewer.style.setProperty("--hcm-highlight-selected-filter", pdfDocument.filterFactory.addHighlightHCMFilter("highlight_selected", "CanvasText", "Canvas", "HighlightText", "ButtonText"));
  7226. }
  7227. for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
  7228. const pageView = new PDFPageView({
  7229. container: viewerElement,
  7230. eventBus,
  7231. id: pageNum,
  7232. scale,
  7233. defaultViewport: viewport.clone(),
  7234. optionalContentConfigPromise,
  7235. renderingQueue: this.renderingQueue,
  7236. textLayerMode,
  7237. annotationMode,
  7238. imageResourcesPath: this.imageResourcesPath,
  7239. maxCanvasPixels: this.maxCanvasPixels,
  7240. pageColors,
  7241. l10n: this.l10n,
  7242. layerProperties: this._layerProperties,
  7243. enableHWA: this.#enableHWA
  7244. });
  7245. this._pages.push(pageView);
  7246. }
  7247. this._pages[0]?.setPdfPage(firstPdfPage);
  7248. if (this._scrollMode === ScrollMode.PAGE) {
  7249. this.#ensurePageViewVisible();
  7250. } else if (this._spreadMode !== SpreadMode.NONE) {
  7251. this._updateSpreadMode();
  7252. }
  7253. this.#onePageRenderedOrForceFetch(signal).then(async () => {
  7254. if (pdfDocument !== this.pdfDocument) {
  7255. return;
  7256. }
  7257. this.findController?.setDocument(pdfDocument);
  7258. this._scriptingManager?.setDocument(pdfDocument);
  7259. if (this.#hiddenCopyElement) {
  7260. document.addEventListener("copy", this.#copyCallback.bind(this, textLayerMode), {
  7261. signal
  7262. });
  7263. }
  7264. if (this.#annotationEditorUIManager) {
  7265. eventBus.dispatch("annotationeditormodechanged", {
  7266. source: this,
  7267. mode: this.#annotationEditorMode
  7268. });
  7269. }
  7270. if (pdfDocument.loadingParams.disableAutoFetch || pagesCount > PagesCountLimit.FORCE_LAZY_PAGE_INIT) {
  7271. this._pagesCapability.resolve();
  7272. return;
  7273. }
  7274. let getPagesLeft = pagesCount - 1;
  7275. if (getPagesLeft <= 0) {
  7276. this._pagesCapability.resolve();
  7277. return;
  7278. }
  7279. for (let pageNum = 2; pageNum <= pagesCount; ++pageNum) {
  7280. const promise = pdfDocument.getPage(pageNum).then(pdfPage => {
  7281. const pageView = this._pages[pageNum - 1];
  7282. if (!pageView.pdfPage) {
  7283. pageView.setPdfPage(pdfPage);
  7284. }
  7285. if (--getPagesLeft === 0) {
  7286. this._pagesCapability.resolve();
  7287. }
  7288. }, reason => {
  7289. console.error(`Unable to get page ${pageNum} to initialize viewer`, reason);
  7290. if (--getPagesLeft === 0) {
  7291. this._pagesCapability.resolve();
  7292. }
  7293. });
  7294. if (pageNum % PagesCountLimit.PAUSE_EAGER_PAGE_INIT === 0) {
  7295. await promise;
  7296. }
  7297. }
  7298. });
  7299. eventBus.dispatch("pagesinit", {
  7300. source: this
  7301. });
  7302. pdfDocument.getMetadata().then(({
  7303. info
  7304. }) => {
  7305. if (pdfDocument !== this.pdfDocument) {
  7306. return;
  7307. }
  7308. if (info.Language) {
  7309. viewer.lang = info.Language;
  7310. }
  7311. });
  7312. if (this.defaultRenderingQueue) {
  7313. this.update();
  7314. }
  7315. }).catch(reason => {
  7316. console.error("Unable to initialize viewer", reason);
  7317. this._pagesCapability.reject(reason);
  7318. });
  7319. }
  7320. setPageLabels(labels) {
  7321. if (!this.pdfDocument) {
  7322. return;
  7323. }
  7324. if (!labels) {
  7325. this._pageLabels = null;
  7326. } else if (!(Array.isArray(labels) && this.pdfDocument.numPages === labels.length)) {
  7327. this._pageLabels = null;
  7328. console.error(`setPageLabels: Invalid page labels.`);
  7329. } else {
  7330. this._pageLabels = labels;
  7331. }
  7332. for (let i = 0, ii = this._pages.length; i < ii; i++) {
  7333. this._pages[i].setPageLabel(this._pageLabels?.[i] ?? null);
  7334. }
  7335. }
  7336. _resetView() {
  7337. this._pages = [];
  7338. this._currentPageNumber = 1;
  7339. this._currentScale = UNKNOWN_SCALE;
  7340. this._currentScaleValue = null;
  7341. this._pageLabels = null;
  7342. this.#buffer = new PDFPageViewBuffer(DEFAULT_CACHE_SIZE);
  7343. this._location = null;
  7344. this._pagesRotation = 0;
  7345. this._optionalContentConfigPromise = null;
  7346. this._firstPageCapability = Promise.withResolvers();
  7347. this._onePageRenderedCapability = Promise.withResolvers();
  7348. this._pagesCapability = Promise.withResolvers();
  7349. this._scrollMode = ScrollMode.VERTICAL;
  7350. this._previousScrollMode = ScrollMode.UNKNOWN;
  7351. this._spreadMode = SpreadMode.NONE;
  7352. this.#scrollModePageState = {
  7353. previousPageNumber: 1,
  7354. scrollDown: true,
  7355. pages: []
  7356. };
  7357. this.#eventAbortController?.abort();
  7358. this.#eventAbortController = null;
  7359. this.viewer.textContent = "";
  7360. this._updateScrollMode();
  7361. this.viewer.removeAttribute("lang");
  7362. this.#hiddenCopyElement?.remove();
  7363. this.#hiddenCopyElement = null;
  7364. this.#cleanupSwitchAnnotationEditorMode();
  7365. }
  7366. #ensurePageViewVisible() {
  7367. if (this._scrollMode !== ScrollMode.PAGE) {
  7368. throw new Error("#ensurePageViewVisible: Invalid scrollMode value.");
  7369. }
  7370. const pageNumber = this._currentPageNumber,
  7371. state = this.#scrollModePageState,
  7372. viewer = this.viewer;
  7373. viewer.textContent = "";
  7374. state.pages.length = 0;
  7375. if (this._spreadMode === SpreadMode.NONE && !this.isInPresentationMode) {
  7376. const pageView = this._pages[pageNumber - 1];
  7377. viewer.append(pageView.div);
  7378. state.pages.push(pageView);
  7379. } else {
  7380. const pageIndexSet = new Set(),
  7381. parity = this._spreadMode - 1;
  7382. if (parity === -1) {
  7383. pageIndexSet.add(pageNumber - 1);
  7384. } else if (pageNumber % 2 !== parity) {
  7385. pageIndexSet.add(pageNumber - 1);
  7386. pageIndexSet.add(pageNumber);
  7387. } else {
  7388. pageIndexSet.add(pageNumber - 2);
  7389. pageIndexSet.add(pageNumber - 1);
  7390. }
  7391. const spread = document.createElement("div");
  7392. spread.className = "spread";
  7393. if (this.isInPresentationMode) {
  7394. const dummyPage = document.createElement("div");
  7395. dummyPage.className = "dummyPage";
  7396. spread.append(dummyPage);
  7397. }
  7398. for (const i of pageIndexSet) {
  7399. const pageView = this._pages[i];
  7400. if (!pageView) {
  7401. continue;
  7402. }
  7403. spread.append(pageView.div);
  7404. state.pages.push(pageView);
  7405. }
  7406. viewer.append(spread);
  7407. }
  7408. state.scrollDown = pageNumber >= state.previousPageNumber;
  7409. state.previousPageNumber = pageNumber;
  7410. }
  7411. _scrollUpdate() {
  7412. if (this.pagesCount === 0) {
  7413. return;
  7414. }
  7415. this.update();
  7416. }
  7417. #scrollIntoView(pageView, pageSpot = null) {
  7418. const {
  7419. div,
  7420. id
  7421. } = pageView;
  7422. if (this._currentPageNumber !== id) {
  7423. this._setCurrentPageNumber(id);
  7424. }
  7425. if (this._scrollMode === ScrollMode.PAGE) {
  7426. this.#ensurePageViewVisible();
  7427. this.update();
  7428. }
  7429. if (!pageSpot && !this.isInPresentationMode) {
  7430. const left = div.offsetLeft + div.clientLeft,
  7431. right = left + div.clientWidth;
  7432. const {
  7433. scrollLeft,
  7434. clientWidth
  7435. } = this.container;
  7436. if (this._scrollMode === ScrollMode.HORIZONTAL || left < scrollLeft || right > scrollLeft + clientWidth) {
  7437. pageSpot = {
  7438. left: 0,
  7439. top: 0
  7440. };
  7441. }
  7442. }
  7443. scrollIntoView(div, pageSpot);
  7444. if (!this._currentScaleValue && this._location) {
  7445. this._location = null;
  7446. }
  7447. }
  7448. #isSameScale(newScale) {
  7449. return newScale === this._currentScale || Math.abs(newScale - this._currentScale) < 1e-15;
  7450. }
  7451. #setScaleUpdatePages(newScale, newValue, {
  7452. noScroll = false,
  7453. preset = false,
  7454. drawingDelay = -1,
  7455. origin = null
  7456. }) {
  7457. this._currentScaleValue = newValue.toString();
  7458. if (this.#isSameScale(newScale)) {
  7459. if (preset) {
  7460. this.eventBus.dispatch("scalechanging", {
  7461. source: this,
  7462. scale: newScale,
  7463. presetValue: newValue
  7464. });
  7465. }
  7466. return;
  7467. }
  7468. this.viewer.style.setProperty("--scale-factor", newScale * PixelsPerInch.PDF_TO_CSS_UNITS);
  7469. const postponeDrawing = drawingDelay >= 0 && drawingDelay < 1000;
  7470. this.refresh(true, {
  7471. scale: newScale,
  7472. drawingDelay: postponeDrawing ? drawingDelay : -1
  7473. });
  7474. if (postponeDrawing) {
  7475. this.#scaleTimeoutId = setTimeout(() => {
  7476. this.#scaleTimeoutId = null;
  7477. this.refresh();
  7478. }, drawingDelay);
  7479. }
  7480. const previousScale = this._currentScale;
  7481. this._currentScale = newScale;
  7482. if (!noScroll) {
  7483. let page = this._currentPageNumber,
  7484. dest;
  7485. if (this._location && !(this.isInPresentationMode || this.isChangingPresentationMode)) {
  7486. page = this._location.pageNumber;
  7487. dest = [null, {
  7488. name: "XYZ"
  7489. }, this._location.left, this._location.top, null];
  7490. }
  7491. this.scrollPageIntoView({
  7492. pageNumber: page,
  7493. destArray: dest,
  7494. allowNegativeOffset: true
  7495. });
  7496. if (Array.isArray(origin)) {
  7497. const scaleDiff = newScale / previousScale - 1;
  7498. const [top, left] = this.containerTopLeft;
  7499. this.container.scrollLeft += (origin[0] - left) * scaleDiff;
  7500. this.container.scrollTop += (origin[1] - top) * scaleDiff;
  7501. }
  7502. }
  7503. this.eventBus.dispatch("scalechanging", {
  7504. source: this,
  7505. scale: newScale,
  7506. presetValue: preset ? newValue : undefined
  7507. });
  7508. if (this.defaultRenderingQueue) {
  7509. this.update();
  7510. }
  7511. }
  7512. get #pageWidthScaleFactor() {
  7513. if (this._spreadMode !== SpreadMode.NONE && this._scrollMode !== ScrollMode.HORIZONTAL) {
  7514. return 2;
  7515. }
  7516. return 1;
  7517. }
  7518. #setScale(value, options) {
  7519. let scale = parseFloat(value);
  7520. if (scale > 0) {
  7521. options.preset = false;
  7522. this.#setScaleUpdatePages(scale, value, options);
  7523. } else {
  7524. const currentPage = this._pages[this._currentPageNumber - 1];
  7525. if (!currentPage) {
  7526. return;
  7527. }
  7528. let hPadding = SCROLLBAR_PADDING,
  7529. vPadding = VERTICAL_PADDING;
  7530. if (this.isInPresentationMode) {
  7531. hPadding = vPadding = 4;
  7532. if (this._spreadMode !== SpreadMode.NONE) {
  7533. hPadding *= 2;
  7534. }
  7535. } else if (this.removePageBorders) {
  7536. hPadding = vPadding = 0;
  7537. } else if (this._scrollMode === ScrollMode.HORIZONTAL) {
  7538. [hPadding, vPadding] = [vPadding, hPadding];
  7539. }
  7540. const pageWidthScale = (this.container.clientWidth - hPadding) / currentPage.width * currentPage.scale / this.#pageWidthScaleFactor;
  7541. const pageHeightScale = (this.container.clientHeight - vPadding) / currentPage.height * currentPage.scale;
  7542. switch (value) {
  7543. case "page-actual":
  7544. scale = 1;
  7545. break;
  7546. case "page-width":
  7547. scale = pageWidthScale;
  7548. break;
  7549. case "page-height":
  7550. scale = pageHeightScale;
  7551. break;
  7552. case "page-fit":
  7553. scale = Math.min(pageWidthScale, pageHeightScale);
  7554. break;
  7555. case "auto":
  7556. const horizontalScale = isPortraitOrientation(currentPage) ? pageWidthScale : Math.min(pageHeightScale, pageWidthScale);
  7557. scale = Math.min(MAX_AUTO_SCALE, horizontalScale);
  7558. break;
  7559. default:
  7560. console.error(`#setScale: "${value}" is an unknown zoom value.`);
  7561. return;
  7562. }
  7563. options.preset = true;
  7564. this.#setScaleUpdatePages(scale, value, options);
  7565. }
  7566. }
  7567. #resetCurrentPageView() {
  7568. const pageView = this._pages[this._currentPageNumber - 1];
  7569. if (this.isInPresentationMode) {
  7570. this.#setScale(this._currentScaleValue, {
  7571. noScroll: true
  7572. });
  7573. }
  7574. this.#scrollIntoView(pageView);
  7575. }
  7576. pageLabelToPageNumber(label) {
  7577. if (!this._pageLabels) {
  7578. return null;
  7579. }
  7580. const i = this._pageLabels.indexOf(label);
  7581. if (i < 0) {
  7582. return null;
  7583. }
  7584. return i + 1;
  7585. }
  7586. scrollPageIntoView({
  7587. pageNumber,
  7588. destArray = null,
  7589. allowNegativeOffset = false,
  7590. ignoreDestinationZoom = false
  7591. }) {
  7592. if (!this.pdfDocument) {
  7593. return;
  7594. }
  7595. const pageView = Number.isInteger(pageNumber) && this._pages[pageNumber - 1];
  7596. if (!pageView) {
  7597. console.error(`scrollPageIntoView: "${pageNumber}" is not a valid pageNumber parameter.`);
  7598. return;
  7599. }
  7600. if (this.isInPresentationMode || !destArray) {
  7601. this._setCurrentPageNumber(pageNumber, true);
  7602. return;
  7603. }
  7604. let x = 0,
  7605. y = 0;
  7606. let width = 0,
  7607. height = 0,
  7608. widthScale,
  7609. heightScale;
  7610. const changeOrientation = pageView.rotation % 180 !== 0;
  7611. const pageWidth = (changeOrientation ? pageView.height : pageView.width) / pageView.scale / PixelsPerInch.PDF_TO_CSS_UNITS;
  7612. const pageHeight = (changeOrientation ? pageView.width : pageView.height) / pageView.scale / PixelsPerInch.PDF_TO_CSS_UNITS;
  7613. let scale = 0;
  7614. switch (destArray[1].name) {
  7615. case "XYZ":
  7616. x = destArray[2];
  7617. y = destArray[3];
  7618. scale = destArray[4];
  7619. x = x !== null ? x : 0;
  7620. y = y !== null ? y : pageHeight;
  7621. break;
  7622. case "Fit":
  7623. case "FitB":
  7624. scale = "page-fit";
  7625. break;
  7626. case "FitH":
  7627. case "FitBH":
  7628. y = destArray[2];
  7629. scale = "page-width";
  7630. if (y === null && this._location) {
  7631. x = this._location.left;
  7632. y = this._location.top;
  7633. } else if (typeof y !== "number" || y < 0) {
  7634. y = pageHeight;
  7635. }
  7636. break;
  7637. case "FitV":
  7638. case "FitBV":
  7639. x = destArray[2];
  7640. width = pageWidth;
  7641. height = pageHeight;
  7642. scale = "page-height";
  7643. break;
  7644. case "FitR":
  7645. x = destArray[2];
  7646. y = destArray[3];
  7647. width = destArray[4] - x;
  7648. height = destArray[5] - y;
  7649. let hPadding = SCROLLBAR_PADDING,
  7650. vPadding = VERTICAL_PADDING;
  7651. if (this.removePageBorders) {
  7652. hPadding = vPadding = 0;
  7653. }
  7654. widthScale = (this.container.clientWidth - hPadding) / width / PixelsPerInch.PDF_TO_CSS_UNITS;
  7655. heightScale = (this.container.clientHeight - vPadding) / height / PixelsPerInch.PDF_TO_CSS_UNITS;
  7656. scale = Math.min(Math.abs(widthScale), Math.abs(heightScale));
  7657. break;
  7658. default:
  7659. console.error(`scrollPageIntoView: "${destArray[1].name}" is not a valid destination type.`);
  7660. return;
  7661. }
  7662. if (!ignoreDestinationZoom) {
  7663. if (scale && scale !== this._currentScale) {
  7664. this.currentScaleValue = scale;
  7665. } else if (this._currentScale === UNKNOWN_SCALE) {
  7666. this.currentScaleValue = DEFAULT_SCALE_VALUE;
  7667. }
  7668. }
  7669. if (scale === "page-fit" && !destArray[4]) {
  7670. this.#scrollIntoView(pageView);
  7671. return;
  7672. }
  7673. const boundingRect = [pageView.viewport.convertToViewportPoint(x, y), pageView.viewport.convertToViewportPoint(x + width, y + height)];
  7674. let left = Math.min(boundingRect[0][0], boundingRect[1][0]);
  7675. let top = Math.min(boundingRect[0][1], boundingRect[1][1]);
  7676. if (!allowNegativeOffset) {
  7677. left = Math.max(left, 0);
  7678. top = Math.max(top, 0);
  7679. }
  7680. this.#scrollIntoView(pageView, {
  7681. left,
  7682. top
  7683. });
  7684. }
  7685. _updateLocation(firstPage) {
  7686. const currentScale = this._currentScale;
  7687. const currentScaleValue = this._currentScaleValue;
  7688. const normalizedScaleValue = parseFloat(currentScaleValue) === currentScale ? Math.round(currentScale * 10000) / 100 : currentScaleValue;
  7689. const pageNumber = firstPage.id;
  7690. const currentPageView = this._pages[pageNumber - 1];
  7691. const container = this.container;
  7692. const topLeft = currentPageView.getPagePoint(container.scrollLeft - firstPage.x, container.scrollTop - firstPage.y);
  7693. const intLeft = Math.round(topLeft[0]);
  7694. const intTop = Math.round(topLeft[1]);
  7695. let pdfOpenParams = `#page=${pageNumber}`;
  7696. if (!this.isInPresentationMode) {
  7697. pdfOpenParams += `&zoom=${normalizedScaleValue},${intLeft},${intTop}`;
  7698. }
  7699. this._location = {
  7700. pageNumber,
  7701. scale: normalizedScaleValue,
  7702. top: intTop,
  7703. left: intLeft,
  7704. rotation: this._pagesRotation,
  7705. pdfOpenParams
  7706. };
  7707. }
  7708. update() {
  7709. const visible = this._getVisiblePages();
  7710. const visiblePages = visible.views,
  7711. numVisiblePages = visiblePages.length;
  7712. if (numVisiblePages === 0) {
  7713. return;
  7714. }
  7715. const newCacheSize = Math.max(DEFAULT_CACHE_SIZE, 2 * numVisiblePages + 1);
  7716. this.#buffer.resize(newCacheSize, visible.ids);
  7717. this.renderingQueue.renderHighestPriority(visible);
  7718. const isSimpleLayout = this._spreadMode === SpreadMode.NONE && (this._scrollMode === ScrollMode.PAGE || this._scrollMode === ScrollMode.VERTICAL);
  7719. const currentId = this._currentPageNumber;
  7720. let stillFullyVisible = false;
  7721. for (const page of visiblePages) {
  7722. if (page.percent < 100) {
  7723. break;
  7724. }
  7725. if (page.id === currentId && isSimpleLayout) {
  7726. stillFullyVisible = true;
  7727. break;
  7728. }
  7729. }
  7730. this._setCurrentPageNumber(stillFullyVisible ? currentId : visiblePages[0].id);
  7731. this._updateLocation(visible.first);
  7732. this.eventBus.dispatch("updateviewarea", {
  7733. source: this,
  7734. location: this._location
  7735. });
  7736. }
  7737. #switchToEditAnnotationMode() {
  7738. const visible = this._getVisiblePages();
  7739. const pagesToRefresh = [];
  7740. const {
  7741. ids,
  7742. views
  7743. } = visible;
  7744. for (const page of views) {
  7745. const {
  7746. view
  7747. } = page;
  7748. if (!view.hasEditableAnnotations()) {
  7749. ids.delete(view.id);
  7750. continue;
  7751. }
  7752. pagesToRefresh.push(page);
  7753. }
  7754. if (pagesToRefresh.length === 0) {
  7755. return null;
  7756. }
  7757. this.renderingQueue.renderHighestPriority({
  7758. first: pagesToRefresh[0],
  7759. last: pagesToRefresh.at(-1),
  7760. views: pagesToRefresh,
  7761. ids
  7762. });
  7763. return ids;
  7764. }
  7765. containsElement(element) {
  7766. return this.container.contains(element);
  7767. }
  7768. focus() {
  7769. this.container.focus();
  7770. }
  7771. get _isContainerRtl() {
  7772. return getComputedStyle(this.container).direction === "rtl";
  7773. }
  7774. get isInPresentationMode() {
  7775. return this.presentationModeState === PresentationModeState.FULLSCREEN;
  7776. }
  7777. get isChangingPresentationMode() {
  7778. return this.presentationModeState === PresentationModeState.CHANGING;
  7779. }
  7780. get isHorizontalScrollbarEnabled() {
  7781. return this.isInPresentationMode ? false : this.container.scrollWidth > this.container.clientWidth;
  7782. }
  7783. get isVerticalScrollbarEnabled() {
  7784. return this.isInPresentationMode ? false : this.container.scrollHeight > this.container.clientHeight;
  7785. }
  7786. _getVisiblePages() {
  7787. const views = this._scrollMode === ScrollMode.PAGE ? this.#scrollModePageState.pages : this._pages,
  7788. horizontal = this._scrollMode === ScrollMode.HORIZONTAL,
  7789. rtl = horizontal && this._isContainerRtl;
  7790. return getVisibleElements({
  7791. scrollEl: this.container,
  7792. views,
  7793. sortByVisibility: true,
  7794. horizontal,
  7795. rtl
  7796. });
  7797. }
  7798. cleanup() {
  7799. for (const pageView of this._pages) {
  7800. if (pageView.renderingState !== RenderingStates.FINISHED) {
  7801. pageView.reset();
  7802. }
  7803. }
  7804. }
  7805. _cancelRendering() {
  7806. for (const pageView of this._pages) {
  7807. pageView.cancelRendering();
  7808. }
  7809. }
  7810. async #ensurePdfPageLoaded(pageView) {
  7811. if (pageView.pdfPage) {
  7812. return pageView.pdfPage;
  7813. }
  7814. try {
  7815. const pdfPage = await this.pdfDocument.getPage(pageView.id);
  7816. if (!pageView.pdfPage) {
  7817. pageView.setPdfPage(pdfPage);
  7818. }
  7819. return pdfPage;
  7820. } catch (reason) {
  7821. console.error("Unable to get page for page view", reason);
  7822. return null;
  7823. }
  7824. }
  7825. #getScrollAhead(visible) {
  7826. if (visible.first?.id === 1) {
  7827. return true;
  7828. } else if (visible.last?.id === this.pagesCount) {
  7829. return false;
  7830. }
  7831. switch (this._scrollMode) {
  7832. case ScrollMode.PAGE:
  7833. return this.#scrollModePageState.scrollDown;
  7834. case ScrollMode.HORIZONTAL:
  7835. return this.scroll.right;
  7836. }
  7837. return this.scroll.down;
  7838. }
  7839. forceRendering(currentlyVisiblePages) {
  7840. const visiblePages = currentlyVisiblePages || this._getVisiblePages();
  7841. const scrollAhead = this.#getScrollAhead(visiblePages);
  7842. const preRenderExtra = this._spreadMode !== SpreadMode.NONE && this._scrollMode !== ScrollMode.HORIZONTAL;
  7843. const pageView = this.renderingQueue.getHighestPriority(visiblePages, this._pages, scrollAhead, preRenderExtra);
  7844. if (pageView) {
  7845. this.#ensurePdfPageLoaded(pageView).then(() => {
  7846. this.renderingQueue.renderView(pageView);
  7847. });
  7848. return true;
  7849. }
  7850. return false;
  7851. }
  7852. get hasEqualPageSizes() {
  7853. const firstPageView = this._pages[0];
  7854. for (let i = 1, ii = this._pages.length; i < ii; ++i) {
  7855. const pageView = this._pages[i];
  7856. if (pageView.width !== firstPageView.width || pageView.height !== firstPageView.height) {
  7857. return false;
  7858. }
  7859. }
  7860. return true;
  7861. }
  7862. getPagesOverview() {
  7863. let initialOrientation;
  7864. return this._pages.map(pageView => {
  7865. const viewport = pageView.pdfPage.getViewport({
  7866. scale: 1
  7867. });
  7868. const orientation = isPortraitOrientation(viewport);
  7869. if (initialOrientation === undefined) {
  7870. initialOrientation = orientation;
  7871. } else if (this.enablePrintAutoRotate && orientation !== initialOrientation) {
  7872. return {
  7873. width: viewport.height,
  7874. height: viewport.width,
  7875. rotation: (viewport.rotation - 90) % 360
  7876. };
  7877. }
  7878. return {
  7879. width: viewport.width,
  7880. height: viewport.height,
  7881. rotation: viewport.rotation
  7882. };
  7883. });
  7884. }
  7885. get optionalContentConfigPromise() {
  7886. if (!this.pdfDocument) {
  7887. return Promise.resolve(null);
  7888. }
  7889. if (!this._optionalContentConfigPromise) {
  7890. console.error("optionalContentConfigPromise: Not initialized yet.");
  7891. return this.pdfDocument.getOptionalContentConfig({
  7892. intent: "display"
  7893. });
  7894. }
  7895. return this._optionalContentConfigPromise;
  7896. }
  7897. set optionalContentConfigPromise(promise) {
  7898. if (!(promise instanceof Promise)) {
  7899. throw new Error(`Invalid optionalContentConfigPromise: ${promise}`);
  7900. }
  7901. if (!this.pdfDocument) {
  7902. return;
  7903. }
  7904. if (!this._optionalContentConfigPromise) {
  7905. return;
  7906. }
  7907. this._optionalContentConfigPromise = promise;
  7908. this.refresh(false, {
  7909. optionalContentConfigPromise: promise
  7910. });
  7911. this.eventBus.dispatch("optionalcontentconfigchanged", {
  7912. source: this,
  7913. promise
  7914. });
  7915. }
  7916. get scrollMode() {
  7917. return this._scrollMode;
  7918. }
  7919. set scrollMode(mode) {
  7920. if (this._scrollMode === mode) {
  7921. return;
  7922. }
  7923. if (!isValidScrollMode(mode)) {
  7924. throw new Error(`Invalid scroll mode: ${mode}`);
  7925. }
  7926. if (this.pagesCount > PagesCountLimit.FORCE_SCROLL_MODE_PAGE) {
  7927. return;
  7928. }
  7929. this._previousScrollMode = this._scrollMode;
  7930. this._scrollMode = mode;
  7931. this.eventBus.dispatch("scrollmodechanged", {
  7932. source: this,
  7933. mode
  7934. });
  7935. this._updateScrollMode(this._currentPageNumber);
  7936. }
  7937. _updateScrollMode(pageNumber = null) {
  7938. const scrollMode = this._scrollMode,
  7939. viewer = this.viewer;
  7940. viewer.classList.toggle("scrollHorizontal", scrollMode === ScrollMode.HORIZONTAL);
  7941. viewer.classList.toggle("scrollWrapped", scrollMode === ScrollMode.WRAPPED);
  7942. if (!this.pdfDocument || !pageNumber) {
  7943. return;
  7944. }
  7945. if (scrollMode === ScrollMode.PAGE) {
  7946. this.#ensurePageViewVisible();
  7947. } else if (this._previousScrollMode === ScrollMode.PAGE) {
  7948. this._updateSpreadMode();
  7949. }
  7950. if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
  7951. this.#setScale(this._currentScaleValue, {
  7952. noScroll: true
  7953. });
  7954. }
  7955. this._setCurrentPageNumber(pageNumber, true);
  7956. this.update();
  7957. }
  7958. get spreadMode() {
  7959. return this._spreadMode;
  7960. }
  7961. set spreadMode(mode) {
  7962. if (this._spreadMode === mode) {
  7963. return;
  7964. }
  7965. if (!isValidSpreadMode(mode)) {
  7966. throw new Error(`Invalid spread mode: ${mode}`);
  7967. }
  7968. this._spreadMode = mode;
  7969. this.eventBus.dispatch("spreadmodechanged", {
  7970. source: this,
  7971. mode
  7972. });
  7973. this._updateSpreadMode(this._currentPageNumber);
  7974. }
  7975. _updateSpreadMode(pageNumber = null) {
  7976. if (!this.pdfDocument) {
  7977. return;
  7978. }
  7979. const viewer = this.viewer,
  7980. pages = this._pages;
  7981. if (this._scrollMode === ScrollMode.PAGE) {
  7982. this.#ensurePageViewVisible();
  7983. } else {
  7984. viewer.textContent = "";
  7985. if (this._spreadMode === SpreadMode.NONE) {
  7986. for (const pageView of this._pages) {
  7987. viewer.append(pageView.div);
  7988. }
  7989. } else {
  7990. const parity = this._spreadMode - 1;
  7991. let spread = null;
  7992. for (let i = 0, ii = pages.length; i < ii; ++i) {
  7993. if (spread === null) {
  7994. spread = document.createElement("div");
  7995. spread.className = "spread";
  7996. viewer.append(spread);
  7997. } else if (i % 2 === parity) {
  7998. spread = spread.cloneNode(false);
  7999. viewer.append(spread);
  8000. }
  8001. spread.append(pages[i].div);
  8002. }
  8003. }
  8004. }
  8005. if (!pageNumber) {
  8006. return;
  8007. }
  8008. if (this._currentScaleValue && isNaN(this._currentScaleValue)) {
  8009. this.#setScale(this._currentScaleValue, {
  8010. noScroll: true
  8011. });
  8012. }
  8013. this._setCurrentPageNumber(pageNumber, true);
  8014. this.update();
  8015. }
  8016. _getPageAdvance(currentPageNumber, previous = false) {
  8017. switch (this._scrollMode) {
  8018. case ScrollMode.WRAPPED:
  8019. {
  8020. const {
  8021. views
  8022. } = this._getVisiblePages(),
  8023. pageLayout = new Map();
  8024. for (const {
  8025. id,
  8026. y,
  8027. percent,
  8028. widthPercent
  8029. } of views) {
  8030. if (percent === 0 || widthPercent < 100) {
  8031. continue;
  8032. }
  8033. let yArray = pageLayout.get(y);
  8034. if (!yArray) {
  8035. pageLayout.set(y, yArray ||= []);
  8036. }
  8037. yArray.push(id);
  8038. }
  8039. for (const yArray of pageLayout.values()) {
  8040. const currentIndex = yArray.indexOf(currentPageNumber);
  8041. if (currentIndex === -1) {
  8042. continue;
  8043. }
  8044. const numPages = yArray.length;
  8045. if (numPages === 1) {
  8046. break;
  8047. }
  8048. if (previous) {
  8049. for (let i = currentIndex - 1, ii = 0; i >= ii; i--) {
  8050. const currentId = yArray[i],
  8051. expectedId = yArray[i + 1] - 1;
  8052. if (currentId < expectedId) {
  8053. return currentPageNumber - expectedId;
  8054. }
  8055. }
  8056. } else {
  8057. for (let i = currentIndex + 1, ii = numPages; i < ii; i++) {
  8058. const currentId = yArray[i],
  8059. expectedId = yArray[i - 1] + 1;
  8060. if (currentId > expectedId) {
  8061. return expectedId - currentPageNumber;
  8062. }
  8063. }
  8064. }
  8065. if (previous) {
  8066. const firstId = yArray[0];
  8067. if (firstId < currentPageNumber) {
  8068. return currentPageNumber - firstId + 1;
  8069. }
  8070. } else {
  8071. const lastId = yArray[numPages - 1];
  8072. if (lastId > currentPageNumber) {
  8073. return lastId - currentPageNumber + 1;
  8074. }
  8075. }
  8076. break;
  8077. }
  8078. break;
  8079. }
  8080. case ScrollMode.HORIZONTAL:
  8081. {
  8082. break;
  8083. }
  8084. case ScrollMode.PAGE:
  8085. case ScrollMode.VERTICAL:
  8086. {
  8087. if (this._spreadMode === SpreadMode.NONE) {
  8088. break;
  8089. }
  8090. const parity = this._spreadMode - 1;
  8091. if (previous && currentPageNumber % 2 !== parity) {
  8092. break;
  8093. } else if (!previous && currentPageNumber % 2 === parity) {
  8094. break;
  8095. }
  8096. const {
  8097. views
  8098. } = this._getVisiblePages(),
  8099. expectedId = previous ? currentPageNumber - 1 : currentPageNumber + 1;
  8100. for (const {
  8101. id,
  8102. percent,
  8103. widthPercent
  8104. } of views) {
  8105. if (id !== expectedId) {
  8106. continue;
  8107. }
  8108. if (percent > 0 && widthPercent === 100) {
  8109. return 2;
  8110. }
  8111. break;
  8112. }
  8113. break;
  8114. }
  8115. }
  8116. return 1;
  8117. }
  8118. nextPage() {
  8119. const currentPageNumber = this._currentPageNumber,
  8120. pagesCount = this.pagesCount;
  8121. if (currentPageNumber >= pagesCount) {
  8122. return false;
  8123. }
  8124. const advance = this._getPageAdvance(currentPageNumber, false) || 1;
  8125. this.currentPageNumber = Math.min(currentPageNumber + advance, pagesCount);
  8126. return true;
  8127. }
  8128. previousPage() {
  8129. const currentPageNumber = this._currentPageNumber;
  8130. if (currentPageNumber <= 1) {
  8131. return false;
  8132. }
  8133. const advance = this._getPageAdvance(currentPageNumber, true) || 1;
  8134. this.currentPageNumber = Math.max(currentPageNumber - advance, 1);
  8135. return true;
  8136. }
  8137. updateScale({
  8138. drawingDelay,
  8139. scaleFactor = null,
  8140. steps = null,
  8141. origin
  8142. }) {
  8143. if (steps === null && scaleFactor === null) {
  8144. throw new Error("Invalid updateScale options: either `steps` or `scaleFactor` must be provided.");
  8145. }
  8146. if (!this.pdfDocument) {
  8147. return;
  8148. }
  8149. let newScale = this._currentScale;
  8150. if (scaleFactor > 0 && scaleFactor !== 1) {
  8151. newScale = Math.round(newScale * scaleFactor * 100) / 100;
  8152. } else if (steps) {
  8153. const delta = steps > 0 ? DEFAULT_SCALE_DELTA : 1 / DEFAULT_SCALE_DELTA;
  8154. const round = steps > 0 ? Math.ceil : Math.floor;
  8155. steps = Math.abs(steps);
  8156. do {
  8157. newScale = round((newScale * delta).toFixed(2) * 10) / 10;
  8158. } while (--steps > 0);
  8159. }
  8160. newScale = Math.max(MIN_SCALE, Math.min(MAX_SCALE, newScale));
  8161. this.#setScale(newScale, {
  8162. noScroll: false,
  8163. drawingDelay,
  8164. origin
  8165. });
  8166. }
  8167. increaseScale(options = {}) {
  8168. this.updateScale({
  8169. ...options,
  8170. steps: options.steps ?? 1
  8171. });
  8172. }
  8173. decreaseScale(options = {}) {
  8174. this.updateScale({
  8175. ...options,
  8176. steps: -(options.steps ?? 1)
  8177. });
  8178. }
  8179. #updateContainerHeightCss(height = this.container.clientHeight) {
  8180. if (height !== this.#previousContainerHeight) {
  8181. this.#previousContainerHeight = height;
  8182. docStyle.setProperty("--viewer-container-height", `${height}px`);
  8183. }
  8184. }
  8185. #resizeObserverCallback(entries) {
  8186. for (const entry of entries) {
  8187. if (entry.target === this.container) {
  8188. this.#updateContainerHeightCss(Math.floor(entry.borderBoxSize[0].blockSize));
  8189. this.#containerTopLeft = null;
  8190. break;
  8191. }
  8192. }
  8193. }
  8194. get containerTopLeft() {
  8195. return this.#containerTopLeft ||= [this.container.offsetTop, this.container.offsetLeft];
  8196. }
  8197. #cleanupSwitchAnnotationEditorMode() {
  8198. this.#switchAnnotationEditorModeAC?.abort();
  8199. this.#switchAnnotationEditorModeAC = null;
  8200. if (this.#switchAnnotationEditorModeTimeoutId !== null) {
  8201. clearTimeout(this.#switchAnnotationEditorModeTimeoutId);
  8202. this.#switchAnnotationEditorModeTimeoutId = null;
  8203. }
  8204. }
  8205. get annotationEditorMode() {
  8206. return this.#annotationEditorUIManager ? this.#annotationEditorMode : AnnotationEditorType.DISABLE;
  8207. }
  8208. set annotationEditorMode({
  8209. mode,
  8210. editId = null,
  8211. isFromKeyboard = false
  8212. }) {
  8213. if (!this.#annotationEditorUIManager) {
  8214. throw new Error(`The AnnotationEditor is not enabled.`);
  8215. }
  8216. if (this.#annotationEditorMode === mode) {
  8217. return;
  8218. }
  8219. if (!isValidAnnotationEditorMode(mode)) {
  8220. throw new Error(`Invalid AnnotationEditor mode: ${mode}`);
  8221. }
  8222. if (!this.pdfDocument) {
  8223. return;
  8224. }
  8225. if (mode === AnnotationEditorType.STAMP) {
  8226. this.#mlManager?.loadModel("altText");
  8227. }
  8228. const {
  8229. eventBus
  8230. } = this;
  8231. const updater = () => {
  8232. this.#cleanupSwitchAnnotationEditorMode();
  8233. this.#annotationEditorMode = mode;
  8234. this.#annotationEditorUIManager.updateMode(mode, editId, isFromKeyboard);
  8235. eventBus.dispatch("annotationeditormodechanged", {
  8236. source: this,
  8237. mode
  8238. });
  8239. };
  8240. if (mode === AnnotationEditorType.NONE || this.#annotationEditorMode === AnnotationEditorType.NONE) {
  8241. const isEditing = mode !== AnnotationEditorType.NONE;
  8242. if (!isEditing) {
  8243. this.pdfDocument.annotationStorage.resetModifiedIds();
  8244. }
  8245. for (const pageView of this._pages) {
  8246. pageView.toggleEditingMode(isEditing);
  8247. }
  8248. const idsToRefresh = this.#switchToEditAnnotationMode();
  8249. if (isEditing && idsToRefresh) {
  8250. this.#cleanupSwitchAnnotationEditorMode();
  8251. this.#switchAnnotationEditorModeAC = new AbortController();
  8252. const signal = AbortSignal.any([this.#eventAbortController.signal, this.#switchAnnotationEditorModeAC.signal]);
  8253. eventBus._on("pagerendered", ({
  8254. pageNumber
  8255. }) => {
  8256. idsToRefresh.delete(pageNumber);
  8257. if (idsToRefresh.size === 0) {
  8258. this.#switchAnnotationEditorModeTimeoutId = setTimeout(updater, 0);
  8259. }
  8260. }, {
  8261. signal
  8262. });
  8263. return;
  8264. }
  8265. }
  8266. updater();
  8267. }
  8268. refresh(noUpdate = false, updateArgs = Object.create(null)) {
  8269. if (!this.pdfDocument) {
  8270. return;
  8271. }
  8272. for (const pageView of this._pages) {
  8273. pageView.update(updateArgs);
  8274. }
  8275. if (this.#scaleTimeoutId !== null) {
  8276. clearTimeout(this.#scaleTimeoutId);
  8277. this.#scaleTimeoutId = null;
  8278. }
  8279. if (!noUpdate) {
  8280. this.update();
  8281. }
  8282. }
  8283. }
  8284. ;// ./web/pdf_single_page_viewer.js
  8285. class PDFSinglePageViewer extends PDFViewer {
  8286. _resetView() {
  8287. super._resetView();
  8288. this._scrollMode = ScrollMode.PAGE;
  8289. this._spreadMode = SpreadMode.NONE;
  8290. }
  8291. set scrollMode(mode) {}
  8292. _updateScrollMode() {}
  8293. set spreadMode(mode) {}
  8294. _updateSpreadMode() {}
  8295. }
  8296. ;// ./web/pdf_viewer.component.js
  8297. const pdfjsVersion = "4.10.38";
  8298. const pdfjsBuild = "f9bea397f";
  8299. var __webpack_exports__AnnotationLayerBuilder = __webpack_exports__.AnnotationLayerBuilder;
  8300. var __webpack_exports__DownloadManager = __webpack_exports__.DownloadManager;
  8301. var __webpack_exports__EventBus = __webpack_exports__.EventBus;
  8302. var __webpack_exports__FindState = __webpack_exports__.FindState;
  8303. var __webpack_exports__GenericL10n = __webpack_exports__.GenericL10n;
  8304. var __webpack_exports__LinkTarget = __webpack_exports__.LinkTarget;
  8305. var __webpack_exports__PDFFindController = __webpack_exports__.PDFFindController;
  8306. var __webpack_exports__PDFHistory = __webpack_exports__.PDFHistory;
  8307. var __webpack_exports__PDFLinkService = __webpack_exports__.PDFLinkService;
  8308. var __webpack_exports__PDFPageView = __webpack_exports__.PDFPageView;
  8309. var __webpack_exports__PDFScriptingManager = __webpack_exports__.PDFScriptingManager;
  8310. var __webpack_exports__PDFSinglePageViewer = __webpack_exports__.PDFSinglePageViewer;
  8311. var __webpack_exports__PDFViewer = __webpack_exports__.PDFViewer;
  8312. var __webpack_exports__ProgressBar = __webpack_exports__.ProgressBar;
  8313. var __webpack_exports__RenderingStates = __webpack_exports__.RenderingStates;
  8314. var __webpack_exports__ScrollMode = __webpack_exports__.ScrollMode;
  8315. var __webpack_exports__SimpleLinkService = __webpack_exports__.SimpleLinkService;
  8316. var __webpack_exports__SpreadMode = __webpack_exports__.SpreadMode;
  8317. var __webpack_exports__StructTreeLayerBuilder = __webpack_exports__.StructTreeLayerBuilder;
  8318. var __webpack_exports__TextLayerBuilder = __webpack_exports__.TextLayerBuilder;
  8319. var __webpack_exports__XfaLayerBuilder = __webpack_exports__.XfaLayerBuilder;
  8320. var __webpack_exports__parseQueryString = __webpack_exports__.parseQueryString;
  8321. export { __webpack_exports__AnnotationLayerBuilder as AnnotationLayerBuilder, __webpack_exports__DownloadManager as DownloadManager, __webpack_exports__EventBus as EventBus, __webpack_exports__FindState as FindState, __webpack_exports__GenericL10n as GenericL10n, __webpack_exports__LinkTarget as LinkTarget, __webpack_exports__PDFFindController as PDFFindController, __webpack_exports__PDFHistory as PDFHistory, __webpack_exports__PDFLinkService as PDFLinkService, __webpack_exports__PDFPageView as PDFPageView, __webpack_exports__PDFScriptingManager as PDFScriptingManager, __webpack_exports__PDFSinglePageViewer as PDFSinglePageViewer, __webpack_exports__PDFViewer as PDFViewer, __webpack_exports__ProgressBar as ProgressBar, __webpack_exports__RenderingStates as RenderingStates, __webpack_exports__ScrollMode as ScrollMode, __webpack_exports__SimpleLinkService as SimpleLinkService, __webpack_exports__SpreadMode as SpreadMode, __webpack_exports__StructTreeLayerBuilder as StructTreeLayerBuilder, __webpack_exports__TextLayerBuilder as TextLayerBuilder, __webpack_exports__XfaLayerBuilder as XfaLayerBuilder, __webpack_exports__parseQueryString as parseQueryString };
  8322. //# sourceMappingURL=pdf_viewer.mjs.map