all.js 761 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968
  1. /* ---- base/codemirror.js ---- */
  2. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  3. // Distributed under an MIT license: https://codemirror.net/LICENSE
  4. // This is CodeMirror (https://codemirror.net), a code editor
  5. // implemented in JavaScript on top of the browser's DOM.
  6. //
  7. // You can find some technical background for some of the code below
  8. // at http://marijnhaverbeke.nl/blog/#cm-internals .
  9. (function (global, factory) {
  10. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  11. typeof define === 'function' && define.amd ? define(factory) :
  12. (global = global || self, global.CodeMirror = factory());
  13. }(this, (function () { 'use strict';
  14. // Kludges for bugs and behavior differences that can't be feature
  15. // detected are enabled based on userAgent etc sniffing.
  16. var userAgent = navigator.userAgent;
  17. var platform = navigator.platform;
  18. var gecko = /gecko\/\d/i.test(userAgent);
  19. var ie_upto10 = /MSIE \d/.test(userAgent);
  20. var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent);
  21. var edge = /Edge\/(\d+)/.exec(userAgent);
  22. var ie = ie_upto10 || ie_11up || edge;
  23. var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]);
  24. var webkit = !edge && /WebKit\//.test(userAgent);
  25. var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent);
  26. var chrome = !edge && /Chrome\//.test(userAgent);
  27. var presto = /Opera\//.test(userAgent);
  28. var safari = /Apple Computer/.test(navigator.vendor);
  29. var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent);
  30. var phantom = /PhantomJS/.test(userAgent);
  31. var ios = !edge && /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent);
  32. var android = /Android/.test(userAgent);
  33. // This is woefully incomplete. Suggestions for alternative methods welcome.
  34. var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);
  35. var mac = ios || /Mac/.test(platform);
  36. var chromeOS = /\bCrOS\b/.test(userAgent);
  37. var windows = /win/i.test(platform);
  38. var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/);
  39. if (presto_version) { presto_version = Number(presto_version[1]); }
  40. if (presto_version && presto_version >= 15) { presto = false; webkit = true; }
  41. // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
  42. var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11));
  43. var captureRightClick = gecko || (ie && ie_version >= 9);
  44. function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") }
  45. var rmClass = function(node, cls) {
  46. var current = node.className;
  47. var match = classTest(cls).exec(current);
  48. if (match) {
  49. var after = current.slice(match.index + match[0].length);
  50. node.className = current.slice(0, match.index) + (after ? match[1] + after : "");
  51. }
  52. };
  53. function removeChildren(e) {
  54. for (var count = e.childNodes.length; count > 0; --count)
  55. { e.removeChild(e.firstChild); }
  56. return e
  57. }
  58. function removeChildrenAndAdd(parent, e) {
  59. return removeChildren(parent).appendChild(e)
  60. }
  61. function elt(tag, content, className, style) {
  62. var e = document.createElement(tag);
  63. if (className) { e.className = className; }
  64. if (style) { e.style.cssText = style; }
  65. if (typeof content == "string") { e.appendChild(document.createTextNode(content)); }
  66. else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]); } }
  67. return e
  68. }
  69. // wrapper for elt, which removes the elt from the accessibility tree
  70. function eltP(tag, content, className, style) {
  71. var e = elt(tag, content, className, style);
  72. e.setAttribute("role", "presentation");
  73. return e
  74. }
  75. var range;
  76. if (document.createRange) { range = function(node, start, end, endNode) {
  77. var r = document.createRange();
  78. r.setEnd(endNode || node, end);
  79. r.setStart(node, start);
  80. return r
  81. }; }
  82. else { range = function(node, start, end) {
  83. var r = document.body.createTextRange();
  84. try { r.moveToElementText(node.parentNode); }
  85. catch(e) { return r }
  86. r.collapse(true);
  87. r.moveEnd("character", end);
  88. r.moveStart("character", start);
  89. return r
  90. }; }
  91. function contains(parent, child) {
  92. if (child.nodeType == 3) // Android browser always returns false when child is a textnode
  93. { child = child.parentNode; }
  94. if (parent.contains)
  95. { return parent.contains(child) }
  96. do {
  97. if (child.nodeType == 11) { child = child.host; }
  98. if (child == parent) { return true }
  99. } while (child = child.parentNode)
  100. }
  101. function activeElt() {
  102. // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement.
  103. // IE < 10 will throw when accessed while the page is loading or in an iframe.
  104. // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable.
  105. var activeElement;
  106. try {
  107. activeElement = document.activeElement;
  108. } catch(e) {
  109. activeElement = document.body || null;
  110. }
  111. while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement)
  112. { activeElement = activeElement.shadowRoot.activeElement; }
  113. return activeElement
  114. }
  115. function addClass(node, cls) {
  116. var current = node.className;
  117. if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls; }
  118. }
  119. function joinClasses(a, b) {
  120. var as = a.split(" ");
  121. for (var i = 0; i < as.length; i++)
  122. { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i]; } }
  123. return b
  124. }
  125. var selectInput = function(node) { node.select(); };
  126. if (ios) // Mobile Safari apparently has a bug where select() is broken.
  127. { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; }
  128. else if (ie) // Suppress mysterious IE10 errors
  129. { selectInput = function(node) { try { node.select(); } catch(_e) {} }; }
  130. function bind(f) {
  131. var args = Array.prototype.slice.call(arguments, 1);
  132. return function(){return f.apply(null, args)}
  133. }
  134. function copyObj(obj, target, overwrite) {
  135. if (!target) { target = {}; }
  136. for (var prop in obj)
  137. { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
  138. { target[prop] = obj[prop]; } }
  139. return target
  140. }
  141. // Counts the column offset in a string, taking tabs into account.
  142. // Used mostly to find indentation.
  143. function countColumn(string, end, tabSize, startIndex, startValue) {
  144. if (end == null) {
  145. end = string.search(/[^\s\u00a0]/);
  146. if (end == -1) { end = string.length; }
  147. }
  148. for (var i = startIndex || 0, n = startValue || 0;;) {
  149. var nextTab = string.indexOf("\t", i);
  150. if (nextTab < 0 || nextTab >= end)
  151. { return n + (end - i) }
  152. n += nextTab - i;
  153. n += tabSize - (n % tabSize);
  154. i = nextTab + 1;
  155. }
  156. }
  157. var Delayed = function() {
  158. this.id = null;
  159. this.f = null;
  160. this.time = 0;
  161. this.handler = bind(this.onTimeout, this);
  162. };
  163. Delayed.prototype.onTimeout = function (self) {
  164. self.id = 0;
  165. if (self.time <= +new Date) {
  166. self.f();
  167. } else {
  168. setTimeout(self.handler, self.time - +new Date);
  169. }
  170. };
  171. Delayed.prototype.set = function (ms, f) {
  172. this.f = f;
  173. var time = +new Date + ms;
  174. if (!this.id || time < this.time) {
  175. clearTimeout(this.id);
  176. this.id = setTimeout(this.handler, ms);
  177. this.time = time;
  178. }
  179. };
  180. function indexOf(array, elt) {
  181. for (var i = 0; i < array.length; ++i)
  182. { if (array[i] == elt) { return i } }
  183. return -1
  184. }
  185. // Number of pixels added to scroller and sizer to hide scrollbar
  186. var scrollerGap = 50;
  187. // Returned or thrown by various protocols to signal 'I'm not
  188. // handling this'.
  189. var Pass = {toString: function(){return "CodeMirror.Pass"}};
  190. // Reused option objects for setSelection & friends
  191. var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"};
  192. // The inverse of countColumn -- find the offset that corresponds to
  193. // a particular column.
  194. function findColumn(string, goal, tabSize) {
  195. for (var pos = 0, col = 0;;) {
  196. var nextTab = string.indexOf("\t", pos);
  197. if (nextTab == -1) { nextTab = string.length; }
  198. var skipped = nextTab - pos;
  199. if (nextTab == string.length || col + skipped >= goal)
  200. { return pos + Math.min(skipped, goal - col) }
  201. col += nextTab - pos;
  202. col += tabSize - (col % tabSize);
  203. pos = nextTab + 1;
  204. if (col >= goal) { return pos }
  205. }
  206. }
  207. var spaceStrs = [""];
  208. function spaceStr(n) {
  209. while (spaceStrs.length <= n)
  210. { spaceStrs.push(lst(spaceStrs) + " "); }
  211. return spaceStrs[n]
  212. }
  213. function lst(arr) { return arr[arr.length-1] }
  214. function map(array, f) {
  215. var out = [];
  216. for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i); }
  217. return out
  218. }
  219. function insertSorted(array, value, score) {
  220. var pos = 0, priority = score(value);
  221. while (pos < array.length && score(array[pos]) <= priority) { pos++; }
  222. array.splice(pos, 0, value);
  223. }
  224. function nothing() {}
  225. function createObj(base, props) {
  226. var inst;
  227. if (Object.create) {
  228. inst = Object.create(base);
  229. } else {
  230. nothing.prototype = base;
  231. inst = new nothing();
  232. }
  233. if (props) { copyObj(props, inst); }
  234. return inst
  235. }
  236. var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;
  237. function isWordCharBasic(ch) {
  238. return /\w/.test(ch) || ch > "\x80" &&
  239. (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch))
  240. }
  241. function isWordChar(ch, helper) {
  242. if (!helper) { return isWordCharBasic(ch) }
  243. if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true }
  244. return helper.test(ch)
  245. }
  246. function isEmpty(obj) {
  247. for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } }
  248. return true
  249. }
  250. // Extending unicode characters. A series of a non-extending char +
  251. // any number of extending chars is treated as a single unit as far
  252. // as editing and measuring is concerned. This is not fully correct,
  253. // since some scripts/fonts/browsers also treat other configurations
  254. // of code points as a group.
  255. var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;
  256. function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) }
  257. // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range.
  258. function skipExtendingChars(str, pos, dir) {
  259. while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir; }
  260. return pos
  261. }
  262. // Returns the value from the range [`from`; `to`] that satisfies
  263. // `pred` and is closest to `from`. Assumes that at least `to`
  264. // satisfies `pred`. Supports `from` being greater than `to`.
  265. function findFirst(pred, from, to) {
  266. // At any point we are certain `to` satisfies `pred`, don't know
  267. // whether `from` does.
  268. var dir = from > to ? -1 : 1;
  269. for (;;) {
  270. if (from == to) { return from }
  271. var midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF);
  272. if (mid == from) { return pred(mid) ? from : to }
  273. if (pred(mid)) { to = mid; }
  274. else { from = mid + dir; }
  275. }
  276. }
  277. // BIDI HELPERS
  278. function iterateBidiSections(order, from, to, f) {
  279. if (!order) { return f(from, to, "ltr", 0) }
  280. var found = false;
  281. for (var i = 0; i < order.length; ++i) {
  282. var part = order[i];
  283. if (part.from < to && part.to > from || from == to && part.to == from) {
  284. f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i);
  285. found = true;
  286. }
  287. }
  288. if (!found) { f(from, to, "ltr"); }
  289. }
  290. var bidiOther = null;
  291. function getBidiPartAt(order, ch, sticky) {
  292. var found;
  293. bidiOther = null;
  294. for (var i = 0; i < order.length; ++i) {
  295. var cur = order[i];
  296. if (cur.from < ch && cur.to > ch) { return i }
  297. if (cur.to == ch) {
  298. if (cur.from != cur.to && sticky == "before") { found = i; }
  299. else { bidiOther = i; }
  300. }
  301. if (cur.from == ch) {
  302. if (cur.from != cur.to && sticky != "before") { found = i; }
  303. else { bidiOther = i; }
  304. }
  305. }
  306. return found != null ? found : bidiOther
  307. }
  308. // Bidirectional ordering algorithm
  309. // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
  310. // that this (partially) implements.
  311. // One-char codes used for character types:
  312. // L (L): Left-to-Right
  313. // R (R): Right-to-Left
  314. // r (AL): Right-to-Left Arabic
  315. // 1 (EN): European Number
  316. // + (ES): European Number Separator
  317. // % (ET): European Number Terminator
  318. // n (AN): Arabic Number
  319. // , (CS): Common Number Separator
  320. // m (NSM): Non-Spacing Mark
  321. // b (BN): Boundary Neutral
  322. // s (B): Paragraph Separator
  323. // t (S): Segment Separator
  324. // w (WS): Whitespace
  325. // N (ON): Other Neutrals
  326. // Returns null if characters are ordered as they appear
  327. // (left-to-right), or an array of sections ({from, to, level}
  328. // objects) in the order in which they occur visually.
  329. var bidiOrdering = (function() {
  330. // Character types for codepoints 0 to 0xff
  331. var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN";
  332. // Character types for codepoints 0x600 to 0x6f9
  333. var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111";
  334. function charType(code) {
  335. if (code <= 0xf7) { return lowTypes.charAt(code) }
  336. else if (0x590 <= code && code <= 0x5f4) { return "R" }
  337. else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) }
  338. else if (0x6ee <= code && code <= 0x8ac) { return "r" }
  339. else if (0x2000 <= code && code <= 0x200b) { return "w" }
  340. else if (code == 0x200c) { return "b" }
  341. else { return "L" }
  342. }
  343. var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
  344. var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/;
  345. function BidiSpan(level, from, to) {
  346. this.level = level;
  347. this.from = from; this.to = to;
  348. }
  349. return function(str, direction) {
  350. var outerType = direction == "ltr" ? "L" : "R";
  351. if (str.length == 0 || direction == "ltr" && !bidiRE.test(str)) { return false }
  352. var len = str.length, types = [];
  353. for (var i = 0; i < len; ++i)
  354. { types.push(charType(str.charCodeAt(i))); }
  355. // W1. Examine each non-spacing mark (NSM) in the level run, and
  356. // change the type of the NSM to the type of the previous
  357. // character. If the NSM is at the start of the level run, it will
  358. // get the type of sor.
  359. for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) {
  360. var type = types[i$1];
  361. if (type == "m") { types[i$1] = prev; }
  362. else { prev = type; }
  363. }
  364. // W2. Search backwards from each instance of a European number
  365. // until the first strong type (R, L, AL, or sor) is found. If an
  366. // AL is found, change the type of the European number to Arabic
  367. // number.
  368. // W3. Change all ALs to R.
  369. for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) {
  370. var type$1 = types[i$2];
  371. if (type$1 == "1" && cur == "r") { types[i$2] = "n"; }
  372. else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R"; } }
  373. }
  374. // W4. A single European separator between two European numbers
  375. // changes to a European number. A single common separator between
  376. // two numbers of the same type changes to that type.
  377. for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) {
  378. var type$2 = types[i$3];
  379. if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1"; }
  380. else if (type$2 == "," && prev$1 == types[i$3+1] &&
  381. (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1; }
  382. prev$1 = type$2;
  383. }
  384. // W5. A sequence of European terminators adjacent to European
  385. // numbers changes to all European numbers.
  386. // W6. Otherwise, separators and terminators change to Other
  387. // Neutral.
  388. for (var i$4 = 0; i$4 < len; ++i$4) {
  389. var type$3 = types[i$4];
  390. if (type$3 == ",") { types[i$4] = "N"; }
  391. else if (type$3 == "%") {
  392. var end = (void 0);
  393. for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {}
  394. var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N";
  395. for (var j = i$4; j < end; ++j) { types[j] = replace; }
  396. i$4 = end - 1;
  397. }
  398. }
  399. // W7. Search backwards from each instance of a European number
  400. // until the first strong type (R, L, or sor) is found. If an L is
  401. // found, then change the type of the European number to L.
  402. for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) {
  403. var type$4 = types[i$5];
  404. if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L"; }
  405. else if (isStrong.test(type$4)) { cur$1 = type$4; }
  406. }
  407. // N1. A sequence of neutrals takes the direction of the
  408. // surrounding strong text if the text on both sides has the same
  409. // direction. European and Arabic numbers act as if they were R in
  410. // terms of their influence on neutrals. Start-of-level-run (sor)
  411. // and end-of-level-run (eor) are used at level run boundaries.
  412. // N2. Any remaining neutrals take the embedding direction.
  413. for (var i$6 = 0; i$6 < len; ++i$6) {
  414. if (isNeutral.test(types[i$6])) {
  415. var end$1 = (void 0);
  416. for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {}
  417. var before = (i$6 ? types[i$6-1] : outerType) == "L";
  418. var after = (end$1 < len ? types[end$1] : outerType) == "L";
  419. var replace$1 = before == after ? (before ? "L" : "R") : outerType;
  420. for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1; }
  421. i$6 = end$1 - 1;
  422. }
  423. }
  424. // Here we depart from the documented algorithm, in order to avoid
  425. // building up an actual levels array. Since there are only three
  426. // levels (0, 1, 2) in an implementation that doesn't take
  427. // explicit embedding into account, we can build up the order on
  428. // the fly, without following the level-based algorithm.
  429. var order = [], m;
  430. for (var i$7 = 0; i$7 < len;) {
  431. if (countsAsLeft.test(types[i$7])) {
  432. var start = i$7;
  433. for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {}
  434. order.push(new BidiSpan(0, start, i$7));
  435. } else {
  436. var pos = i$7, at = order.length, isRTL = direction == "rtl" ? 1 : 0;
  437. for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {}
  438. for (var j$2 = pos; j$2 < i$7;) {
  439. if (countsAsNum.test(types[j$2])) {
  440. if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)); at += isRTL; }
  441. var nstart = j$2;
  442. for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {}
  443. order.splice(at, 0, new BidiSpan(2, nstart, j$2));
  444. at += isRTL;
  445. pos = j$2;
  446. } else { ++j$2; }
  447. }
  448. if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)); }
  449. }
  450. }
  451. if (direction == "ltr") {
  452. if (order[0].level == 1 && (m = str.match(/^\s+/))) {
  453. order[0].from = m[0].length;
  454. order.unshift(new BidiSpan(0, 0, m[0].length));
  455. }
  456. if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
  457. lst(order).to -= m[0].length;
  458. order.push(new BidiSpan(0, len - m[0].length, len));
  459. }
  460. }
  461. return direction == "rtl" ? order.reverse() : order
  462. }
  463. })();
  464. // Get the bidi ordering for the given line (and cache it). Returns
  465. // false for lines that are fully left-to-right, and an array of
  466. // BidiSpan objects otherwise.
  467. function getOrder(line, direction) {
  468. var order = line.order;
  469. if (order == null) { order = line.order = bidiOrdering(line.text, direction); }
  470. return order
  471. }
  472. // EVENT HANDLING
  473. // Lightweight event framework. on/off also work on DOM nodes,
  474. // registering native DOM handlers.
  475. var noHandlers = [];
  476. var on = function(emitter, type, f) {
  477. if (emitter.addEventListener) {
  478. emitter.addEventListener(type, f, false);
  479. } else if (emitter.attachEvent) {
  480. emitter.attachEvent("on" + type, f);
  481. } else {
  482. var map = emitter._handlers || (emitter._handlers = {});
  483. map[type] = (map[type] || noHandlers).concat(f);
  484. }
  485. };
  486. function getHandlers(emitter, type) {
  487. return emitter._handlers && emitter._handlers[type] || noHandlers
  488. }
  489. function off(emitter, type, f) {
  490. if (emitter.removeEventListener) {
  491. emitter.removeEventListener(type, f, false);
  492. } else if (emitter.detachEvent) {
  493. emitter.detachEvent("on" + type, f);
  494. } else {
  495. var map = emitter._handlers, arr = map && map[type];
  496. if (arr) {
  497. var index = indexOf(arr, f);
  498. if (index > -1)
  499. { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)); }
  500. }
  501. }
  502. }
  503. function signal(emitter, type /*, values...*/) {
  504. var handlers = getHandlers(emitter, type);
  505. if (!handlers.length) { return }
  506. var args = Array.prototype.slice.call(arguments, 2);
  507. for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args); }
  508. }
  509. // The DOM events that CodeMirror handles can be overridden by
  510. // registering a (non-DOM) handler on the editor for the event name,
  511. // and preventDefault-ing the event in that handler.
  512. function signalDOMEvent(cm, e, override) {
  513. if (typeof e == "string")
  514. { e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; }
  515. signal(cm, override || e.type, cm, e);
  516. return e_defaultPrevented(e) || e.codemirrorIgnore
  517. }
  518. function signalCursorActivity(cm) {
  519. var arr = cm._handlers && cm._handlers.cursorActivity;
  520. if (!arr) { return }
  521. var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []);
  522. for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1)
  523. { set.push(arr[i]); } }
  524. }
  525. function hasHandler(emitter, type) {
  526. return getHandlers(emitter, type).length > 0
  527. }
  528. // Add on and off methods to a constructor's prototype, to make
  529. // registering events on such objects more convenient.
  530. function eventMixin(ctor) {
  531. ctor.prototype.on = function(type, f) {on(this, type, f);};
  532. ctor.prototype.off = function(type, f) {off(this, type, f);};
  533. }
  534. // Due to the fact that we still support jurassic IE versions, some
  535. // compatibility wrappers are needed.
  536. function e_preventDefault(e) {
  537. if (e.preventDefault) { e.preventDefault(); }
  538. else { e.returnValue = false; }
  539. }
  540. function e_stopPropagation(e) {
  541. if (e.stopPropagation) { e.stopPropagation(); }
  542. else { e.cancelBubble = true; }
  543. }
  544. function e_defaultPrevented(e) {
  545. return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false
  546. }
  547. function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);}
  548. function e_target(e) {return e.target || e.srcElement}
  549. function e_button(e) {
  550. var b = e.which;
  551. if (b == null) {
  552. if (e.button & 1) { b = 1; }
  553. else if (e.button & 2) { b = 3; }
  554. else if (e.button & 4) { b = 2; }
  555. }
  556. if (mac && e.ctrlKey && b == 1) { b = 3; }
  557. return b
  558. }
  559. // Detect drag-and-drop
  560. var dragAndDrop = function() {
  561. // There is *some* kind of drag-and-drop support in IE6-8, but I
  562. // couldn't get it to work yet.
  563. if (ie && ie_version < 9) { return false }
  564. var div = elt('div');
  565. return "draggable" in div || "dragDrop" in div
  566. }();
  567. var zwspSupported;
  568. function zeroWidthElement(measure) {
  569. if (zwspSupported == null) {
  570. var test = elt("span", "\u200b");
  571. removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]));
  572. if (measure.firstChild.offsetHeight != 0)
  573. { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); }
  574. }
  575. var node = zwspSupported ? elt("span", "\u200b") :
  576. elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px");
  577. node.setAttribute("cm-text", "");
  578. return node
  579. }
  580. // Feature-detect IE's crummy client rect reporting for bidi text
  581. var badBidiRects;
  582. function hasBadBidiRects(measure) {
  583. if (badBidiRects != null) { return badBidiRects }
  584. var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"));
  585. var r0 = range(txt, 0, 1).getBoundingClientRect();
  586. var r1 = range(txt, 1, 2).getBoundingClientRect();
  587. removeChildren(measure);
  588. if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780)
  589. return badBidiRects = (r1.right - r0.right < 3)
  590. }
  591. // See if "".split is the broken IE version, if so, provide an
  592. // alternative way to split lines.
  593. var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) {
  594. var pos = 0, result = [], l = string.length;
  595. while (pos <= l) {
  596. var nl = string.indexOf("\n", pos);
  597. if (nl == -1) { nl = string.length; }
  598. var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl);
  599. var rt = line.indexOf("\r");
  600. if (rt != -1) {
  601. result.push(line.slice(0, rt));
  602. pos += rt + 1;
  603. } else {
  604. result.push(line);
  605. pos = nl + 1;
  606. }
  607. }
  608. return result
  609. } : function (string) { return string.split(/\r\n?|\n/); };
  610. var hasSelection = window.getSelection ? function (te) {
  611. try { return te.selectionStart != te.selectionEnd }
  612. catch(e) { return false }
  613. } : function (te) {
  614. var range;
  615. try {range = te.ownerDocument.selection.createRange();}
  616. catch(e) {}
  617. if (!range || range.parentElement() != te) { return false }
  618. return range.compareEndPoints("StartToEnd", range) != 0
  619. };
  620. var hasCopyEvent = (function () {
  621. var e = elt("div");
  622. if ("oncopy" in e) { return true }
  623. e.setAttribute("oncopy", "return;");
  624. return typeof e.oncopy == "function"
  625. })();
  626. var badZoomedRects = null;
  627. function hasBadZoomedRects(measure) {
  628. if (badZoomedRects != null) { return badZoomedRects }
  629. var node = removeChildrenAndAdd(measure, elt("span", "x"));
  630. var normal = node.getBoundingClientRect();
  631. var fromRange = range(node, 0, 1).getBoundingClientRect();
  632. return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1
  633. }
  634. // Known modes, by name and by MIME
  635. var modes = {}, mimeModes = {};
  636. // Extra arguments are stored as the mode's dependencies, which is
  637. // used by (legacy) mechanisms like loadmode.js to automatically
  638. // load a mode. (Preferred mechanism is the require/define calls.)
  639. function defineMode(name, mode) {
  640. if (arguments.length > 2)
  641. { mode.dependencies = Array.prototype.slice.call(arguments, 2); }
  642. modes[name] = mode;
  643. }
  644. function defineMIME(mime, spec) {
  645. mimeModes[mime] = spec;
  646. }
  647. // Given a MIME type, a {name, ...options} config object, or a name
  648. // string, return a mode config object.
  649. function resolveMode(spec) {
  650. if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
  651. spec = mimeModes[spec];
  652. } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
  653. var found = mimeModes[spec.name];
  654. if (typeof found == "string") { found = {name: found}; }
  655. spec = createObj(found, spec);
  656. spec.name = found.name;
  657. } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
  658. return resolveMode("application/xml")
  659. } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) {
  660. return resolveMode("application/json")
  661. }
  662. if (typeof spec == "string") { return {name: spec} }
  663. else { return spec || {name: "null"} }
  664. }
  665. // Given a mode spec (anything that resolveMode accepts), find and
  666. // initialize an actual mode object.
  667. function getMode(options, spec) {
  668. spec = resolveMode(spec);
  669. var mfactory = modes[spec.name];
  670. if (!mfactory) { return getMode(options, "text/plain") }
  671. var modeObj = mfactory(options, spec);
  672. if (modeExtensions.hasOwnProperty(spec.name)) {
  673. var exts = modeExtensions[spec.name];
  674. for (var prop in exts) {
  675. if (!exts.hasOwnProperty(prop)) { continue }
  676. if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; }
  677. modeObj[prop] = exts[prop];
  678. }
  679. }
  680. modeObj.name = spec.name;
  681. if (spec.helperType) { modeObj.helperType = spec.helperType; }
  682. if (spec.modeProps) { for (var prop$1 in spec.modeProps)
  683. { modeObj[prop$1] = spec.modeProps[prop$1]; } }
  684. return modeObj
  685. }
  686. // This can be used to attach properties to mode objects from
  687. // outside the actual mode definition.
  688. var modeExtensions = {};
  689. function extendMode(mode, properties) {
  690. var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
  691. copyObj(properties, exts);
  692. }
  693. function copyState(mode, state) {
  694. if (state === true) { return state }
  695. if (mode.copyState) { return mode.copyState(state) }
  696. var nstate = {};
  697. for (var n in state) {
  698. var val = state[n];
  699. if (val instanceof Array) { val = val.concat([]); }
  700. nstate[n] = val;
  701. }
  702. return nstate
  703. }
  704. // Given a mode and a state (for that mode), find the inner mode and
  705. // state at the position that the state refers to.
  706. function innerMode(mode, state) {
  707. var info;
  708. while (mode.innerMode) {
  709. info = mode.innerMode(state);
  710. if (!info || info.mode == mode) { break }
  711. state = info.state;
  712. mode = info.mode;
  713. }
  714. return info || {mode: mode, state: state}
  715. }
  716. function startState(mode, a1, a2) {
  717. return mode.startState ? mode.startState(a1, a2) : true
  718. }
  719. // STRING STREAM
  720. // Fed to the mode parsers, provides helper functions to make
  721. // parsers more succinct.
  722. var StringStream = function(string, tabSize, lineOracle) {
  723. this.pos = this.start = 0;
  724. this.string = string;
  725. this.tabSize = tabSize || 8;
  726. this.lastColumnPos = this.lastColumnValue = 0;
  727. this.lineStart = 0;
  728. this.lineOracle = lineOracle;
  729. };
  730. StringStream.prototype.eol = function () {return this.pos >= this.string.length};
  731. StringStream.prototype.sol = function () {return this.pos == this.lineStart};
  732. StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined};
  733. StringStream.prototype.next = function () {
  734. if (this.pos < this.string.length)
  735. { return this.string.charAt(this.pos++) }
  736. };
  737. StringStream.prototype.eat = function (match) {
  738. var ch = this.string.charAt(this.pos);
  739. var ok;
  740. if (typeof match == "string") { ok = ch == match; }
  741. else { ok = ch && (match.test ? match.test(ch) : match(ch)); }
  742. if (ok) {++this.pos; return ch}
  743. };
  744. StringStream.prototype.eatWhile = function (match) {
  745. var start = this.pos;
  746. while (this.eat(match)){}
  747. return this.pos > start
  748. };
  749. StringStream.prototype.eatSpace = function () {
  750. var start = this.pos;
  751. while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this.pos; }
  752. return this.pos > start
  753. };
  754. StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;};
  755. StringStream.prototype.skipTo = function (ch) {
  756. var found = this.string.indexOf(ch, this.pos);
  757. if (found > -1) {this.pos = found; return true}
  758. };
  759. StringStream.prototype.backUp = function (n) {this.pos -= n;};
  760. StringStream.prototype.column = function () {
  761. if (this.lastColumnPos < this.start) {
  762. this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
  763. this.lastColumnPos = this.start;
  764. }
  765. return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
  766. };
  767. StringStream.prototype.indentation = function () {
  768. return countColumn(this.string, null, this.tabSize) -
  769. (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
  770. };
  771. StringStream.prototype.match = function (pattern, consume, caseInsensitive) {
  772. if (typeof pattern == "string") {
  773. var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; };
  774. var substr = this.string.substr(this.pos, pattern.length);
  775. if (cased(substr) == cased(pattern)) {
  776. if (consume !== false) { this.pos += pattern.length; }
  777. return true
  778. }
  779. } else {
  780. var match = this.string.slice(this.pos).match(pattern);
  781. if (match && match.index > 0) { return null }
  782. if (match && consume !== false) { this.pos += match[0].length; }
  783. return match
  784. }
  785. };
  786. StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)};
  787. StringStream.prototype.hideFirstChars = function (n, inner) {
  788. this.lineStart += n;
  789. try { return inner() }
  790. finally { this.lineStart -= n; }
  791. };
  792. StringStream.prototype.lookAhead = function (n) {
  793. var oracle = this.lineOracle;
  794. return oracle && oracle.lookAhead(n)
  795. };
  796. StringStream.prototype.baseToken = function () {
  797. var oracle = this.lineOracle;
  798. return oracle && oracle.baseToken(this.pos)
  799. };
  800. // Find the line object corresponding to the given line number.
  801. function getLine(doc, n) {
  802. n -= doc.first;
  803. if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") }
  804. var chunk = doc;
  805. while (!chunk.lines) {
  806. for (var i = 0;; ++i) {
  807. var child = chunk.children[i], sz = child.chunkSize();
  808. if (n < sz) { chunk = child; break }
  809. n -= sz;
  810. }
  811. }
  812. return chunk.lines[n]
  813. }
  814. // Get the part of a document between two positions, as an array of
  815. // strings.
  816. function getBetween(doc, start, end) {
  817. var out = [], n = start.line;
  818. doc.iter(start.line, end.line + 1, function (line) {
  819. var text = line.text;
  820. if (n == end.line) { text = text.slice(0, end.ch); }
  821. if (n == start.line) { text = text.slice(start.ch); }
  822. out.push(text);
  823. ++n;
  824. });
  825. return out
  826. }
  827. // Get the lines between from and to, as array of strings.
  828. function getLines(doc, from, to) {
  829. var out = [];
  830. doc.iter(from, to, function (line) { out.push(line.text); }); // iter aborts when callback returns truthy value
  831. return out
  832. }
  833. // Update the height of a line, propagating the height change
  834. // upwards to parent nodes.
  835. function updateLineHeight(line, height) {
  836. var diff = height - line.height;
  837. if (diff) { for (var n = line; n; n = n.parent) { n.height += diff; } }
  838. }
  839. // Given a line object, find its line number by walking up through
  840. // its parent links.
  841. function lineNo(line) {
  842. if (line.parent == null) { return null }
  843. var cur = line.parent, no = indexOf(cur.lines, line);
  844. for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
  845. for (var i = 0;; ++i) {
  846. if (chunk.children[i] == cur) { break }
  847. no += chunk.children[i].chunkSize();
  848. }
  849. }
  850. return no + cur.first
  851. }
  852. // Find the line at the given vertical position, using the height
  853. // information in the document tree.
  854. function lineAtHeight(chunk, h) {
  855. var n = chunk.first;
  856. outer: do {
  857. for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) {
  858. var child = chunk.children[i$1], ch = child.height;
  859. if (h < ch) { chunk = child; continue outer }
  860. h -= ch;
  861. n += child.chunkSize();
  862. }
  863. return n
  864. } while (!chunk.lines)
  865. var i = 0;
  866. for (; i < chunk.lines.length; ++i) {
  867. var line = chunk.lines[i], lh = line.height;
  868. if (h < lh) { break }
  869. h -= lh;
  870. }
  871. return n + i
  872. }
  873. function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size}
  874. function lineNumberFor(options, i) {
  875. return String(options.lineNumberFormatter(i + options.firstLineNumber))
  876. }
  877. // A Pos instance represents a position within the text.
  878. function Pos(line, ch, sticky) {
  879. if ( sticky === void 0 ) sticky = null;
  880. if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) }
  881. this.line = line;
  882. this.ch = ch;
  883. this.sticky = sticky;
  884. }
  885. // Compare two positions, return 0 if they are the same, a negative
  886. // number when a is less, and a positive number otherwise.
  887. function cmp(a, b) { return a.line - b.line || a.ch - b.ch }
  888. function equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 }
  889. function copyPos(x) {return Pos(x.line, x.ch)}
  890. function maxPos(a, b) { return cmp(a, b) < 0 ? b : a }
  891. function minPos(a, b) { return cmp(a, b) < 0 ? a : b }
  892. // Most of the external API clips given positions to make sure they
  893. // actually exist within the document.
  894. function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))}
  895. function clipPos(doc, pos) {
  896. if (pos.line < doc.first) { return Pos(doc.first, 0) }
  897. var last = doc.first + doc.size - 1;
  898. if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) }
  899. return clipToLen(pos, getLine(doc, pos.line).text.length)
  900. }
  901. function clipToLen(pos, linelen) {
  902. var ch = pos.ch;
  903. if (ch == null || ch > linelen) { return Pos(pos.line, linelen) }
  904. else if (ch < 0) { return Pos(pos.line, 0) }
  905. else { return pos }
  906. }
  907. function clipPosArray(doc, array) {
  908. var out = [];
  909. for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]); }
  910. return out
  911. }
  912. var SavedContext = function(state, lookAhead) {
  913. this.state = state;
  914. this.lookAhead = lookAhead;
  915. };
  916. var Context = function(doc, state, line, lookAhead) {
  917. this.state = state;
  918. this.doc = doc;
  919. this.line = line;
  920. this.maxLookAhead = lookAhead || 0;
  921. this.baseTokens = null;
  922. this.baseTokenPos = 1;
  923. };
  924. Context.prototype.lookAhead = function (n) {
  925. var line = this.doc.getLine(this.line + n);
  926. if (line != null && n > this.maxLookAhead) { this.maxLookAhead = n; }
  927. return line
  928. };
  929. Context.prototype.baseToken = function (n) {
  930. if (!this.baseTokens) { return null }
  931. while (this.baseTokens[this.baseTokenPos] <= n)
  932. { this.baseTokenPos += 2; }
  933. var type = this.baseTokens[this.baseTokenPos + 1];
  934. return {type: type && type.replace(/( |^)overlay .*/, ""),
  935. size: this.baseTokens[this.baseTokenPos] - n}
  936. };
  937. Context.prototype.nextLine = function () {
  938. this.line++;
  939. if (this.maxLookAhead > 0) { this.maxLookAhead--; }
  940. };
  941. Context.fromSaved = function (doc, saved, line) {
  942. if (saved instanceof SavedContext)
  943. { return new Context(doc, copyState(doc.mode, saved.state), line, saved.lookAhead) }
  944. else
  945. { return new Context(doc, copyState(doc.mode, saved), line) }
  946. };
  947. Context.prototype.save = function (copy) {
  948. var state = copy !== false ? copyState(this.doc.mode, this.state) : this.state;
  949. return this.maxLookAhead > 0 ? new SavedContext(state, this.maxLookAhead) : state
  950. };
  951. // Compute a style array (an array starting with a mode generation
  952. // -- for invalidation -- followed by pairs of end positions and
  953. // style strings), which is used to highlight the tokens on the
  954. // line.
  955. function highlightLine(cm, line, context, forceToEnd) {
  956. // A styles array always starts with a number identifying the
  957. // mode/overlays that it is based on (for easy invalidation).
  958. var st = [cm.state.modeGen], lineClasses = {};
  959. // Compute the base array of styles
  960. runMode(cm, line.text, cm.doc.mode, context, function (end, style) { return st.push(end, style); },
  961. lineClasses, forceToEnd);
  962. var state = context.state;
  963. // Run overlays, adjust style array.
  964. var loop = function ( o ) {
  965. context.baseTokens = st;
  966. var overlay = cm.state.overlays[o], i = 1, at = 0;
  967. context.state = true;
  968. runMode(cm, line.text, overlay.mode, context, function (end, style) {
  969. var start = i;
  970. // Ensure there's a token end at the current position, and that i points at it
  971. while (at < end) {
  972. var i_end = st[i];
  973. if (i_end > end)
  974. { st.splice(i, 1, end, st[i+1], i_end); }
  975. i += 2;
  976. at = Math.min(end, i_end);
  977. }
  978. if (!style) { return }
  979. if (overlay.opaque) {
  980. st.splice(start, i - start, end, "overlay " + style);
  981. i = start + 2;
  982. } else {
  983. for (; start < i; start += 2) {
  984. var cur = st[start+1];
  985. st[start+1] = (cur ? cur + " " : "") + "overlay " + style;
  986. }
  987. }
  988. }, lineClasses);
  989. context.state = state;
  990. context.baseTokens = null;
  991. context.baseTokenPos = 1;
  992. };
  993. for (var o = 0; o < cm.state.overlays.length; ++o) loop( o );
  994. return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null}
  995. }
  996. function getLineStyles(cm, line, updateFrontier) {
  997. if (!line.styles || line.styles[0] != cm.state.modeGen) {
  998. var context = getContextBefore(cm, lineNo(line));
  999. var resetState = line.text.length > cm.options.maxHighlightLength && copyState(cm.doc.mode, context.state);
  1000. var result = highlightLine(cm, line, context);
  1001. if (resetState) { context.state = resetState; }
  1002. line.stateAfter = context.save(!resetState);
  1003. line.styles = result.styles;
  1004. if (result.classes) { line.styleClasses = result.classes; }
  1005. else if (line.styleClasses) { line.styleClasses = null; }
  1006. if (updateFrontier === cm.doc.highlightFrontier)
  1007. { cm.doc.modeFrontier = Math.max(cm.doc.modeFrontier, ++cm.doc.highlightFrontier); }
  1008. }
  1009. return line.styles
  1010. }
  1011. function getContextBefore(cm, n, precise) {
  1012. var doc = cm.doc, display = cm.display;
  1013. if (!doc.mode.startState) { return new Context(doc, true, n) }
  1014. var start = findStartLine(cm, n, precise);
  1015. var saved = start > doc.first && getLine(doc, start - 1).stateAfter;
  1016. var context = saved ? Context.fromSaved(doc, saved, start) : new Context(doc, startState(doc.mode), start);
  1017. doc.iter(start, n, function (line) {
  1018. processLine(cm, line.text, context);
  1019. var pos = context.line;
  1020. line.stateAfter = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo ? context.save() : null;
  1021. context.nextLine();
  1022. });
  1023. if (precise) { doc.modeFrontier = context.line; }
  1024. return context
  1025. }
  1026. // Lightweight form of highlight -- proceed over this line and
  1027. // update state, but don't save a style array. Used for lines that
  1028. // aren't currently visible.
  1029. function processLine(cm, text, context, startAt) {
  1030. var mode = cm.doc.mode;
  1031. var stream = new StringStream(text, cm.options.tabSize, context);
  1032. stream.start = stream.pos = startAt || 0;
  1033. if (text == "") { callBlankLine(mode, context.state); }
  1034. while (!stream.eol()) {
  1035. readToken(mode, stream, context.state);
  1036. stream.start = stream.pos;
  1037. }
  1038. }
  1039. function callBlankLine(mode, state) {
  1040. if (mode.blankLine) { return mode.blankLine(state) }
  1041. if (!mode.innerMode) { return }
  1042. var inner = innerMode(mode, state);
  1043. if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) }
  1044. }
  1045. function readToken(mode, stream, state, inner) {
  1046. for (var i = 0; i < 10; i++) {
  1047. if (inner) { inner[0] = innerMode(mode, state).mode; }
  1048. var style = mode.token(stream, state);
  1049. if (stream.pos > stream.start) { return style }
  1050. }
  1051. throw new Error("Mode " + mode.name + " failed to advance stream.")
  1052. }
  1053. var Token = function(stream, type, state) {
  1054. this.start = stream.start; this.end = stream.pos;
  1055. this.string = stream.current();
  1056. this.type = type || null;
  1057. this.state = state;
  1058. };
  1059. // Utility for getTokenAt and getLineTokens
  1060. function takeToken(cm, pos, precise, asArray) {
  1061. var doc = cm.doc, mode = doc.mode, style;
  1062. pos = clipPos(doc, pos);
  1063. var line = getLine(doc, pos.line), context = getContextBefore(cm, pos.line, precise);
  1064. var stream = new StringStream(line.text, cm.options.tabSize, context), tokens;
  1065. if (asArray) { tokens = []; }
  1066. while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
  1067. stream.start = stream.pos;
  1068. style = readToken(mode, stream, context.state);
  1069. if (asArray) { tokens.push(new Token(stream, style, copyState(doc.mode, context.state))); }
  1070. }
  1071. return asArray ? tokens : new Token(stream, style, context.state)
  1072. }
  1073. function extractLineClasses(type, output) {
  1074. if (type) { for (;;) {
  1075. var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/);
  1076. if (!lineClass) { break }
  1077. type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length);
  1078. var prop = lineClass[1] ? "bgClass" : "textClass";
  1079. if (output[prop] == null)
  1080. { output[prop] = lineClass[2]; }
  1081. else if (!(new RegExp("(?:^|\\s)" + lineClass[2] + "(?:$|\\s)")).test(output[prop]))
  1082. { output[prop] += " " + lineClass[2]; }
  1083. } }
  1084. return type
  1085. }
  1086. // Run the given mode's parser over a line, calling f for each token.
  1087. function runMode(cm, text, mode, context, f, lineClasses, forceToEnd) {
  1088. var flattenSpans = mode.flattenSpans;
  1089. if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans; }
  1090. var curStart = 0, curStyle = null;
  1091. var stream = new StringStream(text, cm.options.tabSize, context), style;
  1092. var inner = cm.options.addModeClass && [null];
  1093. if (text == "") { extractLineClasses(callBlankLine(mode, context.state), lineClasses); }
  1094. while (!stream.eol()) {
  1095. if (stream.pos > cm.options.maxHighlightLength) {
  1096. flattenSpans = false;
  1097. if (forceToEnd) { processLine(cm, text, context, stream.pos); }
  1098. stream.pos = text.length;
  1099. style = null;
  1100. } else {
  1101. style = extractLineClasses(readToken(mode, stream, context.state, inner), lineClasses);
  1102. }
  1103. if (inner) {
  1104. var mName = inner[0].name;
  1105. if (mName) { style = "m-" + (style ? mName + " " + style : mName); }
  1106. }
  1107. if (!flattenSpans || curStyle != style) {
  1108. while (curStart < stream.start) {
  1109. curStart = Math.min(stream.start, curStart + 5000);
  1110. f(curStart, curStyle);
  1111. }
  1112. curStyle = style;
  1113. }
  1114. stream.start = stream.pos;
  1115. }
  1116. while (curStart < stream.pos) {
  1117. // Webkit seems to refuse to render text nodes longer than 57444
  1118. // characters, and returns inaccurate measurements in nodes
  1119. // starting around 5000 chars.
  1120. var pos = Math.min(stream.pos, curStart + 5000);
  1121. f(pos, curStyle);
  1122. curStart = pos;
  1123. }
  1124. }
  1125. // Finds the line to start with when starting a parse. Tries to
  1126. // find a line with a stateAfter, so that it can start with a
  1127. // valid state. If that fails, it returns the line with the
  1128. // smallest indentation, which tends to need the least context to
  1129. // parse correctly.
  1130. function findStartLine(cm, n, precise) {
  1131. var minindent, minline, doc = cm.doc;
  1132. var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100);
  1133. for (var search = n; search > lim; --search) {
  1134. if (search <= doc.first) { return doc.first }
  1135. var line = getLine(doc, search - 1), after = line.stateAfter;
  1136. if (after && (!precise || search + (after instanceof SavedContext ? after.lookAhead : 0) <= doc.modeFrontier))
  1137. { return search }
  1138. var indented = countColumn(line.text, null, cm.options.tabSize);
  1139. if (minline == null || minindent > indented) {
  1140. minline = search - 1;
  1141. minindent = indented;
  1142. }
  1143. }
  1144. return minline
  1145. }
  1146. function retreatFrontier(doc, n) {
  1147. doc.modeFrontier = Math.min(doc.modeFrontier, n);
  1148. if (doc.highlightFrontier < n - 10) { return }
  1149. var start = doc.first;
  1150. for (var line = n - 1; line > start; line--) {
  1151. var saved = getLine(doc, line).stateAfter;
  1152. // change is on 3
  1153. // state on line 1 looked ahead 2 -- so saw 3
  1154. // test 1 + 2 < 3 should cover this
  1155. if (saved && (!(saved instanceof SavedContext) || line + saved.lookAhead < n)) {
  1156. start = line + 1;
  1157. break
  1158. }
  1159. }
  1160. doc.highlightFrontier = Math.min(doc.highlightFrontier, start);
  1161. }
  1162. // Optimize some code when these features are not used.
  1163. var sawReadOnlySpans = false, sawCollapsedSpans = false;
  1164. function seeReadOnlySpans() {
  1165. sawReadOnlySpans = true;
  1166. }
  1167. function seeCollapsedSpans() {
  1168. sawCollapsedSpans = true;
  1169. }
  1170. // TEXTMARKER SPANS
  1171. function MarkedSpan(marker, from, to) {
  1172. this.marker = marker;
  1173. this.from = from; this.to = to;
  1174. }
  1175. // Search an array of spans for a span matching the given marker.
  1176. function getMarkedSpanFor(spans, marker) {
  1177. if (spans) { for (var i = 0; i < spans.length; ++i) {
  1178. var span = spans[i];
  1179. if (span.marker == marker) { return span }
  1180. } }
  1181. }
  1182. // Remove a span from an array, returning undefined if no spans are
  1183. // left (we don't store arrays for lines without spans).
  1184. function removeMarkedSpan(spans, span) {
  1185. var r;
  1186. for (var i = 0; i < spans.length; ++i)
  1187. { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } }
  1188. return r
  1189. }
  1190. // Add a span to a line.
  1191. function addMarkedSpan(line, span) {
  1192. line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
  1193. span.marker.attachLine(line);
  1194. }
  1195. // Used for the algorithm that adjusts markers for a change in the
  1196. // document. These functions cut an array of spans at a given
  1197. // character position, returning an array of remaining chunks (or
  1198. // undefined if nothing remains).
  1199. function markedSpansBefore(old, startCh, isInsert) {
  1200. var nw;
  1201. if (old) { for (var i = 0; i < old.length; ++i) {
  1202. var span = old[i], marker = span.marker;
  1203. var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
  1204. if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
  1205. var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh)
  1206. ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to));
  1207. }
  1208. } }
  1209. return nw
  1210. }
  1211. function markedSpansAfter(old, endCh, isInsert) {
  1212. var nw;
  1213. if (old) { for (var i = 0; i < old.length; ++i) {
  1214. var span = old[i], marker = span.marker;
  1215. var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
  1216. if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
  1217. var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh)
  1218. ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,
  1219. span.to == null ? null : span.to - endCh));
  1220. }
  1221. } }
  1222. return nw
  1223. }
  1224. // Given a change object, compute the new set of marker spans that
  1225. // cover the line in which the change took place. Removes spans
  1226. // entirely within the change, reconnects spans belonging to the
  1227. // same marker that appear on both sides of the change, and cuts off
  1228. // spans partially within the change. Returns an array of span
  1229. // arrays with one element for each line in (after) the change.
  1230. function stretchSpansOverChange(doc, change) {
  1231. if (change.full) { return null }
  1232. var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans;
  1233. var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
  1234. if (!oldFirst && !oldLast) { return null }
  1235. var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0;
  1236. // Get the spans that 'stick out' on both sides
  1237. var first = markedSpansBefore(oldFirst, startCh, isInsert);
  1238. var last = markedSpansAfter(oldLast, endCh, isInsert);
  1239. // Next, merge those two ends
  1240. var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
  1241. if (first) {
  1242. // Fix up .to properties of first
  1243. for (var i = 0; i < first.length; ++i) {
  1244. var span = first[i];
  1245. if (span.to == null) {
  1246. var found = getMarkedSpanFor(last, span.marker);
  1247. if (!found) { span.to = startCh; }
  1248. else if (sameLine) { span.to = found.to == null ? null : found.to + offset; }
  1249. }
  1250. }
  1251. }
  1252. if (last) {
  1253. // Fix up .from in last (or move them into first in case of sameLine)
  1254. for (var i$1 = 0; i$1 < last.length; ++i$1) {
  1255. var span$1 = last[i$1];
  1256. if (span$1.to != null) { span$1.to += offset; }
  1257. if (span$1.from == null) {
  1258. var found$1 = getMarkedSpanFor(first, span$1.marker);
  1259. if (!found$1) {
  1260. span$1.from = offset;
  1261. if (sameLine) { (first || (first = [])).push(span$1); }
  1262. }
  1263. } else {
  1264. span$1.from += offset;
  1265. if (sameLine) { (first || (first = [])).push(span$1); }
  1266. }
  1267. }
  1268. }
  1269. // Make sure we didn't create any zero-length spans
  1270. if (first) { first = clearEmptySpans(first); }
  1271. if (last && last != first) { last = clearEmptySpans(last); }
  1272. var newMarkers = [first];
  1273. if (!sameLine) {
  1274. // Fill gap with whole-line-spans
  1275. var gap = change.text.length - 2, gapMarkers;
  1276. if (gap > 0 && first)
  1277. { for (var i$2 = 0; i$2 < first.length; ++i$2)
  1278. { if (first[i$2].to == null)
  1279. { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)); } } }
  1280. for (var i$3 = 0; i$3 < gap; ++i$3)
  1281. { newMarkers.push(gapMarkers); }
  1282. newMarkers.push(last);
  1283. }
  1284. return newMarkers
  1285. }
  1286. // Remove spans that are empty and don't have a clearWhenEmpty
  1287. // option of false.
  1288. function clearEmptySpans(spans) {
  1289. for (var i = 0; i < spans.length; ++i) {
  1290. var span = spans[i];
  1291. if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
  1292. { spans.splice(i--, 1); }
  1293. }
  1294. if (!spans.length) { return null }
  1295. return spans
  1296. }
  1297. // Used to 'clip' out readOnly ranges when making a change.
  1298. function removeReadOnlyRanges(doc, from, to) {
  1299. var markers = null;
  1300. doc.iter(from.line, to.line + 1, function (line) {
  1301. if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {
  1302. var mark = line.markedSpans[i].marker;
  1303. if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
  1304. { (markers || (markers = [])).push(mark); }
  1305. } }
  1306. });
  1307. if (!markers) { return null }
  1308. var parts = [{from: from, to: to}];
  1309. for (var i = 0; i < markers.length; ++i) {
  1310. var mk = markers[i], m = mk.find(0);
  1311. for (var j = 0; j < parts.length; ++j) {
  1312. var p = parts[j];
  1313. if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue }
  1314. var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to);
  1315. if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)
  1316. { newParts.push({from: p.from, to: m.from}); }
  1317. if (dto > 0 || !mk.inclusiveRight && !dto)
  1318. { newParts.push({from: m.to, to: p.to}); }
  1319. parts.splice.apply(parts, newParts);
  1320. j += newParts.length - 3;
  1321. }
  1322. }
  1323. return parts
  1324. }
  1325. // Connect or disconnect spans from a line.
  1326. function detachMarkedSpans(line) {
  1327. var spans = line.markedSpans;
  1328. if (!spans) { return }
  1329. for (var i = 0; i < spans.length; ++i)
  1330. { spans[i].marker.detachLine(line); }
  1331. line.markedSpans = null;
  1332. }
  1333. function attachMarkedSpans(line, spans) {
  1334. if (!spans) { return }
  1335. for (var i = 0; i < spans.length; ++i)
  1336. { spans[i].marker.attachLine(line); }
  1337. line.markedSpans = spans;
  1338. }
  1339. // Helpers used when computing which overlapping collapsed span
  1340. // counts as the larger one.
  1341. function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 }
  1342. function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 }
  1343. // Returns a number indicating which of two overlapping collapsed
  1344. // spans is larger (and thus includes the other). Falls back to
  1345. // comparing ids when the spans cover exactly the same range.
  1346. function compareCollapsedMarkers(a, b) {
  1347. var lenDiff = a.lines.length - b.lines.length;
  1348. if (lenDiff != 0) { return lenDiff }
  1349. var aPos = a.find(), bPos = b.find();
  1350. var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b);
  1351. if (fromCmp) { return -fromCmp }
  1352. var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b);
  1353. if (toCmp) { return toCmp }
  1354. return b.id - a.id
  1355. }
  1356. // Find out whether a line ends or starts in a collapsed span. If
  1357. // so, return the marker for that span.
  1358. function collapsedSpanAtSide(line, start) {
  1359. var sps = sawCollapsedSpans && line.markedSpans, found;
  1360. if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {
  1361. sp = sps[i];
  1362. if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
  1363. (!found || compareCollapsedMarkers(found, sp.marker) < 0))
  1364. { found = sp.marker; }
  1365. } }
  1366. return found
  1367. }
  1368. function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) }
  1369. function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) }
  1370. function collapsedSpanAround(line, ch) {
  1371. var sps = sawCollapsedSpans && line.markedSpans, found;
  1372. if (sps) { for (var i = 0; i < sps.length; ++i) {
  1373. var sp = sps[i];
  1374. if (sp.marker.collapsed && (sp.from == null || sp.from < ch) && (sp.to == null || sp.to > ch) &&
  1375. (!found || compareCollapsedMarkers(found, sp.marker) < 0)) { found = sp.marker; }
  1376. } }
  1377. return found
  1378. }
  1379. // Test whether there exists a collapsed span that partially
  1380. // overlaps (covers the start or end, but not both) of a new span.
  1381. // Such overlap is not allowed.
  1382. function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
  1383. var line = getLine(doc, lineNo);
  1384. var sps = sawCollapsedSpans && line.markedSpans;
  1385. if (sps) { for (var i = 0; i < sps.length; ++i) {
  1386. var sp = sps[i];
  1387. if (!sp.marker.collapsed) { continue }
  1388. var found = sp.marker.find(0);
  1389. var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker);
  1390. var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker);
  1391. if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue }
  1392. if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) ||
  1393. fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0))
  1394. { return true }
  1395. } }
  1396. }
  1397. // A visual line is a line as drawn on the screen. Folding, for
  1398. // example, can cause multiple logical lines to appear on the same
  1399. // visual line. This finds the start of the visual line that the
  1400. // given line is part of (usually that is the line itself).
  1401. function visualLine(line) {
  1402. var merged;
  1403. while (merged = collapsedSpanAtStart(line))
  1404. { line = merged.find(-1, true).line; }
  1405. return line
  1406. }
  1407. function visualLineEnd(line) {
  1408. var merged;
  1409. while (merged = collapsedSpanAtEnd(line))
  1410. { line = merged.find(1, true).line; }
  1411. return line
  1412. }
  1413. // Returns an array of logical lines that continue the visual line
  1414. // started by the argument, or undefined if there are no such lines.
  1415. function visualLineContinued(line) {
  1416. var merged, lines;
  1417. while (merged = collapsedSpanAtEnd(line)) {
  1418. line = merged.find(1, true).line
  1419. ;(lines || (lines = [])).push(line);
  1420. }
  1421. return lines
  1422. }
  1423. // Get the line number of the start of the visual line that the
  1424. // given line number is part of.
  1425. function visualLineNo(doc, lineN) {
  1426. var line = getLine(doc, lineN), vis = visualLine(line);
  1427. if (line == vis) { return lineN }
  1428. return lineNo(vis)
  1429. }
  1430. // Get the line number of the start of the next visual line after
  1431. // the given line.
  1432. function visualLineEndNo(doc, lineN) {
  1433. if (lineN > doc.lastLine()) { return lineN }
  1434. var line = getLine(doc, lineN), merged;
  1435. if (!lineIsHidden(doc, line)) { return lineN }
  1436. while (merged = collapsedSpanAtEnd(line))
  1437. { line = merged.find(1, true).line; }
  1438. return lineNo(line) + 1
  1439. }
  1440. // Compute whether a line is hidden. Lines count as hidden when they
  1441. // are part of a visual line that starts with another line, or when
  1442. // they are entirely covered by collapsed, non-widget span.
  1443. function lineIsHidden(doc, line) {
  1444. var sps = sawCollapsedSpans && line.markedSpans;
  1445. if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {
  1446. sp = sps[i];
  1447. if (!sp.marker.collapsed) { continue }
  1448. if (sp.from == null) { return true }
  1449. if (sp.marker.widgetNode) { continue }
  1450. if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
  1451. { return true }
  1452. } }
  1453. }
  1454. function lineIsHiddenInner(doc, line, span) {
  1455. if (span.to == null) {
  1456. var end = span.marker.find(1, true);
  1457. return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker))
  1458. }
  1459. if (span.marker.inclusiveRight && span.to == line.text.length)
  1460. { return true }
  1461. for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) {
  1462. sp = line.markedSpans[i];
  1463. if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&
  1464. (sp.to == null || sp.to != span.from) &&
  1465. (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
  1466. lineIsHiddenInner(doc, line, sp)) { return true }
  1467. }
  1468. }
  1469. // Find the height above the given line.
  1470. function heightAtLine(lineObj) {
  1471. lineObj = visualLine(lineObj);
  1472. var h = 0, chunk = lineObj.parent;
  1473. for (var i = 0; i < chunk.lines.length; ++i) {
  1474. var line = chunk.lines[i];
  1475. if (line == lineObj) { break }
  1476. else { h += line.height; }
  1477. }
  1478. for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
  1479. for (var i$1 = 0; i$1 < p.children.length; ++i$1) {
  1480. var cur = p.children[i$1];
  1481. if (cur == chunk) { break }
  1482. else { h += cur.height; }
  1483. }
  1484. }
  1485. return h
  1486. }
  1487. // Compute the character length of a line, taking into account
  1488. // collapsed ranges (see markText) that might hide parts, and join
  1489. // other lines onto it.
  1490. function lineLength(line) {
  1491. if (line.height == 0) { return 0 }
  1492. var len = line.text.length, merged, cur = line;
  1493. while (merged = collapsedSpanAtStart(cur)) {
  1494. var found = merged.find(0, true);
  1495. cur = found.from.line;
  1496. len += found.from.ch - found.to.ch;
  1497. }
  1498. cur = line;
  1499. while (merged = collapsedSpanAtEnd(cur)) {
  1500. var found$1 = merged.find(0, true);
  1501. len -= cur.text.length - found$1.from.ch;
  1502. cur = found$1.to.line;
  1503. len += cur.text.length - found$1.to.ch;
  1504. }
  1505. return len
  1506. }
  1507. // Find the longest line in the document.
  1508. function findMaxLine(cm) {
  1509. var d = cm.display, doc = cm.doc;
  1510. d.maxLine = getLine(doc, doc.first);
  1511. d.maxLineLength = lineLength(d.maxLine);
  1512. d.maxLineChanged = true;
  1513. doc.iter(function (line) {
  1514. var len = lineLength(line);
  1515. if (len > d.maxLineLength) {
  1516. d.maxLineLength = len;
  1517. d.maxLine = line;
  1518. }
  1519. });
  1520. }
  1521. // LINE DATA STRUCTURE
  1522. // Line objects. These hold state related to a line, including
  1523. // highlighting info (the styles array).
  1524. var Line = function(text, markedSpans, estimateHeight) {
  1525. this.text = text;
  1526. attachMarkedSpans(this, markedSpans);
  1527. this.height = estimateHeight ? estimateHeight(this) : 1;
  1528. };
  1529. Line.prototype.lineNo = function () { return lineNo(this) };
  1530. eventMixin(Line);
  1531. // Change the content (text, markers) of a line. Automatically
  1532. // invalidates cached information and tries to re-estimate the
  1533. // line's height.
  1534. function updateLine(line, text, markedSpans, estimateHeight) {
  1535. line.text = text;
  1536. if (line.stateAfter) { line.stateAfter = null; }
  1537. if (line.styles) { line.styles = null; }
  1538. if (line.order != null) { line.order = null; }
  1539. detachMarkedSpans(line);
  1540. attachMarkedSpans(line, markedSpans);
  1541. var estHeight = estimateHeight ? estimateHeight(line) : 1;
  1542. if (estHeight != line.height) { updateLineHeight(line, estHeight); }
  1543. }
  1544. // Detach a line from the document tree and its markers.
  1545. function cleanUpLine(line) {
  1546. line.parent = null;
  1547. detachMarkedSpans(line);
  1548. }
  1549. // Convert a style as returned by a mode (either null, or a string
  1550. // containing one or more styles) to a CSS style. This is cached,
  1551. // and also looks for line-wide styles.
  1552. var styleToClassCache = {}, styleToClassCacheWithMode = {};
  1553. function interpretTokenStyle(style, options) {
  1554. if (!style || /^\s*$/.test(style)) { return null }
  1555. var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache;
  1556. return cache[style] ||
  1557. (cache[style] = style.replace(/\S+/g, "cm-$&"))
  1558. }
  1559. // Render the DOM representation of the text of a line. Also builds
  1560. // up a 'line map', which points at the DOM nodes that represent
  1561. // specific stretches of text, and is used by the measuring code.
  1562. // The returned object contains the DOM node, this map, and
  1563. // information about line-wide styles that were set by the mode.
  1564. function buildLineContent(cm, lineView) {
  1565. // The padding-right forces the element to have a 'border', which
  1566. // is needed on Webkit to be able to get line-level bounding
  1567. // rectangles for it (in measureChar).
  1568. var content = eltP("span", null, null, webkit ? "padding-right: .1px" : null);
  1569. var builder = {pre: eltP("pre", [content], "CodeMirror-line"), content: content,
  1570. col: 0, pos: 0, cm: cm,
  1571. trailingSpace: false,
  1572. splitSpaces: cm.getOption("lineWrapping")};
  1573. lineView.measure = {};
  1574. // Iterate over the logical lines that make up this visual line.
  1575. for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {
  1576. var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0);
  1577. builder.pos = 0;
  1578. builder.addToken = buildToken;
  1579. // Optionally wire in some hacks into the token-rendering
  1580. // algorithm, to deal with browser quirks.
  1581. if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line, cm.doc.direction)))
  1582. { builder.addToken = buildTokenBadBidi(builder.addToken, order); }
  1583. builder.map = [];
  1584. var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line);
  1585. insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate));
  1586. if (line.styleClasses) {
  1587. if (line.styleClasses.bgClass)
  1588. { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); }
  1589. if (line.styleClasses.textClass)
  1590. { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); }
  1591. }
  1592. // Ensure at least a single node is present, for measuring.
  1593. if (builder.map.length == 0)
  1594. { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); }
  1595. // Store the map and a cache object for the current logical line
  1596. if (i == 0) {
  1597. lineView.measure.map = builder.map;
  1598. lineView.measure.cache = {};
  1599. } else {
  1600. (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map)
  1601. ;(lineView.measure.caches || (lineView.measure.caches = [])).push({});
  1602. }
  1603. }
  1604. // See issue #2901
  1605. if (webkit) {
  1606. var last = builder.content.lastChild;
  1607. if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab")))
  1608. { builder.content.className = "cm-tab-wrap-hack"; }
  1609. }
  1610. signal(cm, "renderLine", cm, lineView.line, builder.pre);
  1611. if (builder.pre.className)
  1612. { builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); }
  1613. return builder
  1614. }
  1615. function defaultSpecialCharPlaceholder(ch) {
  1616. var token = elt("span", "\u2022", "cm-invalidchar");
  1617. token.title = "\\u" + ch.charCodeAt(0).toString(16);
  1618. token.setAttribute("aria-label", token.title);
  1619. return token
  1620. }
  1621. // Build up the DOM representation for a single token, and add it to
  1622. // the line map. Takes care to render special characters separately.
  1623. function buildToken(builder, text, style, startStyle, endStyle, css, attributes) {
  1624. if (!text) { return }
  1625. var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text;
  1626. var special = builder.cm.state.specialChars, mustWrap = false;
  1627. var content;
  1628. if (!special.test(text)) {
  1629. builder.col += text.length;
  1630. content = document.createTextNode(displayText);
  1631. builder.map.push(builder.pos, builder.pos + text.length, content);
  1632. if (ie && ie_version < 9) { mustWrap = true; }
  1633. builder.pos += text.length;
  1634. } else {
  1635. content = document.createDocumentFragment();
  1636. var pos = 0;
  1637. while (true) {
  1638. special.lastIndex = pos;
  1639. var m = special.exec(text);
  1640. var skipped = m ? m.index - pos : text.length - pos;
  1641. if (skipped) {
  1642. var txt = document.createTextNode(displayText.slice(pos, pos + skipped));
  1643. if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])); }
  1644. else { content.appendChild(txt); }
  1645. builder.map.push(builder.pos, builder.pos + skipped, txt);
  1646. builder.col += skipped;
  1647. builder.pos += skipped;
  1648. }
  1649. if (!m) { break }
  1650. pos += skipped + 1;
  1651. var txt$1 = (void 0);
  1652. if (m[0] == "\t") {
  1653. var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize;
  1654. txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"));
  1655. txt$1.setAttribute("role", "presentation");
  1656. txt$1.setAttribute("cm-text", "\t");
  1657. builder.col += tabWidth;
  1658. } else if (m[0] == "\r" || m[0] == "\n") {
  1659. txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar"));
  1660. txt$1.setAttribute("cm-text", m[0]);
  1661. builder.col += 1;
  1662. } else {
  1663. txt$1 = builder.cm.options.specialCharPlaceholder(m[0]);
  1664. txt$1.setAttribute("cm-text", m[0]);
  1665. if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])); }
  1666. else { content.appendChild(txt$1); }
  1667. builder.col += 1;
  1668. }
  1669. builder.map.push(builder.pos, builder.pos + 1, txt$1);
  1670. builder.pos++;
  1671. }
  1672. }
  1673. builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32;
  1674. if (style || startStyle || endStyle || mustWrap || css) {
  1675. var fullStyle = style || "";
  1676. if (startStyle) { fullStyle += startStyle; }
  1677. if (endStyle) { fullStyle += endStyle; }
  1678. var token = elt("span", [content], fullStyle, css);
  1679. if (attributes) {
  1680. for (var attr in attributes) { if (attributes.hasOwnProperty(attr) && attr != "style" && attr != "class")
  1681. { token.setAttribute(attr, attributes[attr]); } }
  1682. }
  1683. return builder.content.appendChild(token)
  1684. }
  1685. builder.content.appendChild(content);
  1686. }
  1687. // Change some spaces to NBSP to prevent the browser from collapsing
  1688. // trailing spaces at the end of a line when rendering text (issue #1362).
  1689. function splitSpaces(text, trailingBefore) {
  1690. if (text.length > 1 && !/ /.test(text)) { return text }
  1691. var spaceBefore = trailingBefore, result = "";
  1692. for (var i = 0; i < text.length; i++) {
  1693. var ch = text.charAt(i);
  1694. if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32))
  1695. { ch = "\u00a0"; }
  1696. result += ch;
  1697. spaceBefore = ch == " ";
  1698. }
  1699. return result
  1700. }
  1701. // Work around nonsense dimensions being reported for stretches of
  1702. // right-to-left text.
  1703. function buildTokenBadBidi(inner, order) {
  1704. return function (builder, text, style, startStyle, endStyle, css, attributes) {
  1705. style = style ? style + " cm-force-border" : "cm-force-border";
  1706. var start = builder.pos, end = start + text.length;
  1707. for (;;) {
  1708. // Find the part that overlaps with the start of this text
  1709. var part = (void 0);
  1710. for (var i = 0; i < order.length; i++) {
  1711. part = order[i];
  1712. if (part.to > start && part.from <= start) { break }
  1713. }
  1714. if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, css, attributes) }
  1715. inner(builder, text.slice(0, part.to - start), style, startStyle, null, css, attributes);
  1716. startStyle = null;
  1717. text = text.slice(part.to - start);
  1718. start = part.to;
  1719. }
  1720. }
  1721. }
  1722. function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
  1723. var widget = !ignoreWidget && marker.widgetNode;
  1724. if (widget) { builder.map.push(builder.pos, builder.pos + size, widget); }
  1725. if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {
  1726. if (!widget)
  1727. { widget = builder.content.appendChild(document.createElement("span")); }
  1728. widget.setAttribute("cm-marker", marker.id);
  1729. }
  1730. if (widget) {
  1731. builder.cm.display.input.setUneditable(widget);
  1732. builder.content.appendChild(widget);
  1733. }
  1734. builder.pos += size;
  1735. builder.trailingSpace = false;
  1736. }
  1737. // Outputs a number of spans to make up a line, taking highlighting
  1738. // and marked text into account.
  1739. function insertLineContent(line, builder, styles) {
  1740. var spans = line.markedSpans, allText = line.text, at = 0;
  1741. if (!spans) {
  1742. for (var i$1 = 1; i$1 < styles.length; i$1+=2)
  1743. { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)); }
  1744. return
  1745. }
  1746. var len = allText.length, pos = 0, i = 1, text = "", style, css;
  1747. var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed, attributes;
  1748. for (;;) {
  1749. if (nextChange == pos) { // Update current marker set
  1750. spanStyle = spanEndStyle = spanStartStyle = css = "";
  1751. attributes = null;
  1752. collapsed = null; nextChange = Infinity;
  1753. var foundBookmarks = [], endStyles = (void 0);
  1754. for (var j = 0; j < spans.length; ++j) {
  1755. var sp = spans[j], m = sp.marker;
  1756. if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
  1757. foundBookmarks.push(m);
  1758. } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
  1759. if (sp.to != null && sp.to != pos && nextChange > sp.to) {
  1760. nextChange = sp.to;
  1761. spanEndStyle = "";
  1762. }
  1763. if (m.className) { spanStyle += " " + m.className; }
  1764. if (m.css) { css = (css ? css + ";" : "") + m.css; }
  1765. if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle; }
  1766. if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to); }
  1767. // support for the old title property
  1768. // https://github.com/codemirror/CodeMirror/pull/5673
  1769. if (m.title) { (attributes || (attributes = {})).title = m.title; }
  1770. if (m.attributes) {
  1771. for (var attr in m.attributes)
  1772. { (attributes || (attributes = {}))[attr] = m.attributes[attr]; }
  1773. }
  1774. if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
  1775. { collapsed = sp; }
  1776. } else if (sp.from > pos && nextChange > sp.from) {
  1777. nextChange = sp.from;
  1778. }
  1779. }
  1780. if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2)
  1781. { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1]; } } }
  1782. if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2)
  1783. { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]); } }
  1784. if (collapsed && (collapsed.from || 0) == pos) {
  1785. buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
  1786. collapsed.marker, collapsed.from == null);
  1787. if (collapsed.to == null) { return }
  1788. if (collapsed.to == pos) { collapsed = false; }
  1789. }
  1790. }
  1791. if (pos >= len) { break }
  1792. var upto = Math.min(len, nextChange);
  1793. while (true) {
  1794. if (text) {
  1795. var end = pos + text.length;
  1796. if (!collapsed) {
  1797. var tokenText = end > upto ? text.slice(0, upto - pos) : text;
  1798. builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
  1799. spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", css, attributes);
  1800. }
  1801. if (end >= upto) {text = text.slice(upto - pos); pos = upto; break}
  1802. pos = end;
  1803. spanStartStyle = "";
  1804. }
  1805. text = allText.slice(at, at = styles[i++]);
  1806. style = interpretTokenStyle(styles[i++], builder.cm.options);
  1807. }
  1808. }
  1809. }
  1810. // These objects are used to represent the visible (currently drawn)
  1811. // part of the document. A LineView may correspond to multiple
  1812. // logical lines, if those are connected by collapsed ranges.
  1813. function LineView(doc, line, lineN) {
  1814. // The starting line
  1815. this.line = line;
  1816. // Continuing lines, if any
  1817. this.rest = visualLineContinued(line);
  1818. // Number of logical lines in this visual line
  1819. this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1;
  1820. this.node = this.text = null;
  1821. this.hidden = lineIsHidden(doc, line);
  1822. }
  1823. // Create a range of LineView objects for the given lines.
  1824. function buildViewArray(cm, from, to) {
  1825. var array = [], nextPos;
  1826. for (var pos = from; pos < to; pos = nextPos) {
  1827. var view = new LineView(cm.doc, getLine(cm.doc, pos), pos);
  1828. nextPos = pos + view.size;
  1829. array.push(view);
  1830. }
  1831. return array
  1832. }
  1833. var operationGroup = null;
  1834. function pushOperation(op) {
  1835. if (operationGroup) {
  1836. operationGroup.ops.push(op);
  1837. } else {
  1838. op.ownsGroup = operationGroup = {
  1839. ops: [op],
  1840. delayedCallbacks: []
  1841. };
  1842. }
  1843. }
  1844. function fireCallbacksForOps(group) {
  1845. // Calls delayed callbacks and cursorActivity handlers until no
  1846. // new ones appear
  1847. var callbacks = group.delayedCallbacks, i = 0;
  1848. do {
  1849. for (; i < callbacks.length; i++)
  1850. { callbacks[i].call(null); }
  1851. for (var j = 0; j < group.ops.length; j++) {
  1852. var op = group.ops[j];
  1853. if (op.cursorActivityHandlers)
  1854. { while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
  1855. { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); } }
  1856. }
  1857. } while (i < callbacks.length)
  1858. }
  1859. function finishOperation(op, endCb) {
  1860. var group = op.ownsGroup;
  1861. if (!group) { return }
  1862. try { fireCallbacksForOps(group); }
  1863. finally {
  1864. operationGroup = null;
  1865. endCb(group);
  1866. }
  1867. }
  1868. var orphanDelayedCallbacks = null;
  1869. // Often, we want to signal events at a point where we are in the
  1870. // middle of some work, but don't want the handler to start calling
  1871. // other methods on the editor, which might be in an inconsistent
  1872. // state or simply not expect any other events to happen.
  1873. // signalLater looks whether there are any handlers, and schedules
  1874. // them to be executed when the last operation ends, or, if no
  1875. // operation is active, when a timeout fires.
  1876. function signalLater(emitter, type /*, values...*/) {
  1877. var arr = getHandlers(emitter, type);
  1878. if (!arr.length) { return }
  1879. var args = Array.prototype.slice.call(arguments, 2), list;
  1880. if (operationGroup) {
  1881. list = operationGroup.delayedCallbacks;
  1882. } else if (orphanDelayedCallbacks) {
  1883. list = orphanDelayedCallbacks;
  1884. } else {
  1885. list = orphanDelayedCallbacks = [];
  1886. setTimeout(fireOrphanDelayed, 0);
  1887. }
  1888. var loop = function ( i ) {
  1889. list.push(function () { return arr[i].apply(null, args); });
  1890. };
  1891. for (var i = 0; i < arr.length; ++i)
  1892. loop( i );
  1893. }
  1894. function fireOrphanDelayed() {
  1895. var delayed = orphanDelayedCallbacks;
  1896. orphanDelayedCallbacks = null;
  1897. for (var i = 0; i < delayed.length; ++i) { delayed[i](); }
  1898. }
  1899. // When an aspect of a line changes, a string is added to
  1900. // lineView.changes. This updates the relevant part of the line's
  1901. // DOM structure.
  1902. function updateLineForChanges(cm, lineView, lineN, dims) {
  1903. for (var j = 0; j < lineView.changes.length; j++) {
  1904. var type = lineView.changes[j];
  1905. if (type == "text") { updateLineText(cm, lineView); }
  1906. else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims); }
  1907. else if (type == "class") { updateLineClasses(cm, lineView); }
  1908. else if (type == "widget") { updateLineWidgets(cm, lineView, dims); }
  1909. }
  1910. lineView.changes = null;
  1911. }
  1912. // Lines with gutter elements, widgets or a background class need to
  1913. // be wrapped, and have the extra elements added to the wrapper div
  1914. function ensureLineWrapped(lineView) {
  1915. if (lineView.node == lineView.text) {
  1916. lineView.node = elt("div", null, null, "position: relative");
  1917. if (lineView.text.parentNode)
  1918. { lineView.text.parentNode.replaceChild(lineView.node, lineView.text); }
  1919. lineView.node.appendChild(lineView.text);
  1920. if (ie && ie_version < 8) { lineView.node.style.zIndex = 2; }
  1921. }
  1922. return lineView.node
  1923. }
  1924. function updateLineBackground(cm, lineView) {
  1925. var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass;
  1926. if (cls) { cls += " CodeMirror-linebackground"; }
  1927. if (lineView.background) {
  1928. if (cls) { lineView.background.className = cls; }
  1929. else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; }
  1930. } else if (cls) {
  1931. var wrap = ensureLineWrapped(lineView);
  1932. lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild);
  1933. cm.display.input.setUneditable(lineView.background);
  1934. }
  1935. }
  1936. // Wrapper around buildLineContent which will reuse the structure
  1937. // in display.externalMeasured when possible.
  1938. function getLineContent(cm, lineView) {
  1939. var ext = cm.display.externalMeasured;
  1940. if (ext && ext.line == lineView.line) {
  1941. cm.display.externalMeasured = null;
  1942. lineView.measure = ext.measure;
  1943. return ext.built
  1944. }
  1945. return buildLineContent(cm, lineView)
  1946. }
  1947. // Redraw the line's text. Interacts with the background and text
  1948. // classes because the mode may output tokens that influence these
  1949. // classes.
  1950. function updateLineText(cm, lineView) {
  1951. var cls = lineView.text.className;
  1952. var built = getLineContent(cm, lineView);
  1953. if (lineView.text == lineView.node) { lineView.node = built.pre; }
  1954. lineView.text.parentNode.replaceChild(built.pre, lineView.text);
  1955. lineView.text = built.pre;
  1956. if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
  1957. lineView.bgClass = built.bgClass;
  1958. lineView.textClass = built.textClass;
  1959. updateLineClasses(cm, lineView);
  1960. } else if (cls) {
  1961. lineView.text.className = cls;
  1962. }
  1963. }
  1964. function updateLineClasses(cm, lineView) {
  1965. updateLineBackground(cm, lineView);
  1966. if (lineView.line.wrapClass)
  1967. { ensureLineWrapped(lineView).className = lineView.line.wrapClass; }
  1968. else if (lineView.node != lineView.text)
  1969. { lineView.node.className = ""; }
  1970. var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass;
  1971. lineView.text.className = textClass || "";
  1972. }
  1973. function updateLineGutter(cm, lineView, lineN, dims) {
  1974. if (lineView.gutter) {
  1975. lineView.node.removeChild(lineView.gutter);
  1976. lineView.gutter = null;
  1977. }
  1978. if (lineView.gutterBackground) {
  1979. lineView.node.removeChild(lineView.gutterBackground);
  1980. lineView.gutterBackground = null;
  1981. }
  1982. if (lineView.line.gutterClass) {
  1983. var wrap = ensureLineWrapped(lineView);
  1984. lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass,
  1985. ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px"));
  1986. cm.display.input.setUneditable(lineView.gutterBackground);
  1987. wrap.insertBefore(lineView.gutterBackground, lineView.text);
  1988. }
  1989. var markers = lineView.line.gutterMarkers;
  1990. if (cm.options.lineNumbers || markers) {
  1991. var wrap$1 = ensureLineWrapped(lineView);
  1992. var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"));
  1993. cm.display.input.setUneditable(gutterWrap);
  1994. wrap$1.insertBefore(gutterWrap, lineView.text);
  1995. if (lineView.line.gutterClass)
  1996. { gutterWrap.className += " " + lineView.line.gutterClass; }
  1997. if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
  1998. { lineView.lineNumber = gutterWrap.appendChild(
  1999. elt("div", lineNumberFor(cm.options, lineN),
  2000. "CodeMirror-linenumber CodeMirror-gutter-elt",
  2001. ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))); }
  2002. if (markers) { for (var k = 0; k < cm.display.gutterSpecs.length; ++k) {
  2003. var id = cm.display.gutterSpecs[k].className, found = markers.hasOwnProperty(id) && markers[id];
  2004. if (found)
  2005. { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt",
  2006. ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))); }
  2007. } }
  2008. }
  2009. }
  2010. function updateLineWidgets(cm, lineView, dims) {
  2011. if (lineView.alignable) { lineView.alignable = null; }
  2012. var isWidget = classTest("CodeMirror-linewidget");
  2013. for (var node = lineView.node.firstChild, next = (void 0); node; node = next) {
  2014. next = node.nextSibling;
  2015. if (isWidget.test(node.className)) { lineView.node.removeChild(node); }
  2016. }
  2017. insertLineWidgets(cm, lineView, dims);
  2018. }
  2019. // Build a line's DOM representation from scratch
  2020. function buildLineElement(cm, lineView, lineN, dims) {
  2021. var built = getLineContent(cm, lineView);
  2022. lineView.text = lineView.node = built.pre;
  2023. if (built.bgClass) { lineView.bgClass = built.bgClass; }
  2024. if (built.textClass) { lineView.textClass = built.textClass; }
  2025. updateLineClasses(cm, lineView);
  2026. updateLineGutter(cm, lineView, lineN, dims);
  2027. insertLineWidgets(cm, lineView, dims);
  2028. return lineView.node
  2029. }
  2030. // A lineView may contain multiple logical lines (when merged by
  2031. // collapsed spans). The widgets for all of them need to be drawn.
  2032. function insertLineWidgets(cm, lineView, dims) {
  2033. insertLineWidgetsFor(cm, lineView.line, lineView, dims, true);
  2034. if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)
  2035. { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); } }
  2036. }
  2037. function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {
  2038. if (!line.widgets) { return }
  2039. var wrap = ensureLineWrapped(lineView);
  2040. for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
  2041. var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget" + (widget.className ? " " + widget.className : ""));
  2042. if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true"); }
  2043. positionLineWidget(widget, node, lineView, dims);
  2044. cm.display.input.setUneditable(node);
  2045. if (allowAbove && widget.above)
  2046. { wrap.insertBefore(node, lineView.gutter || lineView.text); }
  2047. else
  2048. { wrap.appendChild(node); }
  2049. signalLater(widget, "redraw");
  2050. }
  2051. }
  2052. function positionLineWidget(widget, node, lineView, dims) {
  2053. if (widget.noHScroll) {
  2054. (lineView.alignable || (lineView.alignable = [])).push(node);
  2055. var width = dims.wrapperWidth;
  2056. node.style.left = dims.fixedPos + "px";
  2057. if (!widget.coverGutter) {
  2058. width -= dims.gutterTotalWidth;
  2059. node.style.paddingLeft = dims.gutterTotalWidth + "px";
  2060. }
  2061. node.style.width = width + "px";
  2062. }
  2063. if (widget.coverGutter) {
  2064. node.style.zIndex = 5;
  2065. node.style.position = "relative";
  2066. if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px"; }
  2067. }
  2068. }
  2069. function widgetHeight(widget) {
  2070. if (widget.height != null) { return widget.height }
  2071. var cm = widget.doc.cm;
  2072. if (!cm) { return 0 }
  2073. if (!contains(document.body, widget.node)) {
  2074. var parentStyle = "position: relative;";
  2075. if (widget.coverGutter)
  2076. { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; }
  2077. if (widget.noHScroll)
  2078. { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; }
  2079. removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle));
  2080. }
  2081. return widget.height = widget.node.parentNode.offsetHeight
  2082. }
  2083. // Return true when the given mouse event happened in a widget
  2084. function eventInWidget(display, e) {
  2085. for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
  2086. if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") ||
  2087. (n.parentNode == display.sizer && n != display.mover))
  2088. { return true }
  2089. }
  2090. }
  2091. // POSITION MEASUREMENT
  2092. function paddingTop(display) {return display.lineSpace.offsetTop}
  2093. function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight}
  2094. function paddingH(display) {
  2095. if (display.cachedPaddingH) { return display.cachedPaddingH }
  2096. var e = removeChildrenAndAdd(display.measure, elt("pre", "x", "CodeMirror-line-like"));
  2097. var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle;
  2098. var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)};
  2099. if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data; }
  2100. return data
  2101. }
  2102. function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth }
  2103. function displayWidth(cm) {
  2104. return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth
  2105. }
  2106. function displayHeight(cm) {
  2107. return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight
  2108. }
  2109. // Ensure the lineView.wrapping.heights array is populated. This is
  2110. // an array of bottom offsets for the lines that make up a drawn
  2111. // line. When lineWrapping is on, there might be more than one
  2112. // height.
  2113. function ensureLineHeights(cm, lineView, rect) {
  2114. var wrapping = cm.options.lineWrapping;
  2115. var curWidth = wrapping && displayWidth(cm);
  2116. if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
  2117. var heights = lineView.measure.heights = [];
  2118. if (wrapping) {
  2119. lineView.measure.width = curWidth;
  2120. var rects = lineView.text.firstChild.getClientRects();
  2121. for (var i = 0; i < rects.length - 1; i++) {
  2122. var cur = rects[i], next = rects[i + 1];
  2123. if (Math.abs(cur.bottom - next.bottom) > 2)
  2124. { heights.push((cur.bottom + next.top) / 2 - rect.top); }
  2125. }
  2126. }
  2127. heights.push(rect.bottom - rect.top);
  2128. }
  2129. }
  2130. // Find a line map (mapping character offsets to text nodes) and a
  2131. // measurement cache for the given line number. (A line view might
  2132. // contain multiple lines when collapsed ranges are present.)
  2133. function mapFromLineView(lineView, line, lineN) {
  2134. if (lineView.line == line)
  2135. { return {map: lineView.measure.map, cache: lineView.measure.cache} }
  2136. for (var i = 0; i < lineView.rest.length; i++)
  2137. { if (lineView.rest[i] == line)
  2138. { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } }
  2139. for (var i$1 = 0; i$1 < lineView.rest.length; i$1++)
  2140. { if (lineNo(lineView.rest[i$1]) > lineN)
  2141. { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } }
  2142. }
  2143. // Render a line into the hidden node display.externalMeasured. Used
  2144. // when measurement is needed for a line that's not in the viewport.
  2145. function updateExternalMeasurement(cm, line) {
  2146. line = visualLine(line);
  2147. var lineN = lineNo(line);
  2148. var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN);
  2149. view.lineN = lineN;
  2150. var built = view.built = buildLineContent(cm, view);
  2151. view.text = built.pre;
  2152. removeChildrenAndAdd(cm.display.lineMeasure, built.pre);
  2153. return view
  2154. }
  2155. // Get a {top, bottom, left, right} box (in line-local coordinates)
  2156. // for a given character.
  2157. function measureChar(cm, line, ch, bias) {
  2158. return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias)
  2159. }
  2160. // Find a line view that corresponds to the given line number.
  2161. function findViewForLine(cm, lineN) {
  2162. if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
  2163. { return cm.display.view[findViewIndex(cm, lineN)] }
  2164. var ext = cm.display.externalMeasured;
  2165. if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
  2166. { return ext }
  2167. }
  2168. // Measurement can be split in two steps, the set-up work that
  2169. // applies to the whole line, and the measurement of the actual
  2170. // character. Functions like coordsChar, that need to do a lot of
  2171. // measurements in a row, can thus ensure that the set-up work is
  2172. // only done once.
  2173. function prepareMeasureForLine(cm, line) {
  2174. var lineN = lineNo(line);
  2175. var view = findViewForLine(cm, lineN);
  2176. if (view && !view.text) {
  2177. view = null;
  2178. } else if (view && view.changes) {
  2179. updateLineForChanges(cm, view, lineN, getDimensions(cm));
  2180. cm.curOp.forceUpdate = true;
  2181. }
  2182. if (!view)
  2183. { view = updateExternalMeasurement(cm, line); }
  2184. var info = mapFromLineView(view, line, lineN);
  2185. return {
  2186. line: line, view: view, rect: null,
  2187. map: info.map, cache: info.cache, before: info.before,
  2188. hasHeights: false
  2189. }
  2190. }
  2191. // Given a prepared measurement object, measures the position of an
  2192. // actual character (or fetches it from the cache).
  2193. function measureCharPrepared(cm, prepared, ch, bias, varHeight) {
  2194. if (prepared.before) { ch = -1; }
  2195. var key = ch + (bias || ""), found;
  2196. if (prepared.cache.hasOwnProperty(key)) {
  2197. found = prepared.cache[key];
  2198. } else {
  2199. if (!prepared.rect)
  2200. { prepared.rect = prepared.view.text.getBoundingClientRect(); }
  2201. if (!prepared.hasHeights) {
  2202. ensureLineHeights(cm, prepared.view, prepared.rect);
  2203. prepared.hasHeights = true;
  2204. }
  2205. found = measureCharInner(cm, prepared, ch, bias);
  2206. if (!found.bogus) { prepared.cache[key] = found; }
  2207. }
  2208. return {left: found.left, right: found.right,
  2209. top: varHeight ? found.rtop : found.top,
  2210. bottom: varHeight ? found.rbottom : found.bottom}
  2211. }
  2212. var nullRect = {left: 0, right: 0, top: 0, bottom: 0};
  2213. function nodeAndOffsetInLineMap(map, ch, bias) {
  2214. var node, start, end, collapse, mStart, mEnd;
  2215. // First, search the line map for the text node corresponding to,
  2216. // or closest to, the target character.
  2217. for (var i = 0; i < map.length; i += 3) {
  2218. mStart = map[i];
  2219. mEnd = map[i + 1];
  2220. if (ch < mStart) {
  2221. start = 0; end = 1;
  2222. collapse = "left";
  2223. } else if (ch < mEnd) {
  2224. start = ch - mStart;
  2225. end = start + 1;
  2226. } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
  2227. end = mEnd - mStart;
  2228. start = end - 1;
  2229. if (ch >= mEnd) { collapse = "right"; }
  2230. }
  2231. if (start != null) {
  2232. node = map[i + 2];
  2233. if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
  2234. { collapse = bias; }
  2235. if (bias == "left" && start == 0)
  2236. { while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
  2237. node = map[(i -= 3) + 2];
  2238. collapse = "left";
  2239. } }
  2240. if (bias == "right" && start == mEnd - mStart)
  2241. { while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
  2242. node = map[(i += 3) + 2];
  2243. collapse = "right";
  2244. } }
  2245. break
  2246. }
  2247. }
  2248. return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd}
  2249. }
  2250. function getUsefulRect(rects, bias) {
  2251. var rect = nullRect;
  2252. if (bias == "left") { for (var i = 0; i < rects.length; i++) {
  2253. if ((rect = rects[i]).left != rect.right) { break }
  2254. } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) {
  2255. if ((rect = rects[i$1]).left != rect.right) { break }
  2256. } }
  2257. return rect
  2258. }
  2259. function measureCharInner(cm, prepared, ch, bias) {
  2260. var place = nodeAndOffsetInLineMap(prepared.map, ch, bias);
  2261. var node = place.node, start = place.start, end = place.end, collapse = place.collapse;
  2262. var rect;
  2263. if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
  2264. for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned
  2265. while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start; }
  2266. while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end; }
  2267. if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart)
  2268. { rect = node.parentNode.getBoundingClientRect(); }
  2269. else
  2270. { rect = getUsefulRect(range(node, start, end).getClientRects(), bias); }
  2271. if (rect.left || rect.right || start == 0) { break }
  2272. end = start;
  2273. start = start - 1;
  2274. collapse = "right";
  2275. }
  2276. if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect); }
  2277. } else { // If it is a widget, simply get the box for the whole widget.
  2278. if (start > 0) { collapse = bias = "right"; }
  2279. var rects;
  2280. if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
  2281. { rect = rects[bias == "right" ? rects.length - 1 : 0]; }
  2282. else
  2283. { rect = node.getBoundingClientRect(); }
  2284. }
  2285. if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {
  2286. var rSpan = node.parentNode.getClientRects()[0];
  2287. if (rSpan)
  2288. { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; }
  2289. else
  2290. { rect = nullRect; }
  2291. }
  2292. var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top;
  2293. var mid = (rtop + rbot) / 2;
  2294. var heights = prepared.view.measure.heights;
  2295. var i = 0;
  2296. for (; i < heights.length - 1; i++)
  2297. { if (mid < heights[i]) { break } }
  2298. var top = i ? heights[i - 1] : 0, bot = heights[i];
  2299. var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
  2300. right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
  2301. top: top, bottom: bot};
  2302. if (!rect.left && !rect.right) { result.bogus = true; }
  2303. if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; }
  2304. return result
  2305. }
  2306. // Work around problem with bounding client rects on ranges being
  2307. // returned incorrectly when zoomed on IE10 and below.
  2308. function maybeUpdateRectForZooming(measure, rect) {
  2309. if (!window.screen || screen.logicalXDPI == null ||
  2310. screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))
  2311. { return rect }
  2312. var scaleX = screen.logicalXDPI / screen.deviceXDPI;
  2313. var scaleY = screen.logicalYDPI / screen.deviceYDPI;
  2314. return {left: rect.left * scaleX, right: rect.right * scaleX,
  2315. top: rect.top * scaleY, bottom: rect.bottom * scaleY}
  2316. }
  2317. function clearLineMeasurementCacheFor(lineView) {
  2318. if (lineView.measure) {
  2319. lineView.measure.cache = {};
  2320. lineView.measure.heights = null;
  2321. if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)
  2322. { lineView.measure.caches[i] = {}; } }
  2323. }
  2324. }
  2325. function clearLineMeasurementCache(cm) {
  2326. cm.display.externalMeasure = null;
  2327. removeChildren(cm.display.lineMeasure);
  2328. for (var i = 0; i < cm.display.view.length; i++)
  2329. { clearLineMeasurementCacheFor(cm.display.view[i]); }
  2330. }
  2331. function clearCaches(cm) {
  2332. clearLineMeasurementCache(cm);
  2333. cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null;
  2334. if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true; }
  2335. cm.display.lineNumChars = null;
  2336. }
  2337. function pageScrollX() {
  2338. // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=489206
  2339. // which causes page_Offset and bounding client rects to use
  2340. // different reference viewports and invalidate our calculations.
  2341. if (chrome && android) { return -(document.body.getBoundingClientRect().left - parseInt(getComputedStyle(document.body).marginLeft)) }
  2342. return window.pageXOffset || (document.documentElement || document.body).scrollLeft
  2343. }
  2344. function pageScrollY() {
  2345. if (chrome && android) { return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)) }
  2346. return window.pageYOffset || (document.documentElement || document.body).scrollTop
  2347. }
  2348. function widgetTopHeight(lineObj) {
  2349. var height = 0;
  2350. if (lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above)
  2351. { height += widgetHeight(lineObj.widgets[i]); } } }
  2352. return height
  2353. }
  2354. // Converts a {top, bottom, left, right} box from line-local
  2355. // coordinates into another coordinate system. Context may be one of
  2356. // "line", "div" (display.lineDiv), "local"./null (editor), "window",
  2357. // or "page".
  2358. function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) {
  2359. if (!includeWidgets) {
  2360. var height = widgetTopHeight(lineObj);
  2361. rect.top += height; rect.bottom += height;
  2362. }
  2363. if (context == "line") { return rect }
  2364. if (!context) { context = "local"; }
  2365. var yOff = heightAtLine(lineObj);
  2366. if (context == "local") { yOff += paddingTop(cm.display); }
  2367. else { yOff -= cm.display.viewOffset; }
  2368. if (context == "page" || context == "window") {
  2369. var lOff = cm.display.lineSpace.getBoundingClientRect();
  2370. yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
  2371. var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
  2372. rect.left += xOff; rect.right += xOff;
  2373. }
  2374. rect.top += yOff; rect.bottom += yOff;
  2375. return rect
  2376. }
  2377. // Coverts a box from "div" coords to another coordinate system.
  2378. // Context may be "window", "page", "div", or "local"./null.
  2379. function fromCoordSystem(cm, coords, context) {
  2380. if (context == "div") { return coords }
  2381. var left = coords.left, top = coords.top;
  2382. // First move into "page" coordinate system
  2383. if (context == "page") {
  2384. left -= pageScrollX();
  2385. top -= pageScrollY();
  2386. } else if (context == "local" || !context) {
  2387. var localBox = cm.display.sizer.getBoundingClientRect();
  2388. left += localBox.left;
  2389. top += localBox.top;
  2390. }
  2391. var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect();
  2392. return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top}
  2393. }
  2394. function charCoords(cm, pos, context, lineObj, bias) {
  2395. if (!lineObj) { lineObj = getLine(cm.doc, pos.line); }
  2396. return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context)
  2397. }
  2398. // Returns a box for a given cursor position, which may have an
  2399. // 'other' property containing the position of the secondary cursor
  2400. // on a bidi boundary.
  2401. // A cursor Pos(line, char, "before") is on the same visual line as `char - 1`
  2402. // and after `char - 1` in writing order of `char - 1`
  2403. // A cursor Pos(line, char, "after") is on the same visual line as `char`
  2404. // and before `char` in writing order of `char`
  2405. // Examples (upper-case letters are RTL, lower-case are LTR):
  2406. // Pos(0, 1, ...)
  2407. // before after
  2408. // ab a|b a|b
  2409. // aB a|B aB|
  2410. // Ab |Ab A|b
  2411. // AB B|A B|A
  2412. // Every position after the last character on a line is considered to stick
  2413. // to the last character on the line.
  2414. function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {
  2415. lineObj = lineObj || getLine(cm.doc, pos.line);
  2416. if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); }
  2417. function get(ch, right) {
  2418. var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight);
  2419. if (right) { m.left = m.right; } else { m.right = m.left; }
  2420. return intoCoordSystem(cm, lineObj, m, context)
  2421. }
  2422. var order = getOrder(lineObj, cm.doc.direction), ch = pos.ch, sticky = pos.sticky;
  2423. if (ch >= lineObj.text.length) {
  2424. ch = lineObj.text.length;
  2425. sticky = "before";
  2426. } else if (ch <= 0) {
  2427. ch = 0;
  2428. sticky = "after";
  2429. }
  2430. if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") }
  2431. function getBidi(ch, partPos, invert) {
  2432. var part = order[partPos], right = part.level == 1;
  2433. return get(invert ? ch - 1 : ch, right != invert)
  2434. }
  2435. var partPos = getBidiPartAt(order, ch, sticky);
  2436. var other = bidiOther;
  2437. var val = getBidi(ch, partPos, sticky == "before");
  2438. if (other != null) { val.other = getBidi(ch, other, sticky != "before"); }
  2439. return val
  2440. }
  2441. // Used to cheaply estimate the coordinates for a position. Used for
  2442. // intermediate scroll updates.
  2443. function estimateCoords(cm, pos) {
  2444. var left = 0;
  2445. pos = clipPos(cm.doc, pos);
  2446. if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch; }
  2447. var lineObj = getLine(cm.doc, pos.line);
  2448. var top = heightAtLine(lineObj) + paddingTop(cm.display);
  2449. return {left: left, right: left, top: top, bottom: top + lineObj.height}
  2450. }
  2451. // Positions returned by coordsChar contain some extra information.
  2452. // xRel is the relative x position of the input coordinates compared
  2453. // to the found position (so xRel > 0 means the coordinates are to
  2454. // the right of the character position, for example). When outside
  2455. // is true, that means the coordinates lie outside the line's
  2456. // vertical range.
  2457. function PosWithInfo(line, ch, sticky, outside, xRel) {
  2458. var pos = Pos(line, ch, sticky);
  2459. pos.xRel = xRel;
  2460. if (outside) { pos.outside = outside; }
  2461. return pos
  2462. }
  2463. // Compute the character position closest to the given coordinates.
  2464. // Input must be lineSpace-local ("div" coordinate system).
  2465. function coordsChar(cm, x, y) {
  2466. var doc = cm.doc;
  2467. y += cm.display.viewOffset;
  2468. if (y < 0) { return PosWithInfo(doc.first, 0, null, -1, -1) }
  2469. var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1;
  2470. if (lineN > last)
  2471. { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, 1, 1) }
  2472. if (x < 0) { x = 0; }
  2473. var lineObj = getLine(doc, lineN);
  2474. for (;;) {
  2475. var found = coordsCharInner(cm, lineObj, lineN, x, y);
  2476. var collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 || found.outside > 0 ? 1 : 0));
  2477. if (!collapsed) { return found }
  2478. var rangeEnd = collapsed.find(1);
  2479. if (rangeEnd.line == lineN) { return rangeEnd }
  2480. lineObj = getLine(doc, lineN = rangeEnd.line);
  2481. }
  2482. }
  2483. function wrappedLineExtent(cm, lineObj, preparedMeasure, y) {
  2484. y -= widgetTopHeight(lineObj);
  2485. var end = lineObj.text.length;
  2486. var begin = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; }, end, 0);
  2487. end = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch).top > y; }, begin, end);
  2488. return {begin: begin, end: end}
  2489. }
  2490. function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) {
  2491. if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); }
  2492. var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top;
  2493. return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop)
  2494. }
  2495. // Returns true if the given side of a box is after the given
  2496. // coordinates, in top-to-bottom, left-to-right order.
  2497. function boxIsAfter(box, x, y, left) {
  2498. return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x
  2499. }
  2500. function coordsCharInner(cm, lineObj, lineNo, x, y) {
  2501. // Move y into line-local coordinate space
  2502. y -= heightAtLine(lineObj);
  2503. var preparedMeasure = prepareMeasureForLine(cm, lineObj);
  2504. // When directly calling `measureCharPrepared`, we have to adjust
  2505. // for the widgets at this line.
  2506. var widgetHeight = widgetTopHeight(lineObj);
  2507. var begin = 0, end = lineObj.text.length, ltr = true;
  2508. var order = getOrder(lineObj, cm.doc.direction);
  2509. // If the line isn't plain left-to-right text, first figure out
  2510. // which bidi section the coordinates fall into.
  2511. if (order) {
  2512. var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart)
  2513. (cm, lineObj, lineNo, preparedMeasure, order, x, y);
  2514. ltr = part.level != 1;
  2515. // The awkward -1 offsets are needed because findFirst (called
  2516. // on these below) will treat its first bound as inclusive,
  2517. // second as exclusive, but we want to actually address the
  2518. // characters in the part's range
  2519. begin = ltr ? part.from : part.to - 1;
  2520. end = ltr ? part.to : part.from - 1;
  2521. }
  2522. // A binary search to find the first character whose bounding box
  2523. // starts after the coordinates. If we run across any whose box wrap
  2524. // the coordinates, store that.
  2525. var chAround = null, boxAround = null;
  2526. var ch = findFirst(function (ch) {
  2527. var box = measureCharPrepared(cm, preparedMeasure, ch);
  2528. box.top += widgetHeight; box.bottom += widgetHeight;
  2529. if (!boxIsAfter(box, x, y, false)) { return false }
  2530. if (box.top <= y && box.left <= x) {
  2531. chAround = ch;
  2532. boxAround = box;
  2533. }
  2534. return true
  2535. }, begin, end);
  2536. var baseX, sticky, outside = false;
  2537. // If a box around the coordinates was found, use that
  2538. if (boxAround) {
  2539. // Distinguish coordinates nearer to the left or right side of the box
  2540. var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr;
  2541. ch = chAround + (atStart ? 0 : 1);
  2542. sticky = atStart ? "after" : "before";
  2543. baseX = atLeft ? boxAround.left : boxAround.right;
  2544. } else {
  2545. // (Adjust for extended bound, if necessary.)
  2546. if (!ltr && (ch == end || ch == begin)) { ch++; }
  2547. // To determine which side to associate with, get the box to the
  2548. // left of the character and compare it's vertical position to the
  2549. // coordinates
  2550. sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" :
  2551. (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight <= y) == ltr ?
  2552. "after" : "before";
  2553. // Now get accurate coordinates for this place, in order to get a
  2554. // base X position
  2555. var coords = cursorCoords(cm, Pos(lineNo, ch, sticky), "line", lineObj, preparedMeasure);
  2556. baseX = coords.left;
  2557. outside = y < coords.top ? -1 : y >= coords.bottom ? 1 : 0;
  2558. }
  2559. ch = skipExtendingChars(lineObj.text, ch, 1);
  2560. return PosWithInfo(lineNo, ch, sticky, outside, x - baseX)
  2561. }
  2562. function coordsBidiPart(cm, lineObj, lineNo, preparedMeasure, order, x, y) {
  2563. // Bidi parts are sorted left-to-right, and in a non-line-wrapping
  2564. // situation, we can take this ordering to correspond to the visual
  2565. // ordering. This finds the first part whose end is after the given
  2566. // coordinates.
  2567. var index = findFirst(function (i) {
  2568. var part = order[i], ltr = part.level != 1;
  2569. return boxIsAfter(cursorCoords(cm, Pos(lineNo, ltr ? part.to : part.from, ltr ? "before" : "after"),
  2570. "line", lineObj, preparedMeasure), x, y, true)
  2571. }, 0, order.length - 1);
  2572. var part = order[index];
  2573. // If this isn't the first part, the part's start is also after
  2574. // the coordinates, and the coordinates aren't on the same line as
  2575. // that start, move one part back.
  2576. if (index > 0) {
  2577. var ltr = part.level != 1;
  2578. var start = cursorCoords(cm, Pos(lineNo, ltr ? part.from : part.to, ltr ? "after" : "before"),
  2579. "line", lineObj, preparedMeasure);
  2580. if (boxIsAfter(start, x, y, true) && start.top > y)
  2581. { part = order[index - 1]; }
  2582. }
  2583. return part
  2584. }
  2585. function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) {
  2586. // In a wrapped line, rtl text on wrapping boundaries can do things
  2587. // that don't correspond to the ordering in our `order` array at
  2588. // all, so a binary search doesn't work, and we want to return a
  2589. // part that only spans one line so that the binary search in
  2590. // coordsCharInner is safe. As such, we first find the extent of the
  2591. // wrapped line, and then do a flat search in which we discard any
  2592. // spans that aren't on the line.
  2593. var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y);
  2594. var begin = ref.begin;
  2595. var end = ref.end;
  2596. if (/\s/.test(lineObj.text.charAt(end - 1))) { end--; }
  2597. var part = null, closestDist = null;
  2598. for (var i = 0; i < order.length; i++) {
  2599. var p = order[i];
  2600. if (p.from >= end || p.to <= begin) { continue }
  2601. var ltr = p.level != 1;
  2602. var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right;
  2603. // Weigh against spans ending before this, so that they are only
  2604. // picked if nothing ends after
  2605. var dist = endX < x ? x - endX + 1e9 : endX - x;
  2606. if (!part || closestDist > dist) {
  2607. part = p;
  2608. closestDist = dist;
  2609. }
  2610. }
  2611. if (!part) { part = order[order.length - 1]; }
  2612. // Clip the part to the wrapped line.
  2613. if (part.from < begin) { part = {from: begin, to: part.to, level: part.level}; }
  2614. if (part.to > end) { part = {from: part.from, to: end, level: part.level}; }
  2615. return part
  2616. }
  2617. var measureText;
  2618. // Compute the default text height.
  2619. function textHeight(display) {
  2620. if (display.cachedTextHeight != null) { return display.cachedTextHeight }
  2621. if (measureText == null) {
  2622. measureText = elt("pre", null, "CodeMirror-line-like");
  2623. // Measure a bunch of lines, for browsers that compute
  2624. // fractional heights.
  2625. for (var i = 0; i < 49; ++i) {
  2626. measureText.appendChild(document.createTextNode("x"));
  2627. measureText.appendChild(elt("br"));
  2628. }
  2629. measureText.appendChild(document.createTextNode("x"));
  2630. }
  2631. removeChildrenAndAdd(display.measure, measureText);
  2632. var height = measureText.offsetHeight / 50;
  2633. if (height > 3) { display.cachedTextHeight = height; }
  2634. removeChildren(display.measure);
  2635. return height || 1
  2636. }
  2637. // Compute the default character width.
  2638. function charWidth(display) {
  2639. if (display.cachedCharWidth != null) { return display.cachedCharWidth }
  2640. var anchor = elt("span", "xxxxxxxxxx");
  2641. var pre = elt("pre", [anchor], "CodeMirror-line-like");
  2642. removeChildrenAndAdd(display.measure, pre);
  2643. var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10;
  2644. if (width > 2) { display.cachedCharWidth = width; }
  2645. return width || 10
  2646. }
  2647. // Do a bulk-read of the DOM positions and sizes needed to draw the
  2648. // view, so that we don't interleave reading and writing to the DOM.
  2649. function getDimensions(cm) {
  2650. var d = cm.display, left = {}, width = {};
  2651. var gutterLeft = d.gutters.clientLeft;
  2652. for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
  2653. var id = cm.display.gutterSpecs[i].className;
  2654. left[id] = n.offsetLeft + n.clientLeft + gutterLeft;
  2655. width[id] = n.clientWidth;
  2656. }
  2657. return {fixedPos: compensateForHScroll(d),
  2658. gutterTotalWidth: d.gutters.offsetWidth,
  2659. gutterLeft: left,
  2660. gutterWidth: width,
  2661. wrapperWidth: d.wrapper.clientWidth}
  2662. }
  2663. // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
  2664. // but using getBoundingClientRect to get a sub-pixel-accurate
  2665. // result.
  2666. function compensateForHScroll(display) {
  2667. return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left
  2668. }
  2669. // Returns a function that estimates the height of a line, to use as
  2670. // first approximation until the line becomes visible (and is thus
  2671. // properly measurable).
  2672. function estimateHeight(cm) {
  2673. var th = textHeight(cm.display), wrapping = cm.options.lineWrapping;
  2674. var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3);
  2675. return function (line) {
  2676. if (lineIsHidden(cm.doc, line)) { return 0 }
  2677. var widgetsHeight = 0;
  2678. if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) {
  2679. if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height; }
  2680. } }
  2681. if (wrapping)
  2682. { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th }
  2683. else
  2684. { return widgetsHeight + th }
  2685. }
  2686. }
  2687. function estimateLineHeights(cm) {
  2688. var doc = cm.doc, est = estimateHeight(cm);
  2689. doc.iter(function (line) {
  2690. var estHeight = est(line);
  2691. if (estHeight != line.height) { updateLineHeight(line, estHeight); }
  2692. });
  2693. }
  2694. // Given a mouse event, find the corresponding position. If liberal
  2695. // is false, it checks whether a gutter or scrollbar was clicked,
  2696. // and returns null if it was. forRect is used by rectangular
  2697. // selections, and tries to estimate a character position even for
  2698. // coordinates beyond the right of the text.
  2699. function posFromMouse(cm, e, liberal, forRect) {
  2700. var display = cm.display;
  2701. if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null }
  2702. var x, y, space = display.lineSpace.getBoundingClientRect();
  2703. // Fails unpredictably on IE[67] when mouse is dragged around quickly.
  2704. try { x = e.clientX - space.left; y = e.clientY - space.top; }
  2705. catch (e$1) { return null }
  2706. var coords = coordsChar(cm, x, y), line;
  2707. if (forRect && coords.xRel > 0 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
  2708. var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;
  2709. coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff));
  2710. }
  2711. return coords
  2712. }
  2713. // Find the view element corresponding to a given line. Return null
  2714. // when the line isn't visible.
  2715. function findViewIndex(cm, n) {
  2716. if (n >= cm.display.viewTo) { return null }
  2717. n -= cm.display.viewFrom;
  2718. if (n < 0) { return null }
  2719. var view = cm.display.view;
  2720. for (var i = 0; i < view.length; i++) {
  2721. n -= view[i].size;
  2722. if (n < 0) { return i }
  2723. }
  2724. }
  2725. // Updates the display.view data structure for a given change to the
  2726. // document. From and to are in pre-change coordinates. Lendiff is
  2727. // the amount of lines added or subtracted by the change. This is
  2728. // used for changes that span multiple lines, or change the way
  2729. // lines are divided into visual lines. regLineChange (below)
  2730. // registers single-line changes.
  2731. function regChange(cm, from, to, lendiff) {
  2732. if (from == null) { from = cm.doc.first; }
  2733. if (to == null) { to = cm.doc.first + cm.doc.size; }
  2734. if (!lendiff) { lendiff = 0; }
  2735. var display = cm.display;
  2736. if (lendiff && to < display.viewTo &&
  2737. (display.updateLineNumbers == null || display.updateLineNumbers > from))
  2738. { display.updateLineNumbers = from; }
  2739. cm.curOp.viewChanged = true;
  2740. if (from >= display.viewTo) { // Change after
  2741. if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
  2742. { resetView(cm); }
  2743. } else if (to <= display.viewFrom) { // Change before
  2744. if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
  2745. resetView(cm);
  2746. } else {
  2747. display.viewFrom += lendiff;
  2748. display.viewTo += lendiff;
  2749. }
  2750. } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap
  2751. resetView(cm);
  2752. } else if (from <= display.viewFrom) { // Top overlap
  2753. var cut = viewCuttingPoint(cm, to, to + lendiff, 1);
  2754. if (cut) {
  2755. display.view = display.view.slice(cut.index);
  2756. display.viewFrom = cut.lineN;
  2757. display.viewTo += lendiff;
  2758. } else {
  2759. resetView(cm);
  2760. }
  2761. } else if (to >= display.viewTo) { // Bottom overlap
  2762. var cut$1 = viewCuttingPoint(cm, from, from, -1);
  2763. if (cut$1) {
  2764. display.view = display.view.slice(0, cut$1.index);
  2765. display.viewTo = cut$1.lineN;
  2766. } else {
  2767. resetView(cm);
  2768. }
  2769. } else { // Gap in the middle
  2770. var cutTop = viewCuttingPoint(cm, from, from, -1);
  2771. var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1);
  2772. if (cutTop && cutBot) {
  2773. display.view = display.view.slice(0, cutTop.index)
  2774. .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))
  2775. .concat(display.view.slice(cutBot.index));
  2776. display.viewTo += lendiff;
  2777. } else {
  2778. resetView(cm);
  2779. }
  2780. }
  2781. var ext = display.externalMeasured;
  2782. if (ext) {
  2783. if (to < ext.lineN)
  2784. { ext.lineN += lendiff; }
  2785. else if (from < ext.lineN + ext.size)
  2786. { display.externalMeasured = null; }
  2787. }
  2788. }
  2789. // Register a change to a single line. Type must be one of "text",
  2790. // "gutter", "class", "widget"
  2791. function regLineChange(cm, line, type) {
  2792. cm.curOp.viewChanged = true;
  2793. var display = cm.display, ext = cm.display.externalMeasured;
  2794. if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
  2795. { display.externalMeasured = null; }
  2796. if (line < display.viewFrom || line >= display.viewTo) { return }
  2797. var lineView = display.view[findViewIndex(cm, line)];
  2798. if (lineView.node == null) { return }
  2799. var arr = lineView.changes || (lineView.changes = []);
  2800. if (indexOf(arr, type) == -1) { arr.push(type); }
  2801. }
  2802. // Clear the view.
  2803. function resetView(cm) {
  2804. cm.display.viewFrom = cm.display.viewTo = cm.doc.first;
  2805. cm.display.view = [];
  2806. cm.display.viewOffset = 0;
  2807. }
  2808. function viewCuttingPoint(cm, oldN, newN, dir) {
  2809. var index = findViewIndex(cm, oldN), diff, view = cm.display.view;
  2810. if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
  2811. { return {index: index, lineN: newN} }
  2812. var n = cm.display.viewFrom;
  2813. for (var i = 0; i < index; i++)
  2814. { n += view[i].size; }
  2815. if (n != oldN) {
  2816. if (dir > 0) {
  2817. if (index == view.length - 1) { return null }
  2818. diff = (n + view[index].size) - oldN;
  2819. index++;
  2820. } else {
  2821. diff = n - oldN;
  2822. }
  2823. oldN += diff; newN += diff;
  2824. }
  2825. while (visualLineNo(cm.doc, newN) != newN) {
  2826. if (index == (dir < 0 ? 0 : view.length - 1)) { return null }
  2827. newN += dir * view[index - (dir < 0 ? 1 : 0)].size;
  2828. index += dir;
  2829. }
  2830. return {index: index, lineN: newN}
  2831. }
  2832. // Force the view to cover a given range, adding empty view element
  2833. // or clipping off existing ones as needed.
  2834. function adjustView(cm, from, to) {
  2835. var display = cm.display, view = display.view;
  2836. if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {
  2837. display.view = buildViewArray(cm, from, to);
  2838. display.viewFrom = from;
  2839. } else {
  2840. if (display.viewFrom > from)
  2841. { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); }
  2842. else if (display.viewFrom < from)
  2843. { display.view = display.view.slice(findViewIndex(cm, from)); }
  2844. display.viewFrom = from;
  2845. if (display.viewTo < to)
  2846. { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); }
  2847. else if (display.viewTo > to)
  2848. { display.view = display.view.slice(0, findViewIndex(cm, to)); }
  2849. }
  2850. display.viewTo = to;
  2851. }
  2852. // Count the number of lines in the view whose DOM representation is
  2853. // out of date (or nonexistent).
  2854. function countDirtyView(cm) {
  2855. var view = cm.display.view, dirty = 0;
  2856. for (var i = 0; i < view.length; i++) {
  2857. var lineView = view[i];
  2858. if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty; }
  2859. }
  2860. return dirty
  2861. }
  2862. function updateSelection(cm) {
  2863. cm.display.input.showSelection(cm.display.input.prepareSelection());
  2864. }
  2865. function prepareSelection(cm, primary) {
  2866. if ( primary === void 0 ) primary = true;
  2867. var doc = cm.doc, result = {};
  2868. var curFragment = result.cursors = document.createDocumentFragment();
  2869. var selFragment = result.selection = document.createDocumentFragment();
  2870. for (var i = 0; i < doc.sel.ranges.length; i++) {
  2871. if (!primary && i == doc.sel.primIndex) { continue }
  2872. var range = doc.sel.ranges[i];
  2873. if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue }
  2874. var collapsed = range.empty();
  2875. if (collapsed || cm.options.showCursorWhenSelecting)
  2876. { drawSelectionCursor(cm, range.head, curFragment); }
  2877. if (!collapsed)
  2878. { drawSelectionRange(cm, range, selFragment); }
  2879. }
  2880. return result
  2881. }
  2882. // Draws a cursor for the given range
  2883. function drawSelectionCursor(cm, head, output) {
  2884. var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine);
  2885. var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"));
  2886. cursor.style.left = pos.left + "px";
  2887. cursor.style.top = pos.top + "px";
  2888. cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
  2889. if (pos.other) {
  2890. // Secondary cursor, shown when on a 'jump' in bi-directional text
  2891. var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
  2892. otherCursor.style.display = "";
  2893. otherCursor.style.left = pos.other.left + "px";
  2894. otherCursor.style.top = pos.other.top + "px";
  2895. otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px";
  2896. }
  2897. }
  2898. function cmpCoords(a, b) { return a.top - b.top || a.left - b.left }
  2899. // Draws the given range as a highlighted selection
  2900. function drawSelectionRange(cm, range, output) {
  2901. var display = cm.display, doc = cm.doc;
  2902. var fragment = document.createDocumentFragment();
  2903. var padding = paddingH(cm.display), leftSide = padding.left;
  2904. var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right;
  2905. var docLTR = doc.direction == "ltr";
  2906. function add(left, top, width, bottom) {
  2907. if (top < 0) { top = 0; }
  2908. top = Math.round(top);
  2909. bottom = Math.round(bottom);
  2910. fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n height: " + (bottom - top) + "px")));
  2911. }
  2912. function drawForLine(line, fromArg, toArg) {
  2913. var lineObj = getLine(doc, line);
  2914. var lineLen = lineObj.text.length;
  2915. var start, end;
  2916. function coords(ch, bias) {
  2917. return charCoords(cm, Pos(line, ch), "div", lineObj, bias)
  2918. }
  2919. function wrapX(pos, dir, side) {
  2920. var extent = wrappedLineExtentChar(cm, lineObj, null, pos);
  2921. var prop = (dir == "ltr") == (side == "after") ? "left" : "right";
  2922. var ch = side == "after" ? extent.begin : extent.end - (/\s/.test(lineObj.text.charAt(extent.end - 1)) ? 2 : 1);
  2923. return coords(ch, prop)[prop]
  2924. }
  2925. var order = getOrder(lineObj, doc.direction);
  2926. iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) {
  2927. var ltr = dir == "ltr";
  2928. var fromPos = coords(from, ltr ? "left" : "right");
  2929. var toPos = coords(to - 1, ltr ? "right" : "left");
  2930. var openStart = fromArg == null && from == 0, openEnd = toArg == null && to == lineLen;
  2931. var first = i == 0, last = !order || i == order.length - 1;
  2932. if (toPos.top - fromPos.top <= 3) { // Single line
  2933. var openLeft = (docLTR ? openStart : openEnd) && first;
  2934. var openRight = (docLTR ? openEnd : openStart) && last;
  2935. var left = openLeft ? leftSide : (ltr ? fromPos : toPos).left;
  2936. var right = openRight ? rightSide : (ltr ? toPos : fromPos).right;
  2937. add(left, fromPos.top, right - left, fromPos.bottom);
  2938. } else { // Multiple lines
  2939. var topLeft, topRight, botLeft, botRight;
  2940. if (ltr) {
  2941. topLeft = docLTR && openStart && first ? leftSide : fromPos.left;
  2942. topRight = docLTR ? rightSide : wrapX(from, dir, "before");
  2943. botLeft = docLTR ? leftSide : wrapX(to, dir, "after");
  2944. botRight = docLTR && openEnd && last ? rightSide : toPos.right;
  2945. } else {
  2946. topLeft = !docLTR ? leftSide : wrapX(from, dir, "before");
  2947. topRight = !docLTR && openStart && first ? rightSide : fromPos.right;
  2948. botLeft = !docLTR && openEnd && last ? leftSide : toPos.left;
  2949. botRight = !docLTR ? rightSide : wrapX(to, dir, "after");
  2950. }
  2951. add(topLeft, fromPos.top, topRight - topLeft, fromPos.bottom);
  2952. if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top); }
  2953. add(botLeft, toPos.top, botRight - botLeft, toPos.bottom);
  2954. }
  2955. if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos; }
  2956. if (cmpCoords(toPos, start) < 0) { start = toPos; }
  2957. if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos; }
  2958. if (cmpCoords(toPos, end) < 0) { end = toPos; }
  2959. });
  2960. return {start: start, end: end}
  2961. }
  2962. var sFrom = range.from(), sTo = range.to();
  2963. if (sFrom.line == sTo.line) {
  2964. drawForLine(sFrom.line, sFrom.ch, sTo.ch);
  2965. } else {
  2966. var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line);
  2967. var singleVLine = visualLine(fromLine) == visualLine(toLine);
  2968. var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end;
  2969. var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start;
  2970. if (singleVLine) {
  2971. if (leftEnd.top < rightStart.top - 2) {
  2972. add(leftEnd.right, leftEnd.top, null, leftEnd.bottom);
  2973. add(leftSide, rightStart.top, rightStart.left, rightStart.bottom);
  2974. } else {
  2975. add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom);
  2976. }
  2977. }
  2978. if (leftEnd.bottom < rightStart.top)
  2979. { add(leftSide, leftEnd.bottom, null, rightStart.top); }
  2980. }
  2981. output.appendChild(fragment);
  2982. }
  2983. // Cursor-blinking
  2984. function restartBlink(cm) {
  2985. if (!cm.state.focused) { return }
  2986. var display = cm.display;
  2987. clearInterval(display.blinker);
  2988. var on = true;
  2989. display.cursorDiv.style.visibility = "";
  2990. if (cm.options.cursorBlinkRate > 0)
  2991. { display.blinker = setInterval(function () { return display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; },
  2992. cm.options.cursorBlinkRate); }
  2993. else if (cm.options.cursorBlinkRate < 0)
  2994. { display.cursorDiv.style.visibility = "hidden"; }
  2995. }
  2996. function ensureFocus(cm) {
  2997. if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); }
  2998. }
  2999. function delayBlurEvent(cm) {
  3000. cm.state.delayingBlurEvent = true;
  3001. setTimeout(function () { if (cm.state.delayingBlurEvent) {
  3002. cm.state.delayingBlurEvent = false;
  3003. onBlur(cm);
  3004. } }, 100);
  3005. }
  3006. function onFocus(cm, e) {
  3007. if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false; }
  3008. if (cm.options.readOnly == "nocursor") { return }
  3009. if (!cm.state.focused) {
  3010. signal(cm, "focus", cm, e);
  3011. cm.state.focused = true;
  3012. addClass(cm.display.wrapper, "CodeMirror-focused");
  3013. // This test prevents this from firing when a context
  3014. // menu is closed (since the input reset would kill the
  3015. // select-all detection hack)
  3016. if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
  3017. cm.display.input.reset();
  3018. if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20); } // Issue #1730
  3019. }
  3020. cm.display.input.receivedFocus();
  3021. }
  3022. restartBlink(cm);
  3023. }
  3024. function onBlur(cm, e) {
  3025. if (cm.state.delayingBlurEvent) { return }
  3026. if (cm.state.focused) {
  3027. signal(cm, "blur", cm, e);
  3028. cm.state.focused = false;
  3029. rmClass(cm.display.wrapper, "CodeMirror-focused");
  3030. }
  3031. clearInterval(cm.display.blinker);
  3032. setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false; } }, 150);
  3033. }
  3034. // Read the actual heights of the rendered lines, and update their
  3035. // stored heights to match.
  3036. function updateHeightsInViewport(cm) {
  3037. var display = cm.display;
  3038. var prevBottom = display.lineDiv.offsetTop;
  3039. for (var i = 0; i < display.view.length; i++) {
  3040. var cur = display.view[i], wrapping = cm.options.lineWrapping;
  3041. var height = (void 0), width = 0;
  3042. if (cur.hidden) { continue }
  3043. if (ie && ie_version < 8) {
  3044. var bot = cur.node.offsetTop + cur.node.offsetHeight;
  3045. height = bot - prevBottom;
  3046. prevBottom = bot;
  3047. } else {
  3048. var box = cur.node.getBoundingClientRect();
  3049. height = box.bottom - box.top;
  3050. // Check that lines don't extend past the right of the current
  3051. // editor width
  3052. if (!wrapping && cur.text.firstChild)
  3053. { width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1; }
  3054. }
  3055. var diff = cur.line.height - height;
  3056. if (diff > .005 || diff < -.005) {
  3057. updateLineHeight(cur.line, height);
  3058. updateWidgetHeight(cur.line);
  3059. if (cur.rest) { for (var j = 0; j < cur.rest.length; j++)
  3060. { updateWidgetHeight(cur.rest[j]); } }
  3061. }
  3062. if (width > cm.display.sizerWidth) {
  3063. var chWidth = Math.ceil(width / charWidth(cm.display));
  3064. if (chWidth > cm.display.maxLineLength) {
  3065. cm.display.maxLineLength = chWidth;
  3066. cm.display.maxLine = cur.line;
  3067. cm.display.maxLineChanged = true;
  3068. }
  3069. }
  3070. }
  3071. }
  3072. // Read and store the height of line widgets associated with the
  3073. // given line.
  3074. function updateWidgetHeight(line) {
  3075. if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i) {
  3076. var w = line.widgets[i], parent = w.node.parentNode;
  3077. if (parent) { w.height = parent.offsetHeight; }
  3078. } }
  3079. }
  3080. // Compute the lines that are visible in a given viewport (defaults
  3081. // the the current scroll position). viewport may contain top,
  3082. // height, and ensure (see op.scrollToPos) properties.
  3083. function visibleLines(display, doc, viewport) {
  3084. var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop;
  3085. top = Math.floor(top - paddingTop(display));
  3086. var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight;
  3087. var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom);
  3088. // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
  3089. // forces those lines into the viewport (if possible).
  3090. if (viewport && viewport.ensure) {
  3091. var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line;
  3092. if (ensureFrom < from) {
  3093. from = ensureFrom;
  3094. to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight);
  3095. } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
  3096. from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight);
  3097. to = ensureTo;
  3098. }
  3099. }
  3100. return {from: from, to: Math.max(to, from + 1)}
  3101. }
  3102. // SCROLLING THINGS INTO VIEW
  3103. // If an editor sits on the top or bottom of the window, partially
  3104. // scrolled out of view, this ensures that the cursor is visible.
  3105. function maybeScrollWindow(cm, rect) {
  3106. if (signalDOMEvent(cm, "scrollCursorIntoView")) { return }
  3107. var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
  3108. if (rect.top + box.top < 0) { doScroll = true; }
  3109. else if (rect.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false; }
  3110. if (doScroll != null && !phantom) {
  3111. var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;"));
  3112. cm.display.lineSpace.appendChild(scrollNode);
  3113. scrollNode.scrollIntoView(doScroll);
  3114. cm.display.lineSpace.removeChild(scrollNode);
  3115. }
  3116. }
  3117. // Scroll a given position into view (immediately), verifying that
  3118. // it actually became visible (as line heights are accurately
  3119. // measured, the position of something may 'drift' during drawing).
  3120. function scrollPosIntoView(cm, pos, end, margin) {
  3121. if (margin == null) { margin = 0; }
  3122. var rect;
  3123. if (!cm.options.lineWrapping && pos == end) {
  3124. // Set pos and end to the cursor positions around the character pos sticks to
  3125. // If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch
  3126. // If pos == Pos(_, 0, "before"), pos and end are unchanged
  3127. pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos;
  3128. end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos;
  3129. }
  3130. for (var limit = 0; limit < 5; limit++) {
  3131. var changed = false;
  3132. var coords = cursorCoords(cm, pos);
  3133. var endCoords = !end || end == pos ? coords : cursorCoords(cm, end);
  3134. rect = {left: Math.min(coords.left, endCoords.left),
  3135. top: Math.min(coords.top, endCoords.top) - margin,
  3136. right: Math.max(coords.left, endCoords.left),
  3137. bottom: Math.max(coords.bottom, endCoords.bottom) + margin};
  3138. var scrollPos = calculateScrollPos(cm, rect);
  3139. var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft;
  3140. if (scrollPos.scrollTop != null) {
  3141. updateScrollTop(cm, scrollPos.scrollTop);
  3142. if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true; }
  3143. }
  3144. if (scrollPos.scrollLeft != null) {
  3145. setScrollLeft(cm, scrollPos.scrollLeft);
  3146. if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true; }
  3147. }
  3148. if (!changed) { break }
  3149. }
  3150. return rect
  3151. }
  3152. // Scroll a given set of coordinates into view (immediately).
  3153. function scrollIntoView(cm, rect) {
  3154. var scrollPos = calculateScrollPos(cm, rect);
  3155. if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop); }
  3156. if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); }
  3157. }
  3158. // Calculate a new scroll position needed to scroll the given
  3159. // rectangle into view. Returns an object with scrollTop and
  3160. // scrollLeft properties. When these are undefined, the
  3161. // vertical/horizontal position does not need to be adjusted.
  3162. function calculateScrollPos(cm, rect) {
  3163. var display = cm.display, snapMargin = textHeight(cm.display);
  3164. if (rect.top < 0) { rect.top = 0; }
  3165. var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop;
  3166. var screen = displayHeight(cm), result = {};
  3167. if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen; }
  3168. var docBottom = cm.doc.height + paddingVert(display);
  3169. var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin;
  3170. if (rect.top < screentop) {
  3171. result.scrollTop = atTop ? 0 : rect.top;
  3172. } else if (rect.bottom > screentop + screen) {
  3173. var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen);
  3174. if (newTop != screentop) { result.scrollTop = newTop; }
  3175. }
  3176. var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;
  3177. var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);
  3178. var tooWide = rect.right - rect.left > screenw;
  3179. if (tooWide) { rect.right = rect.left + screenw; }
  3180. if (rect.left < 10)
  3181. { result.scrollLeft = 0; }
  3182. else if (rect.left < screenleft)
  3183. { result.scrollLeft = Math.max(0, rect.left - (tooWide ? 0 : 10)); }
  3184. else if (rect.right > screenw + screenleft - 3)
  3185. { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; }
  3186. return result
  3187. }
  3188. // Store a relative adjustment to the scroll position in the current
  3189. // operation (to be applied when the operation finishes).
  3190. function addToScrollTop(cm, top) {
  3191. if (top == null) { return }
  3192. resolveScrollToPos(cm);
  3193. cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top;
  3194. }
  3195. // Make sure that at the end of the operation the current cursor is
  3196. // shown.
  3197. function ensureCursorVisible(cm) {
  3198. resolveScrollToPos(cm);
  3199. var cur = cm.getCursor();
  3200. cm.curOp.scrollToPos = {from: cur, to: cur, margin: cm.options.cursorScrollMargin};
  3201. }
  3202. function scrollToCoords(cm, x, y) {
  3203. if (x != null || y != null) { resolveScrollToPos(cm); }
  3204. if (x != null) { cm.curOp.scrollLeft = x; }
  3205. if (y != null) { cm.curOp.scrollTop = y; }
  3206. }
  3207. function scrollToRange(cm, range) {
  3208. resolveScrollToPos(cm);
  3209. cm.curOp.scrollToPos = range;
  3210. }
  3211. // When an operation has its scrollToPos property set, and another
  3212. // scroll action is applied before the end of the operation, this
  3213. // 'simulates' scrolling that position into view in a cheap way, so
  3214. // that the effect of intermediate scroll commands is not ignored.
  3215. function resolveScrollToPos(cm) {
  3216. var range = cm.curOp.scrollToPos;
  3217. if (range) {
  3218. cm.curOp.scrollToPos = null;
  3219. var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to);
  3220. scrollToCoordsRange(cm, from, to, range.margin);
  3221. }
  3222. }
  3223. function scrollToCoordsRange(cm, from, to, margin) {
  3224. var sPos = calculateScrollPos(cm, {
  3225. left: Math.min(from.left, to.left),
  3226. top: Math.min(from.top, to.top) - margin,
  3227. right: Math.max(from.right, to.right),
  3228. bottom: Math.max(from.bottom, to.bottom) + margin
  3229. });
  3230. scrollToCoords(cm, sPos.scrollLeft, sPos.scrollTop);
  3231. }
  3232. // Sync the scrollable area and scrollbars, ensure the viewport
  3233. // covers the visible area.
  3234. function updateScrollTop(cm, val) {
  3235. if (Math.abs(cm.doc.scrollTop - val) < 2) { return }
  3236. if (!gecko) { updateDisplaySimple(cm, {top: val}); }
  3237. setScrollTop(cm, val, true);
  3238. if (gecko) { updateDisplaySimple(cm); }
  3239. startWorker(cm, 100);
  3240. }
  3241. function setScrollTop(cm, val, forceScroll) {
  3242. val = Math.max(0, Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val));
  3243. if (cm.display.scroller.scrollTop == val && !forceScroll) { return }
  3244. cm.doc.scrollTop = val;
  3245. cm.display.scrollbars.setScrollTop(val);
  3246. if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val; }
  3247. }
  3248. // Sync scroller and scrollbar, ensure the gutter elements are
  3249. // aligned.
  3250. function setScrollLeft(cm, val, isScroller, forceScroll) {
  3251. val = Math.max(0, Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth));
  3252. if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { return }
  3253. cm.doc.scrollLeft = val;
  3254. alignHorizontally(cm);
  3255. if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val; }
  3256. cm.display.scrollbars.setScrollLeft(val);
  3257. }
  3258. // SCROLLBARS
  3259. // Prepare DOM reads needed to update the scrollbars. Done in one
  3260. // shot to minimize update/measure roundtrips.
  3261. function measureForScrollbars(cm) {
  3262. var d = cm.display, gutterW = d.gutters.offsetWidth;
  3263. var docH = Math.round(cm.doc.height + paddingVert(cm.display));
  3264. return {
  3265. clientHeight: d.scroller.clientHeight,
  3266. viewHeight: d.wrapper.clientHeight,
  3267. scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,
  3268. viewWidth: d.wrapper.clientWidth,
  3269. barLeft: cm.options.fixedGutter ? gutterW : 0,
  3270. docHeight: docH,
  3271. scrollHeight: docH + scrollGap(cm) + d.barHeight,
  3272. nativeBarWidth: d.nativeBarWidth,
  3273. gutterWidth: gutterW
  3274. }
  3275. }
  3276. var NativeScrollbars = function(place, scroll, cm) {
  3277. this.cm = cm;
  3278. var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar");
  3279. var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar");
  3280. vert.tabIndex = horiz.tabIndex = -1;
  3281. place(vert); place(horiz);
  3282. on(vert, "scroll", function () {
  3283. if (vert.clientHeight) { scroll(vert.scrollTop, "vertical"); }
  3284. });
  3285. on(horiz, "scroll", function () {
  3286. if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal"); }
  3287. });
  3288. this.checkedZeroWidth = false;
  3289. // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
  3290. if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; }
  3291. };
  3292. NativeScrollbars.prototype.update = function (measure) {
  3293. var needsH = measure.scrollWidth > measure.clientWidth + 1;
  3294. var needsV = measure.scrollHeight > measure.clientHeight + 1;
  3295. var sWidth = measure.nativeBarWidth;
  3296. if (needsV) {
  3297. this.vert.style.display = "block";
  3298. this.vert.style.bottom = needsH ? sWidth + "px" : "0";
  3299. var totalHeight = measure.viewHeight - (needsH ? sWidth : 0);
  3300. // A bug in IE8 can cause this value to be negative, so guard it.
  3301. this.vert.firstChild.style.height =
  3302. Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";
  3303. } else {
  3304. this.vert.style.display = "";
  3305. this.vert.firstChild.style.height = "0";
  3306. }
  3307. if (needsH) {
  3308. this.horiz.style.display = "block";
  3309. this.horiz.style.right = needsV ? sWidth + "px" : "0";
  3310. this.horiz.style.left = measure.barLeft + "px";
  3311. var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0);
  3312. this.horiz.firstChild.style.width =
  3313. Math.max(0, measure.scrollWidth - measure.clientWidth + totalWidth) + "px";
  3314. } else {
  3315. this.horiz.style.display = "";
  3316. this.horiz.firstChild.style.width = "0";
  3317. }
  3318. if (!this.checkedZeroWidth && measure.clientHeight > 0) {
  3319. if (sWidth == 0) { this.zeroWidthHack(); }
  3320. this.checkedZeroWidth = true;
  3321. }
  3322. return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0}
  3323. };
  3324. NativeScrollbars.prototype.setScrollLeft = function (pos) {
  3325. if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos; }
  3326. if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz, "horiz"); }
  3327. };
  3328. NativeScrollbars.prototype.setScrollTop = function (pos) {
  3329. if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos; }
  3330. if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert, "vert"); }
  3331. };
  3332. NativeScrollbars.prototype.zeroWidthHack = function () {
  3333. var w = mac && !mac_geMountainLion ? "12px" : "18px";
  3334. this.horiz.style.height = this.vert.style.width = w;
  3335. this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none";
  3336. this.disableHoriz = new Delayed;
  3337. this.disableVert = new Delayed;
  3338. };
  3339. NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay, type) {
  3340. bar.style.pointerEvents = "auto";
  3341. function maybeDisable() {
  3342. // To find out whether the scrollbar is still visible, we
  3343. // check whether the element under the pixel in the bottom
  3344. // right corner of the scrollbar box is the scrollbar box
  3345. // itself (when the bar is still visible) or its filler child
  3346. // (when the bar is hidden). If it is still visible, we keep
  3347. // it enabled, if it's hidden, we disable pointer events.
  3348. var box = bar.getBoundingClientRect();
  3349. var elt = type == "vert" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2)
  3350. : document.elementFromPoint((box.right + box.left) / 2, box.bottom - 1);
  3351. if (elt != bar) { bar.style.pointerEvents = "none"; }
  3352. else { delay.set(1000, maybeDisable); }
  3353. }
  3354. delay.set(1000, maybeDisable);
  3355. };
  3356. NativeScrollbars.prototype.clear = function () {
  3357. var parent = this.horiz.parentNode;
  3358. parent.removeChild(this.horiz);
  3359. parent.removeChild(this.vert);
  3360. };
  3361. var NullScrollbars = function () {};
  3362. NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} };
  3363. NullScrollbars.prototype.setScrollLeft = function () {};
  3364. NullScrollbars.prototype.setScrollTop = function () {};
  3365. NullScrollbars.prototype.clear = function () {};
  3366. function updateScrollbars(cm, measure) {
  3367. if (!measure) { measure = measureForScrollbars(cm); }
  3368. var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight;
  3369. updateScrollbarsInner(cm, measure);
  3370. for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {
  3371. if (startWidth != cm.display.barWidth && cm.options.lineWrapping)
  3372. { updateHeightsInViewport(cm); }
  3373. updateScrollbarsInner(cm, measureForScrollbars(cm));
  3374. startWidth = cm.display.barWidth; startHeight = cm.display.barHeight;
  3375. }
  3376. }
  3377. // Re-synchronize the fake scrollbars with the actual size of the
  3378. // content.
  3379. function updateScrollbarsInner(cm, measure) {
  3380. var d = cm.display;
  3381. var sizes = d.scrollbars.update(measure);
  3382. d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px";
  3383. d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px";
  3384. d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent";
  3385. if (sizes.right && sizes.bottom) {
  3386. d.scrollbarFiller.style.display = "block";
  3387. d.scrollbarFiller.style.height = sizes.bottom + "px";
  3388. d.scrollbarFiller.style.width = sizes.right + "px";
  3389. } else { d.scrollbarFiller.style.display = ""; }
  3390. if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
  3391. d.gutterFiller.style.display = "block";
  3392. d.gutterFiller.style.height = sizes.bottom + "px";
  3393. d.gutterFiller.style.width = measure.gutterWidth + "px";
  3394. } else { d.gutterFiller.style.display = ""; }
  3395. }
  3396. var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars};
  3397. function initScrollbars(cm) {
  3398. if (cm.display.scrollbars) {
  3399. cm.display.scrollbars.clear();
  3400. if (cm.display.scrollbars.addClass)
  3401. { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); }
  3402. }
  3403. cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) {
  3404. cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller);
  3405. // Prevent clicks in the scrollbars from killing focus
  3406. on(node, "mousedown", function () {
  3407. if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0); }
  3408. });
  3409. node.setAttribute("cm-not-content", "true");
  3410. }, function (pos, axis) {
  3411. if (axis == "horizontal") { setScrollLeft(cm, pos); }
  3412. else { updateScrollTop(cm, pos); }
  3413. }, cm);
  3414. if (cm.display.scrollbars.addClass)
  3415. { addClass(cm.display.wrapper, cm.display.scrollbars.addClass); }
  3416. }
  3417. // Operations are used to wrap a series of changes to the editor
  3418. // state in such a way that each change won't have to update the
  3419. // cursor and display (which would be awkward, slow, and
  3420. // error-prone). Instead, display updates are batched and then all
  3421. // combined and executed at once.
  3422. var nextOpId = 0;
  3423. // Start a new operation.
  3424. function startOperation(cm) {
  3425. cm.curOp = {
  3426. cm: cm,
  3427. viewChanged: false, // Flag that indicates that lines might need to be redrawn
  3428. startHeight: cm.doc.height, // Used to detect need to update scrollbar
  3429. forceUpdate: false, // Used to force a redraw
  3430. updateInput: 0, // Whether to reset the input textarea
  3431. typing: false, // Whether this reset should be careful to leave existing text (for compositing)
  3432. changeObjs: null, // Accumulated changes, for firing change events
  3433. cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on
  3434. cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already
  3435. selectionChanged: false, // Whether the selection needs to be redrawn
  3436. updateMaxLine: false, // Set when the widest line needs to be determined anew
  3437. scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
  3438. scrollToPos: null, // Used to scroll to a specific position
  3439. focus: false,
  3440. id: ++nextOpId // Unique ID
  3441. };
  3442. pushOperation(cm.curOp);
  3443. }
  3444. // Finish an operation, updating the display and signalling delayed events
  3445. function endOperation(cm) {
  3446. var op = cm.curOp;
  3447. if (op) { finishOperation(op, function (group) {
  3448. for (var i = 0; i < group.ops.length; i++)
  3449. { group.ops[i].cm.curOp = null; }
  3450. endOperations(group);
  3451. }); }
  3452. }
  3453. // The DOM updates done when an operation finishes are batched so
  3454. // that the minimum number of relayouts are required.
  3455. function endOperations(group) {
  3456. var ops = group.ops;
  3457. for (var i = 0; i < ops.length; i++) // Read DOM
  3458. { endOperation_R1(ops[i]); }
  3459. for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe)
  3460. { endOperation_W1(ops[i$1]); }
  3461. for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM
  3462. { endOperation_R2(ops[i$2]); }
  3463. for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe)
  3464. { endOperation_W2(ops[i$3]); }
  3465. for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM
  3466. { endOperation_finish(ops[i$4]); }
  3467. }
  3468. function endOperation_R1(op) {
  3469. var cm = op.cm, display = cm.display;
  3470. maybeClipScrollbars(cm);
  3471. if (op.updateMaxLine) { findMaxLine(cm); }
  3472. op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||
  3473. op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
  3474. op.scrollToPos.to.line >= display.viewTo) ||
  3475. display.maxLineChanged && cm.options.lineWrapping;
  3476. op.update = op.mustUpdate &&
  3477. new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate);
  3478. }
  3479. function endOperation_W1(op) {
  3480. op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update);
  3481. }
  3482. function endOperation_R2(op) {
  3483. var cm = op.cm, display = cm.display;
  3484. if (op.updatedDisplay) { updateHeightsInViewport(cm); }
  3485. op.barMeasure = measureForScrollbars(cm);
  3486. // If the max line changed since it was last measured, measure it,
  3487. // and ensure the document's width matches it.
  3488. // updateDisplay_W2 will use these properties to do the actual resizing
  3489. if (display.maxLineChanged && !cm.options.lineWrapping) {
  3490. op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3;
  3491. cm.display.sizerWidth = op.adjustWidthTo;
  3492. op.barMeasure.scrollWidth =
  3493. Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth);
  3494. op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm));
  3495. }
  3496. if (op.updatedDisplay || op.selectionChanged)
  3497. { op.preparedSelection = display.input.prepareSelection(); }
  3498. }
  3499. function endOperation_W2(op) {
  3500. var cm = op.cm;
  3501. if (op.adjustWidthTo != null) {
  3502. cm.display.sizer.style.minWidth = op.adjustWidthTo + "px";
  3503. if (op.maxScrollLeft < cm.doc.scrollLeft)
  3504. { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); }
  3505. cm.display.maxLineChanged = false;
  3506. }
  3507. var takeFocus = op.focus && op.focus == activeElt();
  3508. if (op.preparedSelection)
  3509. { cm.display.input.showSelection(op.preparedSelection, takeFocus); }
  3510. if (op.updatedDisplay || op.startHeight != cm.doc.height)
  3511. { updateScrollbars(cm, op.barMeasure); }
  3512. if (op.updatedDisplay)
  3513. { setDocumentHeight(cm, op.barMeasure); }
  3514. if (op.selectionChanged) { restartBlink(cm); }
  3515. if (cm.state.focused && op.updateInput)
  3516. { cm.display.input.reset(op.typing); }
  3517. if (takeFocus) { ensureFocus(op.cm); }
  3518. }
  3519. function endOperation_finish(op) {
  3520. var cm = op.cm, display = cm.display, doc = cm.doc;
  3521. if (op.updatedDisplay) { postUpdateDisplay(cm, op.update); }
  3522. // Abort mouse wheel delta measurement, when scrolling explicitly
  3523. if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
  3524. { display.wheelStartX = display.wheelStartY = null; }
  3525. // Propagate the scroll position to the actual DOM scroller
  3526. if (op.scrollTop != null) { setScrollTop(cm, op.scrollTop, op.forceScroll); }
  3527. if (op.scrollLeft != null) { setScrollLeft(cm, op.scrollLeft, true, true); }
  3528. // If we need to scroll a specific position into view, do so.
  3529. if (op.scrollToPos) {
  3530. var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
  3531. clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin);
  3532. maybeScrollWindow(cm, rect);
  3533. }
  3534. // Fire events for markers that are hidden/unidden by editing or
  3535. // undoing
  3536. var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers;
  3537. if (hidden) { for (var i = 0; i < hidden.length; ++i)
  3538. { if (!hidden[i].lines.length) { signal(hidden[i], "hide"); } } }
  3539. if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1)
  3540. { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide"); } } }
  3541. if (display.wrapper.offsetHeight)
  3542. { doc.scrollTop = cm.display.scroller.scrollTop; }
  3543. // Fire change events, and delayed event handlers
  3544. if (op.changeObjs)
  3545. { signal(cm, "changes", cm, op.changeObjs); }
  3546. if (op.update)
  3547. { op.update.finish(); }
  3548. }
  3549. // Run the given function in an operation
  3550. function runInOp(cm, f) {
  3551. if (cm.curOp) { return f() }
  3552. startOperation(cm);
  3553. try { return f() }
  3554. finally { endOperation(cm); }
  3555. }
  3556. // Wraps a function in an operation. Returns the wrapped function.
  3557. function operation(cm, f) {
  3558. return function() {
  3559. if (cm.curOp) { return f.apply(cm, arguments) }
  3560. startOperation(cm);
  3561. try { return f.apply(cm, arguments) }
  3562. finally { endOperation(cm); }
  3563. }
  3564. }
  3565. // Used to add methods to editor and doc instances, wrapping them in
  3566. // operations.
  3567. function methodOp(f) {
  3568. return function() {
  3569. if (this.curOp) { return f.apply(this, arguments) }
  3570. startOperation(this);
  3571. try { return f.apply(this, arguments) }
  3572. finally { endOperation(this); }
  3573. }
  3574. }
  3575. function docMethodOp(f) {
  3576. return function() {
  3577. var cm = this.cm;
  3578. if (!cm || cm.curOp) { return f.apply(this, arguments) }
  3579. startOperation(cm);
  3580. try { return f.apply(this, arguments) }
  3581. finally { endOperation(cm); }
  3582. }
  3583. }
  3584. // HIGHLIGHT WORKER
  3585. function startWorker(cm, time) {
  3586. if (cm.doc.highlightFrontier < cm.display.viewTo)
  3587. { cm.state.highlight.set(time, bind(highlightWorker, cm)); }
  3588. }
  3589. function highlightWorker(cm) {
  3590. var doc = cm.doc;
  3591. if (doc.highlightFrontier >= cm.display.viewTo) { return }
  3592. var end = +new Date + cm.options.workTime;
  3593. var context = getContextBefore(cm, doc.highlightFrontier);
  3594. var changedLines = [];
  3595. doc.iter(context.line, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) {
  3596. if (context.line >= cm.display.viewFrom) { // Visible
  3597. var oldStyles = line.styles;
  3598. var resetState = line.text.length > cm.options.maxHighlightLength ? copyState(doc.mode, context.state) : null;
  3599. var highlighted = highlightLine(cm, line, context, true);
  3600. if (resetState) { context.state = resetState; }
  3601. line.styles = highlighted.styles;
  3602. var oldCls = line.styleClasses, newCls = highlighted.classes;
  3603. if (newCls) { line.styleClasses = newCls; }
  3604. else if (oldCls) { line.styleClasses = null; }
  3605. var ischange = !oldStyles || oldStyles.length != line.styles.length ||
  3606. oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass);
  3607. for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i]; }
  3608. if (ischange) { changedLines.push(context.line); }
  3609. line.stateAfter = context.save();
  3610. context.nextLine();
  3611. } else {
  3612. if (line.text.length <= cm.options.maxHighlightLength)
  3613. { processLine(cm, line.text, context); }
  3614. line.stateAfter = context.line % 5 == 0 ? context.save() : null;
  3615. context.nextLine();
  3616. }
  3617. if (+new Date > end) {
  3618. startWorker(cm, cm.options.workDelay);
  3619. return true
  3620. }
  3621. });
  3622. doc.highlightFrontier = context.line;
  3623. doc.modeFrontier = Math.max(doc.modeFrontier, context.line);
  3624. if (changedLines.length) { runInOp(cm, function () {
  3625. for (var i = 0; i < changedLines.length; i++)
  3626. { regLineChange(cm, changedLines[i], "text"); }
  3627. }); }
  3628. }
  3629. // DISPLAY DRAWING
  3630. var DisplayUpdate = function(cm, viewport, force) {
  3631. var display = cm.display;
  3632. this.viewport = viewport;
  3633. // Store some values that we'll need later (but don't want to force a relayout for)
  3634. this.visible = visibleLines(display, cm.doc, viewport);
  3635. this.editorIsHidden = !display.wrapper.offsetWidth;
  3636. this.wrapperHeight = display.wrapper.clientHeight;
  3637. this.wrapperWidth = display.wrapper.clientWidth;
  3638. this.oldDisplayWidth = displayWidth(cm);
  3639. this.force = force;
  3640. this.dims = getDimensions(cm);
  3641. this.events = [];
  3642. };
  3643. DisplayUpdate.prototype.signal = function (emitter, type) {
  3644. if (hasHandler(emitter, type))
  3645. { this.events.push(arguments); }
  3646. };
  3647. DisplayUpdate.prototype.finish = function () {
  3648. for (var i = 0; i < this.events.length; i++)
  3649. { signal.apply(null, this.events[i]); }
  3650. };
  3651. function maybeClipScrollbars(cm) {
  3652. var display = cm.display;
  3653. if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
  3654. display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth;
  3655. display.heightForcer.style.height = scrollGap(cm) + "px";
  3656. display.sizer.style.marginBottom = -display.nativeBarWidth + "px";
  3657. display.sizer.style.borderRightWidth = scrollGap(cm) + "px";
  3658. display.scrollbarsClipped = true;
  3659. }
  3660. }
  3661. function selectionSnapshot(cm) {
  3662. if (cm.hasFocus()) { return null }
  3663. var active = activeElt();
  3664. if (!active || !contains(cm.display.lineDiv, active)) { return null }
  3665. var result = {activeElt: active};
  3666. if (window.getSelection) {
  3667. var sel = window.getSelection();
  3668. if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) {
  3669. result.anchorNode = sel.anchorNode;
  3670. result.anchorOffset = sel.anchorOffset;
  3671. result.focusNode = sel.focusNode;
  3672. result.focusOffset = sel.focusOffset;
  3673. }
  3674. }
  3675. return result
  3676. }
  3677. function restoreSelection(snapshot) {
  3678. if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt()) { return }
  3679. snapshot.activeElt.focus();
  3680. if (!/^(INPUT|TEXTAREA)$/.test(snapshot.activeElt.nodeName) &&
  3681. snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) {
  3682. var sel = window.getSelection(), range = document.createRange();
  3683. range.setEnd(snapshot.anchorNode, snapshot.anchorOffset);
  3684. range.collapse(false);
  3685. sel.removeAllRanges();
  3686. sel.addRange(range);
  3687. sel.extend(snapshot.focusNode, snapshot.focusOffset);
  3688. }
  3689. }
  3690. // Does the actual updating of the line display. Bails out
  3691. // (returning false) when there is nothing to be done and forced is
  3692. // false.
  3693. function updateDisplayIfNeeded(cm, update) {
  3694. var display = cm.display, doc = cm.doc;
  3695. if (update.editorIsHidden) {
  3696. resetView(cm);
  3697. return false
  3698. }
  3699. // Bail out if the visible area is already rendered and nothing changed.
  3700. if (!update.force &&
  3701. update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&
  3702. (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&
  3703. display.renderedView == display.view && countDirtyView(cm) == 0)
  3704. { return false }
  3705. if (maybeUpdateLineNumberWidth(cm)) {
  3706. resetView(cm);
  3707. update.dims = getDimensions(cm);
  3708. }
  3709. // Compute a suitable new viewport (from & to)
  3710. var end = doc.first + doc.size;
  3711. var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first);
  3712. var to = Math.min(end, update.visible.to + cm.options.viewportMargin);
  3713. if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom); }
  3714. if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo); }
  3715. if (sawCollapsedSpans) {
  3716. from = visualLineNo(cm.doc, from);
  3717. to = visualLineEndNo(cm.doc, to);
  3718. }
  3719. var different = from != display.viewFrom || to != display.viewTo ||
  3720. display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth;
  3721. adjustView(cm, from, to);
  3722. display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom));
  3723. // Position the mover div to align with the current scroll position
  3724. cm.display.mover.style.top = display.viewOffset + "px";
  3725. var toUpdate = countDirtyView(cm);
  3726. if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&
  3727. (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))
  3728. { return false }
  3729. // For big changes, we hide the enclosing element during the
  3730. // update, since that speeds up the operations on most browsers.
  3731. var selSnapshot = selectionSnapshot(cm);
  3732. if (toUpdate > 4) { display.lineDiv.style.display = "none"; }
  3733. patchDisplay(cm, display.updateLineNumbers, update.dims);
  3734. if (toUpdate > 4) { display.lineDiv.style.display = ""; }
  3735. display.renderedView = display.view;
  3736. // There might have been a widget with a focused element that got
  3737. // hidden or updated, if so re-focus it.
  3738. restoreSelection(selSnapshot);
  3739. // Prevent selection and cursors from interfering with the scroll
  3740. // width and height.
  3741. removeChildren(display.cursorDiv);
  3742. removeChildren(display.selectionDiv);
  3743. display.gutters.style.height = display.sizer.style.minHeight = 0;
  3744. if (different) {
  3745. display.lastWrapHeight = update.wrapperHeight;
  3746. display.lastWrapWidth = update.wrapperWidth;
  3747. startWorker(cm, 400);
  3748. }
  3749. display.updateLineNumbers = null;
  3750. return true
  3751. }
  3752. function postUpdateDisplay(cm, update) {
  3753. var viewport = update.viewport;
  3754. for (var first = true;; first = false) {
  3755. if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
  3756. // Clip forced viewport to actual scrollable area.
  3757. if (viewport && viewport.top != null)
  3758. { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; }
  3759. // Updated line heights might result in the drawn area not
  3760. // actually covering the viewport. Keep looping until it does.
  3761. update.visible = visibleLines(cm.display, cm.doc, viewport);
  3762. if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
  3763. { break }
  3764. } else if (first) {
  3765. update.visible = visibleLines(cm.display, cm.doc, viewport);
  3766. }
  3767. if (!updateDisplayIfNeeded(cm, update)) { break }
  3768. updateHeightsInViewport(cm);
  3769. var barMeasure = measureForScrollbars(cm);
  3770. updateSelection(cm);
  3771. updateScrollbars(cm, barMeasure);
  3772. setDocumentHeight(cm, barMeasure);
  3773. update.force = false;
  3774. }
  3775. update.signal(cm, "update", cm);
  3776. if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
  3777. update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo);
  3778. cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo;
  3779. }
  3780. }
  3781. function updateDisplaySimple(cm, viewport) {
  3782. var update = new DisplayUpdate(cm, viewport);
  3783. if (updateDisplayIfNeeded(cm, update)) {
  3784. updateHeightsInViewport(cm);
  3785. postUpdateDisplay(cm, update);
  3786. var barMeasure = measureForScrollbars(cm);
  3787. updateSelection(cm);
  3788. updateScrollbars(cm, barMeasure);
  3789. setDocumentHeight(cm, barMeasure);
  3790. update.finish();
  3791. }
  3792. }
  3793. // Sync the actual display DOM structure with display.view, removing
  3794. // nodes for lines that are no longer in view, and creating the ones
  3795. // that are not there yet, and updating the ones that are out of
  3796. // date.
  3797. function patchDisplay(cm, updateNumbersFrom, dims) {
  3798. var display = cm.display, lineNumbers = cm.options.lineNumbers;
  3799. var container = display.lineDiv, cur = container.firstChild;
  3800. function rm(node) {
  3801. var next = node.nextSibling;
  3802. // Works around a throw-scroll bug in OS X Webkit
  3803. if (webkit && mac && cm.display.currentWheelTarget == node)
  3804. { node.style.display = "none"; }
  3805. else
  3806. { node.parentNode.removeChild(node); }
  3807. return next
  3808. }
  3809. var view = display.view, lineN = display.viewFrom;
  3810. // Loop over the elements in the view, syncing cur (the DOM nodes
  3811. // in display.lineDiv) with the view as we go.
  3812. for (var i = 0; i < view.length; i++) {
  3813. var lineView = view[i];
  3814. if (lineView.hidden) ; else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet
  3815. var node = buildLineElement(cm, lineView, lineN, dims);
  3816. container.insertBefore(node, cur);
  3817. } else { // Already drawn
  3818. while (cur != lineView.node) { cur = rm(cur); }
  3819. var updateNumber = lineNumbers && updateNumbersFrom != null &&
  3820. updateNumbersFrom <= lineN && lineView.lineNumber;
  3821. if (lineView.changes) {
  3822. if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false; }
  3823. updateLineForChanges(cm, lineView, lineN, dims);
  3824. }
  3825. if (updateNumber) {
  3826. removeChildren(lineView.lineNumber);
  3827. lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)));
  3828. }
  3829. cur = lineView.node.nextSibling;
  3830. }
  3831. lineN += lineView.size;
  3832. }
  3833. while (cur) { cur = rm(cur); }
  3834. }
  3835. function updateGutterSpace(display) {
  3836. var width = display.gutters.offsetWidth;
  3837. display.sizer.style.marginLeft = width + "px";
  3838. }
  3839. function setDocumentHeight(cm, measure) {
  3840. cm.display.sizer.style.minHeight = measure.docHeight + "px";
  3841. cm.display.heightForcer.style.top = measure.docHeight + "px";
  3842. cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px";
  3843. }
  3844. // Re-align line numbers and gutter marks to compensate for
  3845. // horizontal scrolling.
  3846. function alignHorizontally(cm) {
  3847. var display = cm.display, view = display.view;
  3848. if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return }
  3849. var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft;
  3850. var gutterW = display.gutters.offsetWidth, left = comp + "px";
  3851. for (var i = 0; i < view.length; i++) { if (!view[i].hidden) {
  3852. if (cm.options.fixedGutter) {
  3853. if (view[i].gutter)
  3854. { view[i].gutter.style.left = left; }
  3855. if (view[i].gutterBackground)
  3856. { view[i].gutterBackground.style.left = left; }
  3857. }
  3858. var align = view[i].alignable;
  3859. if (align) { for (var j = 0; j < align.length; j++)
  3860. { align[j].style.left = left; } }
  3861. } }
  3862. if (cm.options.fixedGutter)
  3863. { display.gutters.style.left = (comp + gutterW) + "px"; }
  3864. }
  3865. // Used to ensure that the line number gutter is still the right
  3866. // size for the current document size. Returns true when an update
  3867. // is needed.
  3868. function maybeUpdateLineNumberWidth(cm) {
  3869. if (!cm.options.lineNumbers) { return false }
  3870. var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display;
  3871. if (last.length != display.lineNumChars) {
  3872. var test = display.measure.appendChild(elt("div", [elt("div", last)],
  3873. "CodeMirror-linenumber CodeMirror-gutter-elt"));
  3874. var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW;
  3875. display.lineGutter.style.width = "";
  3876. display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1;
  3877. display.lineNumWidth = display.lineNumInnerWidth + padding;
  3878. display.lineNumChars = display.lineNumInnerWidth ? last.length : -1;
  3879. display.lineGutter.style.width = display.lineNumWidth + "px";
  3880. updateGutterSpace(cm.display);
  3881. return true
  3882. }
  3883. return false
  3884. }
  3885. function getGutters(gutters, lineNumbers) {
  3886. var result = [], sawLineNumbers = false;
  3887. for (var i = 0; i < gutters.length; i++) {
  3888. var name = gutters[i], style = null;
  3889. if (typeof name != "string") { style = name.style; name = name.className; }
  3890. if (name == "CodeMirror-linenumbers") {
  3891. if (!lineNumbers) { continue }
  3892. else { sawLineNumbers = true; }
  3893. }
  3894. result.push({className: name, style: style});
  3895. }
  3896. if (lineNumbers && !sawLineNumbers) { result.push({className: "CodeMirror-linenumbers", style: null}); }
  3897. return result
  3898. }
  3899. // Rebuild the gutter elements, ensure the margin to the left of the
  3900. // code matches their width.
  3901. function renderGutters(display) {
  3902. var gutters = display.gutters, specs = display.gutterSpecs;
  3903. removeChildren(gutters);
  3904. display.lineGutter = null;
  3905. for (var i = 0; i < specs.length; ++i) {
  3906. var ref = specs[i];
  3907. var className = ref.className;
  3908. var style = ref.style;
  3909. var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + className));
  3910. if (style) { gElt.style.cssText = style; }
  3911. if (className == "CodeMirror-linenumbers") {
  3912. display.lineGutter = gElt;
  3913. gElt.style.width = (display.lineNumWidth || 1) + "px";
  3914. }
  3915. }
  3916. gutters.style.display = specs.length ? "" : "none";
  3917. updateGutterSpace(display);
  3918. }
  3919. function updateGutters(cm) {
  3920. renderGutters(cm.display);
  3921. regChange(cm);
  3922. alignHorizontally(cm);
  3923. }
  3924. // The display handles the DOM integration, both for input reading
  3925. // and content drawing. It holds references to DOM nodes and
  3926. // display-related state.
  3927. function Display(place, doc, input, options) {
  3928. var d = this;
  3929. this.input = input;
  3930. // Covers bottom-right square when both scrollbars are present.
  3931. d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler");
  3932. d.scrollbarFiller.setAttribute("cm-not-content", "true");
  3933. // Covers bottom of gutter when coverGutterNextToScrollbar is on
  3934. // and h scrollbar is present.
  3935. d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler");
  3936. d.gutterFiller.setAttribute("cm-not-content", "true");
  3937. // Will contain the actual code, positioned to cover the viewport.
  3938. d.lineDiv = eltP("div", null, "CodeMirror-code");
  3939. // Elements are added to these to represent selection and cursors.
  3940. d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1");
  3941. d.cursorDiv = elt("div", null, "CodeMirror-cursors");
  3942. // A visibility: hidden element used to find the size of things.
  3943. d.measure = elt("div", null, "CodeMirror-measure");
  3944. // When lines outside of the viewport are measured, they are drawn in this.
  3945. d.lineMeasure = elt("div", null, "CodeMirror-measure");
  3946. // Wraps everything that needs to exist inside the vertically-padded coordinate system
  3947. d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
  3948. null, "position: relative; outline: none");
  3949. var lines = eltP("div", [d.lineSpace], "CodeMirror-lines");
  3950. // Moved around its parent to cover visible view.
  3951. d.mover = elt("div", [lines], null, "position: relative");
  3952. // Set to the height of the document, allowing scrolling.
  3953. d.sizer = elt("div", [d.mover], "CodeMirror-sizer");
  3954. d.sizerWidth = null;
  3955. // Behavior of elts with overflow: auto and padding is
  3956. // inconsistent across browsers. This is used to ensure the
  3957. // scrollable area is big enough.
  3958. d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;");
  3959. // Will contain the gutters, if any.
  3960. d.gutters = elt("div", null, "CodeMirror-gutters");
  3961. d.lineGutter = null;
  3962. // Actual scrollable element.
  3963. d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll");
  3964. d.scroller.setAttribute("tabIndex", "-1");
  3965. // The element in which the editor lives.
  3966. d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
  3967. // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
  3968. if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
  3969. if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; }
  3970. if (place) {
  3971. if (place.appendChild) { place.appendChild(d.wrapper); }
  3972. else { place(d.wrapper); }
  3973. }
  3974. // Current rendered range (may be bigger than the view window).
  3975. d.viewFrom = d.viewTo = doc.first;
  3976. d.reportedViewFrom = d.reportedViewTo = doc.first;
  3977. // Information about the rendered lines.
  3978. d.view = [];
  3979. d.renderedView = null;
  3980. // Holds info about a single rendered line when it was rendered
  3981. // for measurement, while not in view.
  3982. d.externalMeasured = null;
  3983. // Empty space (in pixels) above the view
  3984. d.viewOffset = 0;
  3985. d.lastWrapHeight = d.lastWrapWidth = 0;
  3986. d.updateLineNumbers = null;
  3987. d.nativeBarWidth = d.barHeight = d.barWidth = 0;
  3988. d.scrollbarsClipped = false;
  3989. // Used to only resize the line number gutter when necessary (when
  3990. // the amount of lines crosses a boundary that makes its width change)
  3991. d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null;
  3992. // Set to true when a non-horizontal-scrolling line widget is
  3993. // added. As an optimization, line widget aligning is skipped when
  3994. // this is false.
  3995. d.alignWidgets = false;
  3996. d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
  3997. // Tracks the maximum line length so that the horizontal scrollbar
  3998. // can be kept static when scrolling.
  3999. d.maxLine = null;
  4000. d.maxLineLength = 0;
  4001. d.maxLineChanged = false;
  4002. // Used for measuring wheel scrolling granularity
  4003. d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null;
  4004. // True when shift is held down.
  4005. d.shift = false;
  4006. // Used to track whether anything happened since the context menu
  4007. // was opened.
  4008. d.selForContextMenu = null;
  4009. d.activeTouch = null;
  4010. d.gutterSpecs = getGutters(options.gutters, options.lineNumbers);
  4011. renderGutters(d);
  4012. input.init(d);
  4013. }
  4014. // Since the delta values reported on mouse wheel events are
  4015. // unstandardized between browsers and even browser versions, and
  4016. // generally horribly unpredictable, this code starts by measuring
  4017. // the scroll effect that the first few mouse wheel events have,
  4018. // and, from that, detects the way it can convert deltas to pixel
  4019. // offsets afterwards.
  4020. //
  4021. // The reason we want to know the amount a wheel event will scroll
  4022. // is that it gives us a chance to update the display before the
  4023. // actual scrolling happens, reducing flickering.
  4024. var wheelSamples = 0, wheelPixelsPerUnit = null;
  4025. // Fill in a browser-detected starting value on browsers where we
  4026. // know one. These don't have to be accurate -- the result of them
  4027. // being wrong would just be a slight flicker on the first wheel
  4028. // scroll (if it is large enough).
  4029. if (ie) { wheelPixelsPerUnit = -.53; }
  4030. else if (gecko) { wheelPixelsPerUnit = 15; }
  4031. else if (chrome) { wheelPixelsPerUnit = -.7; }
  4032. else if (safari) { wheelPixelsPerUnit = -1/3; }
  4033. function wheelEventDelta(e) {
  4034. var dx = e.wheelDeltaX, dy = e.wheelDeltaY;
  4035. if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail; }
  4036. if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail; }
  4037. else if (dy == null) { dy = e.wheelDelta; }
  4038. return {x: dx, y: dy}
  4039. }
  4040. function wheelEventPixels(e) {
  4041. var delta = wheelEventDelta(e);
  4042. delta.x *= wheelPixelsPerUnit;
  4043. delta.y *= wheelPixelsPerUnit;
  4044. return delta
  4045. }
  4046. function onScrollWheel(cm, e) {
  4047. var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;
  4048. var display = cm.display, scroll = display.scroller;
  4049. // Quit if there's nothing to scroll here
  4050. var canScrollX = scroll.scrollWidth > scroll.clientWidth;
  4051. var canScrollY = scroll.scrollHeight > scroll.clientHeight;
  4052. if (!(dx && canScrollX || dy && canScrollY)) { return }
  4053. // Webkit browsers on OS X abort momentum scrolls when the target
  4054. // of the scroll event is removed from the scrollable element.
  4055. // This hack (see related code in patchDisplay) makes sure the
  4056. // element is kept around.
  4057. if (dy && mac && webkit) {
  4058. outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
  4059. for (var i = 0; i < view.length; i++) {
  4060. if (view[i].node == cur) {
  4061. cm.display.currentWheelTarget = cur;
  4062. break outer
  4063. }
  4064. }
  4065. }
  4066. }
  4067. // On some browsers, horizontal scrolling will cause redraws to
  4068. // happen before the gutter has been realigned, causing it to
  4069. // wriggle around in a most unseemly way. When we have an
  4070. // estimated pixels/delta value, we just handle horizontal
  4071. // scrolling entirely here. It'll be slightly off from native, but
  4072. // better than glitching out.
  4073. if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
  4074. if (dy && canScrollY)
  4075. { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * wheelPixelsPerUnit)); }
  4076. setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * wheelPixelsPerUnit));
  4077. // Only prevent default scrolling if vertical scrolling is
  4078. // actually possible. Otherwise, it causes vertical scroll
  4079. // jitter on OSX trackpads when deltaX is small and deltaY
  4080. // is large (issue #3579)
  4081. if (!dy || (dy && canScrollY))
  4082. { e_preventDefault(e); }
  4083. display.wheelStartX = null; // Abort measurement, if in progress
  4084. return
  4085. }
  4086. // 'Project' the visible viewport to cover the area that is being
  4087. // scrolled into view (if we know enough to estimate it).
  4088. if (dy && wheelPixelsPerUnit != null) {
  4089. var pixels = dy * wheelPixelsPerUnit;
  4090. var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
  4091. if (pixels < 0) { top = Math.max(0, top + pixels - 50); }
  4092. else { bot = Math.min(cm.doc.height, bot + pixels + 50); }
  4093. updateDisplaySimple(cm, {top: top, bottom: bot});
  4094. }
  4095. if (wheelSamples < 20) {
  4096. if (display.wheelStartX == null) {
  4097. display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
  4098. display.wheelDX = dx; display.wheelDY = dy;
  4099. setTimeout(function () {
  4100. if (display.wheelStartX == null) { return }
  4101. var movedX = scroll.scrollLeft - display.wheelStartX;
  4102. var movedY = scroll.scrollTop - display.wheelStartY;
  4103. var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
  4104. (movedX && display.wheelDX && movedX / display.wheelDX);
  4105. display.wheelStartX = display.wheelStartY = null;
  4106. if (!sample) { return }
  4107. wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1);
  4108. ++wheelSamples;
  4109. }, 200);
  4110. } else {
  4111. display.wheelDX += dx; display.wheelDY += dy;
  4112. }
  4113. }
  4114. }
  4115. // Selection objects are immutable. A new one is created every time
  4116. // the selection changes. A selection is one or more non-overlapping
  4117. // (and non-touching) ranges, sorted, and an integer that indicates
  4118. // which one is the primary selection (the one that's scrolled into
  4119. // view, that getCursor returns, etc).
  4120. var Selection = function(ranges, primIndex) {
  4121. this.ranges = ranges;
  4122. this.primIndex = primIndex;
  4123. };
  4124. Selection.prototype.primary = function () { return this.ranges[this.primIndex] };
  4125. Selection.prototype.equals = function (other) {
  4126. if (other == this) { return true }
  4127. if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false }
  4128. for (var i = 0; i < this.ranges.length; i++) {
  4129. var here = this.ranges[i], there = other.ranges[i];
  4130. if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { return false }
  4131. }
  4132. return true
  4133. };
  4134. Selection.prototype.deepCopy = function () {
  4135. var out = [];
  4136. for (var i = 0; i < this.ranges.length; i++)
  4137. { out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head)); }
  4138. return new Selection(out, this.primIndex)
  4139. };
  4140. Selection.prototype.somethingSelected = function () {
  4141. for (var i = 0; i < this.ranges.length; i++)
  4142. { if (!this.ranges[i].empty()) { return true } }
  4143. return false
  4144. };
  4145. Selection.prototype.contains = function (pos, end) {
  4146. if (!end) { end = pos; }
  4147. for (var i = 0; i < this.ranges.length; i++) {
  4148. var range = this.ranges[i];
  4149. if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
  4150. { return i }
  4151. }
  4152. return -1
  4153. };
  4154. var Range = function(anchor, head) {
  4155. this.anchor = anchor; this.head = head;
  4156. };
  4157. Range.prototype.from = function () { return minPos(this.anchor, this.head) };
  4158. Range.prototype.to = function () { return maxPos(this.anchor, this.head) };
  4159. Range.prototype.empty = function () { return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch };
  4160. // Take an unsorted, potentially overlapping set of ranges, and
  4161. // build a selection out of it. 'Consumes' ranges array (modifying
  4162. // it).
  4163. function normalizeSelection(cm, ranges, primIndex) {
  4164. var mayTouch = cm && cm.options.selectionsMayTouch;
  4165. var prim = ranges[primIndex];
  4166. ranges.sort(function (a, b) { return cmp(a.from(), b.from()); });
  4167. primIndex = indexOf(ranges, prim);
  4168. for (var i = 1; i < ranges.length; i++) {
  4169. var cur = ranges[i], prev = ranges[i - 1];
  4170. var diff = cmp(prev.to(), cur.from());
  4171. if (mayTouch && !cur.empty() ? diff > 0 : diff >= 0) {
  4172. var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to());
  4173. var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head;
  4174. if (i <= primIndex) { --primIndex; }
  4175. ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to));
  4176. }
  4177. }
  4178. return new Selection(ranges, primIndex)
  4179. }
  4180. function simpleSelection(anchor, head) {
  4181. return new Selection([new Range(anchor, head || anchor)], 0)
  4182. }
  4183. // Compute the position of the end of a change (its 'to' property
  4184. // refers to the pre-change end).
  4185. function changeEnd(change) {
  4186. if (!change.text) { return change.to }
  4187. return Pos(change.from.line + change.text.length - 1,
  4188. lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0))
  4189. }
  4190. // Adjust a position to refer to the post-change position of the
  4191. // same text, or the end of the change if the change covers it.
  4192. function adjustForChange(pos, change) {
  4193. if (cmp(pos, change.from) < 0) { return pos }
  4194. if (cmp(pos, change.to) <= 0) { return changeEnd(change) }
  4195. var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch;
  4196. if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch; }
  4197. return Pos(line, ch)
  4198. }
  4199. function computeSelAfterChange(doc, change) {
  4200. var out = [];
  4201. for (var i = 0; i < doc.sel.ranges.length; i++) {
  4202. var range = doc.sel.ranges[i];
  4203. out.push(new Range(adjustForChange(range.anchor, change),
  4204. adjustForChange(range.head, change)));
  4205. }
  4206. return normalizeSelection(doc.cm, out, doc.sel.primIndex)
  4207. }
  4208. function offsetPos(pos, old, nw) {
  4209. if (pos.line == old.line)
  4210. { return Pos(nw.line, pos.ch - old.ch + nw.ch) }
  4211. else
  4212. { return Pos(nw.line + (pos.line - old.line), pos.ch) }
  4213. }
  4214. // Used by replaceSelections to allow moving the selection to the
  4215. // start or around the replaced test. Hint may be "start" or "around".
  4216. function computeReplacedSel(doc, changes, hint) {
  4217. var out = [];
  4218. var oldPrev = Pos(doc.first, 0), newPrev = oldPrev;
  4219. for (var i = 0; i < changes.length; i++) {
  4220. var change = changes[i];
  4221. var from = offsetPos(change.from, oldPrev, newPrev);
  4222. var to = offsetPos(changeEnd(change), oldPrev, newPrev);
  4223. oldPrev = change.to;
  4224. newPrev = to;
  4225. if (hint == "around") {
  4226. var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0;
  4227. out[i] = new Range(inv ? to : from, inv ? from : to);
  4228. } else {
  4229. out[i] = new Range(from, from);
  4230. }
  4231. }
  4232. return new Selection(out, doc.sel.primIndex)
  4233. }
  4234. // Used to get the editor into a consistent state again when options change.
  4235. function loadMode(cm) {
  4236. cm.doc.mode = getMode(cm.options, cm.doc.modeOption);
  4237. resetModeState(cm);
  4238. }
  4239. function resetModeState(cm) {
  4240. cm.doc.iter(function (line) {
  4241. if (line.stateAfter) { line.stateAfter = null; }
  4242. if (line.styles) { line.styles = null; }
  4243. });
  4244. cm.doc.modeFrontier = cm.doc.highlightFrontier = cm.doc.first;
  4245. startWorker(cm, 100);
  4246. cm.state.modeGen++;
  4247. if (cm.curOp) { regChange(cm); }
  4248. }
  4249. // DOCUMENT DATA STRUCTURE
  4250. // By default, updates that start and end at the beginning of a line
  4251. // are treated specially, in order to make the association of line
  4252. // widgets and marker elements with the text behave more intuitive.
  4253. function isWholeLineUpdate(doc, change) {
  4254. return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&
  4255. (!doc.cm || doc.cm.options.wholeLineUpdateBefore)
  4256. }
  4257. // Perform a change on the document data structure.
  4258. function updateDoc(doc, change, markedSpans, estimateHeight) {
  4259. function spansFor(n) {return markedSpans ? markedSpans[n] : null}
  4260. function update(line, text, spans) {
  4261. updateLine(line, text, spans, estimateHeight);
  4262. signalLater(line, "change", line, change);
  4263. }
  4264. function linesFor(start, end) {
  4265. var result = [];
  4266. for (var i = start; i < end; ++i)
  4267. { result.push(new Line(text[i], spansFor(i), estimateHeight)); }
  4268. return result
  4269. }
  4270. var from = change.from, to = change.to, text = change.text;
  4271. var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line);
  4272. var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line;
  4273. // Adjust the line structure
  4274. if (change.full) {
  4275. doc.insert(0, linesFor(0, text.length));
  4276. doc.remove(text.length, doc.size - text.length);
  4277. } else if (isWholeLineUpdate(doc, change)) {
  4278. // This is a whole-line replace. Treated specially to make
  4279. // sure line objects move the way they are supposed to.
  4280. var added = linesFor(0, text.length - 1);
  4281. update(lastLine, lastLine.text, lastSpans);
  4282. if (nlines) { doc.remove(from.line, nlines); }
  4283. if (added.length) { doc.insert(from.line, added); }
  4284. } else if (firstLine == lastLine) {
  4285. if (text.length == 1) {
  4286. update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
  4287. } else {
  4288. var added$1 = linesFor(1, text.length - 1);
  4289. added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
  4290. update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
  4291. doc.insert(from.line + 1, added$1);
  4292. }
  4293. } else if (text.length == 1) {
  4294. update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0));
  4295. doc.remove(from.line + 1, nlines);
  4296. } else {
  4297. update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
  4298. update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans);
  4299. var added$2 = linesFor(1, text.length - 1);
  4300. if (nlines > 1) { doc.remove(from.line + 1, nlines - 1); }
  4301. doc.insert(from.line + 1, added$2);
  4302. }
  4303. signalLater(doc, "change", doc, change);
  4304. }
  4305. // Call f for all linked documents.
  4306. function linkedDocs(doc, f, sharedHistOnly) {
  4307. function propagate(doc, skip, sharedHist) {
  4308. if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) {
  4309. var rel = doc.linked[i];
  4310. if (rel.doc == skip) { continue }
  4311. var shared = sharedHist && rel.sharedHist;
  4312. if (sharedHistOnly && !shared) { continue }
  4313. f(rel.doc, shared);
  4314. propagate(rel.doc, doc, shared);
  4315. } }
  4316. }
  4317. propagate(doc, null, true);
  4318. }
  4319. // Attach a document to an editor.
  4320. function attachDoc(cm, doc) {
  4321. if (doc.cm) { throw new Error("This document is already in use.") }
  4322. cm.doc = doc;
  4323. doc.cm = cm;
  4324. estimateLineHeights(cm);
  4325. loadMode(cm);
  4326. setDirectionClass(cm);
  4327. if (!cm.options.lineWrapping) { findMaxLine(cm); }
  4328. cm.options.mode = doc.modeOption;
  4329. regChange(cm);
  4330. }
  4331. function setDirectionClass(cm) {
  4332. (cm.doc.direction == "rtl" ? addClass : rmClass)(cm.display.lineDiv, "CodeMirror-rtl");
  4333. }
  4334. function directionChanged(cm) {
  4335. runInOp(cm, function () {
  4336. setDirectionClass(cm);
  4337. regChange(cm);
  4338. });
  4339. }
  4340. function History(startGen) {
  4341. // Arrays of change events and selections. Doing something adds an
  4342. // event to done and clears undo. Undoing moves events from done
  4343. // to undone, redoing moves them in the other direction.
  4344. this.done = []; this.undone = [];
  4345. this.undoDepth = Infinity;
  4346. // Used to track when changes can be merged into a single undo
  4347. // event
  4348. this.lastModTime = this.lastSelTime = 0;
  4349. this.lastOp = this.lastSelOp = null;
  4350. this.lastOrigin = this.lastSelOrigin = null;
  4351. // Used by the isClean() method
  4352. this.generation = this.maxGeneration = startGen || 1;
  4353. }
  4354. // Create a history change event from an updateDoc-style change
  4355. // object.
  4356. function historyChangeFromChange(doc, change) {
  4357. var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)};
  4358. attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);
  4359. linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true);
  4360. return histChange
  4361. }
  4362. // Pop all selection events off the end of a history array. Stop at
  4363. // a change event.
  4364. function clearSelectionEvents(array) {
  4365. while (array.length) {
  4366. var last = lst(array);
  4367. if (last.ranges) { array.pop(); }
  4368. else { break }
  4369. }
  4370. }
  4371. // Find the top change event in the history. Pop off selection
  4372. // events that are in the way.
  4373. function lastChangeEvent(hist, force) {
  4374. if (force) {
  4375. clearSelectionEvents(hist.done);
  4376. return lst(hist.done)
  4377. } else if (hist.done.length && !lst(hist.done).ranges) {
  4378. return lst(hist.done)
  4379. } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
  4380. hist.done.pop();
  4381. return lst(hist.done)
  4382. }
  4383. }
  4384. // Register a change in the history. Merges changes that are within
  4385. // a single operation, or are close together with an origin that
  4386. // allows merging (starting with "+") into a single event.
  4387. function addChangeToHistory(doc, change, selAfter, opId) {
  4388. var hist = doc.history;
  4389. hist.undone.length = 0;
  4390. var time = +new Date, cur;
  4391. var last;
  4392. if ((hist.lastOp == opId ||
  4393. hist.lastOrigin == change.origin && change.origin &&
  4394. ((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) ||
  4395. change.origin.charAt(0) == "*")) &&
  4396. (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
  4397. // Merge this change into the last event
  4398. last = lst(cur.changes);
  4399. if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
  4400. // Optimized case for simple insertion -- don't want to add
  4401. // new changesets for every character typed
  4402. last.to = changeEnd(change);
  4403. } else {
  4404. // Add new sub-event
  4405. cur.changes.push(historyChangeFromChange(doc, change));
  4406. }
  4407. } else {
  4408. // Can not be merged, start a new event.
  4409. var before = lst(hist.done);
  4410. if (!before || !before.ranges)
  4411. { pushSelectionToHistory(doc.sel, hist.done); }
  4412. cur = {changes: [historyChangeFromChange(doc, change)],
  4413. generation: hist.generation};
  4414. hist.done.push(cur);
  4415. while (hist.done.length > hist.undoDepth) {
  4416. hist.done.shift();
  4417. if (!hist.done[0].ranges) { hist.done.shift(); }
  4418. }
  4419. }
  4420. hist.done.push(selAfter);
  4421. hist.generation = ++hist.maxGeneration;
  4422. hist.lastModTime = hist.lastSelTime = time;
  4423. hist.lastOp = hist.lastSelOp = opId;
  4424. hist.lastOrigin = hist.lastSelOrigin = change.origin;
  4425. if (!last) { signal(doc, "historyAdded"); }
  4426. }
  4427. function selectionEventCanBeMerged(doc, origin, prev, sel) {
  4428. var ch = origin.charAt(0);
  4429. return ch == "*" ||
  4430. ch == "+" &&
  4431. prev.ranges.length == sel.ranges.length &&
  4432. prev.somethingSelected() == sel.somethingSelected() &&
  4433. new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500)
  4434. }
  4435. // Called whenever the selection changes, sets the new selection as
  4436. // the pending selection in the history, and pushes the old pending
  4437. // selection into the 'done' array when it was significantly
  4438. // different (in number of selected ranges, emptiness, or time).
  4439. function addSelectionToHistory(doc, sel, opId, options) {
  4440. var hist = doc.history, origin = options && options.origin;
  4441. // A new event is started when the previous origin does not match
  4442. // the current, or the origins don't allow matching. Origins
  4443. // starting with * are always merged, those starting with + are
  4444. // merged when similar and close together in time.
  4445. if (opId == hist.lastSelOp ||
  4446. (origin && hist.lastSelOrigin == origin &&
  4447. (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
  4448. selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
  4449. { hist.done[hist.done.length - 1] = sel; }
  4450. else
  4451. { pushSelectionToHistory(sel, hist.done); }
  4452. hist.lastSelTime = +new Date;
  4453. hist.lastSelOrigin = origin;
  4454. hist.lastSelOp = opId;
  4455. if (options && options.clearRedo !== false)
  4456. { clearSelectionEvents(hist.undone); }
  4457. }
  4458. function pushSelectionToHistory(sel, dest) {
  4459. var top = lst(dest);
  4460. if (!(top && top.ranges && top.equals(sel)))
  4461. { dest.push(sel); }
  4462. }
  4463. // Used to store marked span information in the history.
  4464. function attachLocalSpans(doc, change, from, to) {
  4465. var existing = change["spans_" + doc.id], n = 0;
  4466. doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) {
  4467. if (line.markedSpans)
  4468. { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; }
  4469. ++n;
  4470. });
  4471. }
  4472. // When un/re-doing restores text containing marked spans, those
  4473. // that have been explicitly cleared should not be restored.
  4474. function removeClearedSpans(spans) {
  4475. if (!spans) { return null }
  4476. var out;
  4477. for (var i = 0; i < spans.length; ++i) {
  4478. if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i); } }
  4479. else if (out) { out.push(spans[i]); }
  4480. }
  4481. return !out ? spans : out.length ? out : null
  4482. }
  4483. // Retrieve and filter the old marked spans stored in a change event.
  4484. function getOldSpans(doc, change) {
  4485. var found = change["spans_" + doc.id];
  4486. if (!found) { return null }
  4487. var nw = [];
  4488. for (var i = 0; i < change.text.length; ++i)
  4489. { nw.push(removeClearedSpans(found[i])); }
  4490. return nw
  4491. }
  4492. // Used for un/re-doing changes from the history. Combines the
  4493. // result of computing the existing spans with the set of spans that
  4494. // existed in the history (so that deleting around a span and then
  4495. // undoing brings back the span).
  4496. function mergeOldSpans(doc, change) {
  4497. var old = getOldSpans(doc, change);
  4498. var stretched = stretchSpansOverChange(doc, change);
  4499. if (!old) { return stretched }
  4500. if (!stretched) { return old }
  4501. for (var i = 0; i < old.length; ++i) {
  4502. var oldCur = old[i], stretchCur = stretched[i];
  4503. if (oldCur && stretchCur) {
  4504. spans: for (var j = 0; j < stretchCur.length; ++j) {
  4505. var span = stretchCur[j];
  4506. for (var k = 0; k < oldCur.length; ++k)
  4507. { if (oldCur[k].marker == span.marker) { continue spans } }
  4508. oldCur.push(span);
  4509. }
  4510. } else if (stretchCur) {
  4511. old[i] = stretchCur;
  4512. }
  4513. }
  4514. return old
  4515. }
  4516. // Used both to provide a JSON-safe object in .getHistory, and, when
  4517. // detaching a document, to split the history in two
  4518. function copyHistoryArray(events, newGroup, instantiateSel) {
  4519. var copy = [];
  4520. for (var i = 0; i < events.length; ++i) {
  4521. var event = events[i];
  4522. if (event.ranges) {
  4523. copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event);
  4524. continue
  4525. }
  4526. var changes = event.changes, newChanges = [];
  4527. copy.push({changes: newChanges});
  4528. for (var j = 0; j < changes.length; ++j) {
  4529. var change = changes[j], m = (void 0);
  4530. newChanges.push({from: change.from, to: change.to, text: change.text});
  4531. if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) {
  4532. if (indexOf(newGroup, Number(m[1])) > -1) {
  4533. lst(newChanges)[prop] = change[prop];
  4534. delete change[prop];
  4535. }
  4536. } } }
  4537. }
  4538. }
  4539. return copy
  4540. }
  4541. // The 'scroll' parameter given to many of these indicated whether
  4542. // the new cursor position should be scrolled into view after
  4543. // modifying the selection.
  4544. // If shift is held or the extend flag is set, extends a range to
  4545. // include a given position (and optionally a second position).
  4546. // Otherwise, simply returns the range between the given positions.
  4547. // Used for cursor motion and such.
  4548. function extendRange(range, head, other, extend) {
  4549. if (extend) {
  4550. var anchor = range.anchor;
  4551. if (other) {
  4552. var posBefore = cmp(head, anchor) < 0;
  4553. if (posBefore != (cmp(other, anchor) < 0)) {
  4554. anchor = head;
  4555. head = other;
  4556. } else if (posBefore != (cmp(head, other) < 0)) {
  4557. head = other;
  4558. }
  4559. }
  4560. return new Range(anchor, head)
  4561. } else {
  4562. return new Range(other || head, head)
  4563. }
  4564. }
  4565. // Extend the primary selection range, discard the rest.
  4566. function extendSelection(doc, head, other, options, extend) {
  4567. if (extend == null) { extend = doc.cm && (doc.cm.display.shift || doc.extend); }
  4568. setSelection(doc, new Selection([extendRange(doc.sel.primary(), head, other, extend)], 0), options);
  4569. }
  4570. // Extend all selections (pos is an array of selections with length
  4571. // equal the number of selections)
  4572. function extendSelections(doc, heads, options) {
  4573. var out = [];
  4574. var extend = doc.cm && (doc.cm.display.shift || doc.extend);
  4575. for (var i = 0; i < doc.sel.ranges.length; i++)
  4576. { out[i] = extendRange(doc.sel.ranges[i], heads[i], null, extend); }
  4577. var newSel = normalizeSelection(doc.cm, out, doc.sel.primIndex);
  4578. setSelection(doc, newSel, options);
  4579. }
  4580. // Updates a single range in the selection.
  4581. function replaceOneSelection(doc, i, range, options) {
  4582. var ranges = doc.sel.ranges.slice(0);
  4583. ranges[i] = range;
  4584. setSelection(doc, normalizeSelection(doc.cm, ranges, doc.sel.primIndex), options);
  4585. }
  4586. // Reset the selection to a single range.
  4587. function setSimpleSelection(doc, anchor, head, options) {
  4588. setSelection(doc, simpleSelection(anchor, head), options);
  4589. }
  4590. // Give beforeSelectionChange handlers a change to influence a
  4591. // selection update.
  4592. function filterSelectionChange(doc, sel, options) {
  4593. var obj = {
  4594. ranges: sel.ranges,
  4595. update: function(ranges) {
  4596. this.ranges = [];
  4597. for (var i = 0; i < ranges.length; i++)
  4598. { this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
  4599. clipPos(doc, ranges[i].head)); }
  4600. },
  4601. origin: options && options.origin
  4602. };
  4603. signal(doc, "beforeSelectionChange", doc, obj);
  4604. if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj); }
  4605. if (obj.ranges != sel.ranges) { return normalizeSelection(doc.cm, obj.ranges, obj.ranges.length - 1) }
  4606. else { return sel }
  4607. }
  4608. function setSelectionReplaceHistory(doc, sel, options) {
  4609. var done = doc.history.done, last = lst(done);
  4610. if (last && last.ranges) {
  4611. done[done.length - 1] = sel;
  4612. setSelectionNoUndo(doc, sel, options);
  4613. } else {
  4614. setSelection(doc, sel, options);
  4615. }
  4616. }
  4617. // Set a new selection.
  4618. function setSelection(doc, sel, options) {
  4619. setSelectionNoUndo(doc, sel, options);
  4620. addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options);
  4621. }
  4622. function setSelectionNoUndo(doc, sel, options) {
  4623. if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
  4624. { sel = filterSelectionChange(doc, sel, options); }
  4625. var bias = options && options.bias ||
  4626. (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
  4627. setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
  4628. if (!(options && options.scroll === false) && doc.cm)
  4629. { ensureCursorVisible(doc.cm); }
  4630. }
  4631. function setSelectionInner(doc, sel) {
  4632. if (sel.equals(doc.sel)) { return }
  4633. doc.sel = sel;
  4634. if (doc.cm) {
  4635. doc.cm.curOp.updateInput = 1;
  4636. doc.cm.curOp.selectionChanged = true;
  4637. signalCursorActivity(doc.cm);
  4638. }
  4639. signalLater(doc, "cursorActivity", doc);
  4640. }
  4641. // Verify that the selection does not partially select any atomic
  4642. // marked ranges.
  4643. function reCheckSelection(doc) {
  4644. setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false));
  4645. }
  4646. // Return a selection that does not partially select any atomic
  4647. // ranges.
  4648. function skipAtomicInSelection(doc, sel, bias, mayClear) {
  4649. var out;
  4650. for (var i = 0; i < sel.ranges.length; i++) {
  4651. var range = sel.ranges[i];
  4652. var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i];
  4653. var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear);
  4654. var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear);
  4655. if (out || newAnchor != range.anchor || newHead != range.head) {
  4656. if (!out) { out = sel.ranges.slice(0, i); }
  4657. out[i] = new Range(newAnchor, newHead);
  4658. }
  4659. }
  4660. return out ? normalizeSelection(doc.cm, out, sel.primIndex) : sel
  4661. }
  4662. function skipAtomicInner(doc, pos, oldPos, dir, mayClear) {
  4663. var line = getLine(doc, pos.line);
  4664. if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {
  4665. var sp = line.markedSpans[i], m = sp.marker;
  4666. // Determine if we should prevent the cursor being placed to the left/right of an atomic marker
  4667. // Historically this was determined using the inclusiveLeft/Right option, but the new way to control it
  4668. // is with selectLeft/Right
  4669. var preventCursorLeft = ("selectLeft" in m) ? !m.selectLeft : m.inclusiveLeft;
  4670. var preventCursorRight = ("selectRight" in m) ? !m.selectRight : m.inclusiveRight;
  4671. if ((sp.from == null || (preventCursorLeft ? sp.from <= pos.ch : sp.from < pos.ch)) &&
  4672. (sp.to == null || (preventCursorRight ? sp.to >= pos.ch : sp.to > pos.ch))) {
  4673. if (mayClear) {
  4674. signal(m, "beforeCursorEnter");
  4675. if (m.explicitlyCleared) {
  4676. if (!line.markedSpans) { break }
  4677. else {--i; continue}
  4678. }
  4679. }
  4680. if (!m.atomic) { continue }
  4681. if (oldPos) {
  4682. var near = m.find(dir < 0 ? 1 : -1), diff = (void 0);
  4683. if (dir < 0 ? preventCursorRight : preventCursorLeft)
  4684. { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); }
  4685. if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0))
  4686. { return skipAtomicInner(doc, near, pos, dir, mayClear) }
  4687. }
  4688. var far = m.find(dir < 0 ? -1 : 1);
  4689. if (dir < 0 ? preventCursorLeft : preventCursorRight)
  4690. { far = movePos(doc, far, dir, far.line == pos.line ? line : null); }
  4691. return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null
  4692. }
  4693. } }
  4694. return pos
  4695. }
  4696. // Ensure a given position is not inside an atomic range.
  4697. function skipAtomic(doc, pos, oldPos, bias, mayClear) {
  4698. var dir = bias || 1;
  4699. var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) ||
  4700. (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) ||
  4701. skipAtomicInner(doc, pos, oldPos, -dir, mayClear) ||
  4702. (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true));
  4703. if (!found) {
  4704. doc.cantEdit = true;
  4705. return Pos(doc.first, 0)
  4706. }
  4707. return found
  4708. }
  4709. function movePos(doc, pos, dir, line) {
  4710. if (dir < 0 && pos.ch == 0) {
  4711. if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) }
  4712. else { return null }
  4713. } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) {
  4714. if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) }
  4715. else { return null }
  4716. } else {
  4717. return new Pos(pos.line, pos.ch + dir)
  4718. }
  4719. }
  4720. function selectAll(cm) {
  4721. cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);
  4722. }
  4723. // UPDATING
  4724. // Allow "beforeChange" event handlers to influence a change
  4725. function filterChange(doc, change, update) {
  4726. var obj = {
  4727. canceled: false,
  4728. from: change.from,
  4729. to: change.to,
  4730. text: change.text,
  4731. origin: change.origin,
  4732. cancel: function () { return obj.canceled = true; }
  4733. };
  4734. if (update) { obj.update = function (from, to, text, origin) {
  4735. if (from) { obj.from = clipPos(doc, from); }
  4736. if (to) { obj.to = clipPos(doc, to); }
  4737. if (text) { obj.text = text; }
  4738. if (origin !== undefined) { obj.origin = origin; }
  4739. }; }
  4740. signal(doc, "beforeChange", doc, obj);
  4741. if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj); }
  4742. if (obj.canceled) {
  4743. if (doc.cm) { doc.cm.curOp.updateInput = 2; }
  4744. return null
  4745. }
  4746. return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin}
  4747. }
  4748. // Apply a change to a document, and add it to the document's
  4749. // history, and propagating it to all linked documents.
  4750. function makeChange(doc, change, ignoreReadOnly) {
  4751. if (doc.cm) {
  4752. if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) }
  4753. if (doc.cm.state.suppressEdits) { return }
  4754. }
  4755. if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
  4756. change = filterChange(doc, change, true);
  4757. if (!change) { return }
  4758. }
  4759. // Possibly split or suppress the update based on the presence
  4760. // of read-only spans in its range.
  4761. var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to);
  4762. if (split) {
  4763. for (var i = split.length - 1; i >= 0; --i)
  4764. { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text, origin: change.origin}); }
  4765. } else {
  4766. makeChangeInner(doc, change);
  4767. }
  4768. }
  4769. function makeChangeInner(doc, change) {
  4770. if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return }
  4771. var selAfter = computeSelAfterChange(doc, change);
  4772. addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN);
  4773. makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change));
  4774. var rebased = [];
  4775. linkedDocs(doc, function (doc, sharedHist) {
  4776. if (!sharedHist && indexOf(rebased, doc.history) == -1) {
  4777. rebaseHist(doc.history, change);
  4778. rebased.push(doc.history);
  4779. }
  4780. makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change));
  4781. });
  4782. }
  4783. // Revert a change stored in a document's history.
  4784. function makeChangeFromHistory(doc, type, allowSelectionOnly) {
  4785. var suppress = doc.cm && doc.cm.state.suppressEdits;
  4786. if (suppress && !allowSelectionOnly) { return }
  4787. var hist = doc.history, event, selAfter = doc.sel;
  4788. var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done;
  4789. // Verify that there is a useable event (so that ctrl-z won't
  4790. // needlessly clear selection events)
  4791. var i = 0;
  4792. for (; i < source.length; i++) {
  4793. event = source[i];
  4794. if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
  4795. { break }
  4796. }
  4797. if (i == source.length) { return }
  4798. hist.lastOrigin = hist.lastSelOrigin = null;
  4799. for (;;) {
  4800. event = source.pop();
  4801. if (event.ranges) {
  4802. pushSelectionToHistory(event, dest);
  4803. if (allowSelectionOnly && !event.equals(doc.sel)) {
  4804. setSelection(doc, event, {clearRedo: false});
  4805. return
  4806. }
  4807. selAfter = event;
  4808. } else if (suppress) {
  4809. source.push(event);
  4810. return
  4811. } else { break }
  4812. }
  4813. // Build up a reverse change object to add to the opposite history
  4814. // stack (redo when undoing, and vice versa).
  4815. var antiChanges = [];
  4816. pushSelectionToHistory(selAfter, dest);
  4817. dest.push({changes: antiChanges, generation: hist.generation});
  4818. hist.generation = event.generation || ++hist.maxGeneration;
  4819. var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange");
  4820. var loop = function ( i ) {
  4821. var change = event.changes[i];
  4822. change.origin = type;
  4823. if (filter && !filterChange(doc, change, false)) {
  4824. source.length = 0;
  4825. return {}
  4826. }
  4827. antiChanges.push(historyChangeFromChange(doc, change));
  4828. var after = i ? computeSelAfterChange(doc, change) : lst(source);
  4829. makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change));
  4830. if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); }
  4831. var rebased = [];
  4832. // Propagate to the linked documents
  4833. linkedDocs(doc, function (doc, sharedHist) {
  4834. if (!sharedHist && indexOf(rebased, doc.history) == -1) {
  4835. rebaseHist(doc.history, change);
  4836. rebased.push(doc.history);
  4837. }
  4838. makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change));
  4839. });
  4840. };
  4841. for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) {
  4842. var returned = loop( i$1 );
  4843. if ( returned ) return returned.v;
  4844. }
  4845. }
  4846. // Sub-views need their line numbers shifted when text is added
  4847. // above or below them in the parent document.
  4848. function shiftDoc(doc, distance) {
  4849. if (distance == 0) { return }
  4850. doc.first += distance;
  4851. doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range(
  4852. Pos(range.anchor.line + distance, range.anchor.ch),
  4853. Pos(range.head.line + distance, range.head.ch)
  4854. ); }), doc.sel.primIndex);
  4855. if (doc.cm) {
  4856. regChange(doc.cm, doc.first, doc.first - distance, distance);
  4857. for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
  4858. { regLineChange(doc.cm, l, "gutter"); }
  4859. }
  4860. }
  4861. // More lower-level change function, handling only a single document
  4862. // (not linked ones).
  4863. function makeChangeSingleDoc(doc, change, selAfter, spans) {
  4864. if (doc.cm && !doc.cm.curOp)
  4865. { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) }
  4866. if (change.to.line < doc.first) {
  4867. shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line));
  4868. return
  4869. }
  4870. if (change.from.line > doc.lastLine()) { return }
  4871. // Clip the change to the size of this doc
  4872. if (change.from.line < doc.first) {
  4873. var shift = change.text.length - 1 - (doc.first - change.from.line);
  4874. shiftDoc(doc, shift);
  4875. change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
  4876. text: [lst(change.text)], origin: change.origin};
  4877. }
  4878. var last = doc.lastLine();
  4879. if (change.to.line > last) {
  4880. change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
  4881. text: [change.text[0]], origin: change.origin};
  4882. }
  4883. change.removed = getBetween(doc, change.from, change.to);
  4884. if (!selAfter) { selAfter = computeSelAfterChange(doc, change); }
  4885. if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans); }
  4886. else { updateDoc(doc, change, spans); }
  4887. setSelectionNoUndo(doc, selAfter, sel_dontScroll);
  4888. if (doc.cantEdit && skipAtomic(doc, Pos(doc.firstLine(), 0)))
  4889. { doc.cantEdit = false; }
  4890. }
  4891. // Handle the interaction of a change to a document with the editor
  4892. // that this document is part of.
  4893. function makeChangeSingleDocInEditor(cm, change, spans) {
  4894. var doc = cm.doc, display = cm.display, from = change.from, to = change.to;
  4895. var recomputeMaxLength = false, checkWidthStart = from.line;
  4896. if (!cm.options.lineWrapping) {
  4897. checkWidthStart = lineNo(visualLine(getLine(doc, from.line)));
  4898. doc.iter(checkWidthStart, to.line + 1, function (line) {
  4899. if (line == display.maxLine) {
  4900. recomputeMaxLength = true;
  4901. return true
  4902. }
  4903. });
  4904. }
  4905. if (doc.sel.contains(change.from, change.to) > -1)
  4906. { signalCursorActivity(cm); }
  4907. updateDoc(doc, change, spans, estimateHeight(cm));
  4908. if (!cm.options.lineWrapping) {
  4909. doc.iter(checkWidthStart, from.line + change.text.length, function (line) {
  4910. var len = lineLength(line);
  4911. if (len > display.maxLineLength) {
  4912. display.maxLine = line;
  4913. display.maxLineLength = len;
  4914. display.maxLineChanged = true;
  4915. recomputeMaxLength = false;
  4916. }
  4917. });
  4918. if (recomputeMaxLength) { cm.curOp.updateMaxLine = true; }
  4919. }
  4920. retreatFrontier(doc, from.line);
  4921. startWorker(cm, 400);
  4922. var lendiff = change.text.length - (to.line - from.line) - 1;
  4923. // Remember that these lines changed, for updating the display
  4924. if (change.full)
  4925. { regChange(cm); }
  4926. else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))
  4927. { regLineChange(cm, from.line, "text"); }
  4928. else
  4929. { regChange(cm, from.line, to.line + 1, lendiff); }
  4930. var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change");
  4931. if (changeHandler || changesHandler) {
  4932. var obj = {
  4933. from: from, to: to,
  4934. text: change.text,
  4935. removed: change.removed,
  4936. origin: change.origin
  4937. };
  4938. if (changeHandler) { signalLater(cm, "change", cm, obj); }
  4939. if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); }
  4940. }
  4941. cm.display.selForContextMenu = null;
  4942. }
  4943. function replaceRange(doc, code, from, to, origin) {
  4944. var assign;
  4945. if (!to) { to = from; }
  4946. if (cmp(to, from) < 0) { (assign = [to, from], from = assign[0], to = assign[1]); }
  4947. if (typeof code == "string") { code = doc.splitLines(code); }
  4948. makeChange(doc, {from: from, to: to, text: code, origin: origin});
  4949. }
  4950. // Rebasing/resetting history to deal with externally-sourced changes
  4951. function rebaseHistSelSingle(pos, from, to, diff) {
  4952. if (to < pos.line) {
  4953. pos.line += diff;
  4954. } else if (from < pos.line) {
  4955. pos.line = from;
  4956. pos.ch = 0;
  4957. }
  4958. }
  4959. // Tries to rebase an array of history events given a change in the
  4960. // document. If the change touches the same lines as the event, the
  4961. // event, and everything 'behind' it, is discarded. If the change is
  4962. // before the event, the event's positions are updated. Uses a
  4963. // copy-on-write scheme for the positions, to avoid having to
  4964. // reallocate them all on every rebase, but also avoid problems with
  4965. // shared position objects being unsafely updated.
  4966. function rebaseHistArray(array, from, to, diff) {
  4967. for (var i = 0; i < array.length; ++i) {
  4968. var sub = array[i], ok = true;
  4969. if (sub.ranges) {
  4970. if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; }
  4971. for (var j = 0; j < sub.ranges.length; j++) {
  4972. rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff);
  4973. rebaseHistSelSingle(sub.ranges[j].head, from, to, diff);
  4974. }
  4975. continue
  4976. }
  4977. for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) {
  4978. var cur = sub.changes[j$1];
  4979. if (to < cur.from.line) {
  4980. cur.from = Pos(cur.from.line + diff, cur.from.ch);
  4981. cur.to = Pos(cur.to.line + diff, cur.to.ch);
  4982. } else if (from <= cur.to.line) {
  4983. ok = false;
  4984. break
  4985. }
  4986. }
  4987. if (!ok) {
  4988. array.splice(0, i + 1);
  4989. i = 0;
  4990. }
  4991. }
  4992. }
  4993. function rebaseHist(hist, change) {
  4994. var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1;
  4995. rebaseHistArray(hist.done, from, to, diff);
  4996. rebaseHistArray(hist.undone, from, to, diff);
  4997. }
  4998. // Utility for applying a change to a line by handle or number,
  4999. // returning the number and optionally registering the line as
  5000. // changed.
  5001. function changeLine(doc, handle, changeType, op) {
  5002. var no = handle, line = handle;
  5003. if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)); }
  5004. else { no = lineNo(handle); }
  5005. if (no == null) { return null }
  5006. if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType); }
  5007. return line
  5008. }
  5009. // The document is represented as a BTree consisting of leaves, with
  5010. // chunk of lines in them, and branches, with up to ten leaves or
  5011. // other branch nodes below them. The top node is always a branch
  5012. // node, and is the document object itself (meaning it has
  5013. // additional methods and properties).
  5014. //
  5015. // All nodes have parent links. The tree is used both to go from
  5016. // line numbers to line objects, and to go from objects to numbers.
  5017. // It also indexes by height, and is used to convert between height
  5018. // and line object, and to find the total height of the document.
  5019. //
  5020. // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html
  5021. function LeafChunk(lines) {
  5022. this.lines = lines;
  5023. this.parent = null;
  5024. var height = 0;
  5025. for (var i = 0; i < lines.length; ++i) {
  5026. lines[i].parent = this;
  5027. height += lines[i].height;
  5028. }
  5029. this.height = height;
  5030. }
  5031. LeafChunk.prototype = {
  5032. chunkSize: function() { return this.lines.length },
  5033. // Remove the n lines at offset 'at'.
  5034. removeInner: function(at, n) {
  5035. for (var i = at, e = at + n; i < e; ++i) {
  5036. var line = this.lines[i];
  5037. this.height -= line.height;
  5038. cleanUpLine(line);
  5039. signalLater(line, "delete");
  5040. }
  5041. this.lines.splice(at, n);
  5042. },
  5043. // Helper used to collapse a small branch into a single leaf.
  5044. collapse: function(lines) {
  5045. lines.push.apply(lines, this.lines);
  5046. },
  5047. // Insert the given array of lines at offset 'at', count them as
  5048. // having the given height.
  5049. insertInner: function(at, lines, height) {
  5050. this.height += height;
  5051. this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
  5052. for (var i = 0; i < lines.length; ++i) { lines[i].parent = this; }
  5053. },
  5054. // Used to iterate over a part of the tree.
  5055. iterN: function(at, n, op) {
  5056. for (var e = at + n; at < e; ++at)
  5057. { if (op(this.lines[at])) { return true } }
  5058. }
  5059. };
  5060. function BranchChunk(children) {
  5061. this.children = children;
  5062. var size = 0, height = 0;
  5063. for (var i = 0; i < children.length; ++i) {
  5064. var ch = children[i];
  5065. size += ch.chunkSize(); height += ch.height;
  5066. ch.parent = this;
  5067. }
  5068. this.size = size;
  5069. this.height = height;
  5070. this.parent = null;
  5071. }
  5072. BranchChunk.prototype = {
  5073. chunkSize: function() { return this.size },
  5074. removeInner: function(at, n) {
  5075. this.size -= n;
  5076. for (var i = 0; i < this.children.length; ++i) {
  5077. var child = this.children[i], sz = child.chunkSize();
  5078. if (at < sz) {
  5079. var rm = Math.min(n, sz - at), oldHeight = child.height;
  5080. child.removeInner(at, rm);
  5081. this.height -= oldHeight - child.height;
  5082. if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
  5083. if ((n -= rm) == 0) { break }
  5084. at = 0;
  5085. } else { at -= sz; }
  5086. }
  5087. // If the result is smaller than 25 lines, ensure that it is a
  5088. // single leaf node.
  5089. if (this.size - n < 25 &&
  5090. (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {
  5091. var lines = [];
  5092. this.collapse(lines);
  5093. this.children = [new LeafChunk(lines)];
  5094. this.children[0].parent = this;
  5095. }
  5096. },
  5097. collapse: function(lines) {
  5098. for (var i = 0; i < this.children.length; ++i) { this.children[i].collapse(lines); }
  5099. },
  5100. insertInner: function(at, lines, height) {
  5101. this.size += lines.length;
  5102. this.height += height;
  5103. for (var i = 0; i < this.children.length; ++i) {
  5104. var child = this.children[i], sz = child.chunkSize();
  5105. if (at <= sz) {
  5106. child.insertInner(at, lines, height);
  5107. if (child.lines && child.lines.length > 50) {
  5108. // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced.
  5109. // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest.
  5110. var remaining = child.lines.length % 25 + 25;
  5111. for (var pos = remaining; pos < child.lines.length;) {
  5112. var leaf = new LeafChunk(child.lines.slice(pos, pos += 25));
  5113. child.height -= leaf.height;
  5114. this.children.splice(++i, 0, leaf);
  5115. leaf.parent = this;
  5116. }
  5117. child.lines = child.lines.slice(0, remaining);
  5118. this.maybeSpill();
  5119. }
  5120. break
  5121. }
  5122. at -= sz;
  5123. }
  5124. },
  5125. // When a node has grown, check whether it should be split.
  5126. maybeSpill: function() {
  5127. if (this.children.length <= 10) { return }
  5128. var me = this;
  5129. do {
  5130. var spilled = me.children.splice(me.children.length - 5, 5);
  5131. var sibling = new BranchChunk(spilled);
  5132. if (!me.parent) { // Become the parent node
  5133. var copy = new BranchChunk(me.children);
  5134. copy.parent = me;
  5135. me.children = [copy, sibling];
  5136. me = copy;
  5137. } else {
  5138. me.size -= sibling.size;
  5139. me.height -= sibling.height;
  5140. var myIndex = indexOf(me.parent.children, me);
  5141. me.parent.children.splice(myIndex + 1, 0, sibling);
  5142. }
  5143. sibling.parent = me.parent;
  5144. } while (me.children.length > 10)
  5145. me.parent.maybeSpill();
  5146. },
  5147. iterN: function(at, n, op) {
  5148. for (var i = 0; i < this.children.length; ++i) {
  5149. var child = this.children[i], sz = child.chunkSize();
  5150. if (at < sz) {
  5151. var used = Math.min(n, sz - at);
  5152. if (child.iterN(at, used, op)) { return true }
  5153. if ((n -= used) == 0) { break }
  5154. at = 0;
  5155. } else { at -= sz; }
  5156. }
  5157. }
  5158. };
  5159. // Line widgets are block elements displayed above or below a line.
  5160. var LineWidget = function(doc, node, options) {
  5161. if (options) { for (var opt in options) { if (options.hasOwnProperty(opt))
  5162. { this[opt] = options[opt]; } } }
  5163. this.doc = doc;
  5164. this.node = node;
  5165. };
  5166. LineWidget.prototype.clear = function () {
  5167. var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
  5168. if (no == null || !ws) { return }
  5169. for (var i = 0; i < ws.length; ++i) { if (ws[i] == this) { ws.splice(i--, 1); } }
  5170. if (!ws.length) { line.widgets = null; }
  5171. var height = widgetHeight(this);
  5172. updateLineHeight(line, Math.max(0, line.height - height));
  5173. if (cm) {
  5174. runInOp(cm, function () {
  5175. adjustScrollWhenAboveVisible(cm, line, -height);
  5176. regLineChange(cm, no, "widget");
  5177. });
  5178. signalLater(cm, "lineWidgetCleared", cm, this, no);
  5179. }
  5180. };
  5181. LineWidget.prototype.changed = function () {
  5182. var this$1 = this;
  5183. var oldH = this.height, cm = this.doc.cm, line = this.line;
  5184. this.height = null;
  5185. var diff = widgetHeight(this) - oldH;
  5186. if (!diff) { return }
  5187. if (!lineIsHidden(this.doc, line)) { updateLineHeight(line, line.height + diff); }
  5188. if (cm) {
  5189. runInOp(cm, function () {
  5190. cm.curOp.forceUpdate = true;
  5191. adjustScrollWhenAboveVisible(cm, line, diff);
  5192. signalLater(cm, "lineWidgetChanged", cm, this$1, lineNo(line));
  5193. });
  5194. }
  5195. };
  5196. eventMixin(LineWidget);
  5197. function adjustScrollWhenAboveVisible(cm, line, diff) {
  5198. if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
  5199. { addToScrollTop(cm, diff); }
  5200. }
  5201. function addLineWidget(doc, handle, node, options) {
  5202. var widget = new LineWidget(doc, node, options);
  5203. var cm = doc.cm;
  5204. if (cm && widget.noHScroll) { cm.display.alignWidgets = true; }
  5205. changeLine(doc, handle, "widget", function (line) {
  5206. var widgets = line.widgets || (line.widgets = []);
  5207. if (widget.insertAt == null) { widgets.push(widget); }
  5208. else { widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); }
  5209. widget.line = line;
  5210. if (cm && !lineIsHidden(doc, line)) {
  5211. var aboveVisible = heightAtLine(line) < doc.scrollTop;
  5212. updateLineHeight(line, line.height + widgetHeight(widget));
  5213. if (aboveVisible) { addToScrollTop(cm, widget.height); }
  5214. cm.curOp.forceUpdate = true;
  5215. }
  5216. return true
  5217. });
  5218. if (cm) { signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)); }
  5219. return widget
  5220. }
  5221. // TEXTMARKERS
  5222. // Created with markText and setBookmark methods. A TextMarker is a
  5223. // handle that can be used to clear or find a marked position in the
  5224. // document. Line objects hold arrays (markedSpans) containing
  5225. // {from, to, marker} object pointing to such marker objects, and
  5226. // indicating that such a marker is present on that line. Multiple
  5227. // lines may point to the same marker when it spans across lines.
  5228. // The spans will have null for their from/to properties when the
  5229. // marker continues beyond the start/end of the line. Markers have
  5230. // links back to the lines they currently touch.
  5231. // Collapsed markers have unique ids, in order to be able to order
  5232. // them, which is needed for uniquely determining an outer marker
  5233. // when they overlap (they may nest, but not partially overlap).
  5234. var nextMarkerId = 0;
  5235. var TextMarker = function(doc, type) {
  5236. this.lines = [];
  5237. this.type = type;
  5238. this.doc = doc;
  5239. this.id = ++nextMarkerId;
  5240. };
  5241. // Clear the marker.
  5242. TextMarker.prototype.clear = function () {
  5243. if (this.explicitlyCleared) { return }
  5244. var cm = this.doc.cm, withOp = cm && !cm.curOp;
  5245. if (withOp) { startOperation(cm); }
  5246. if (hasHandler(this, "clear")) {
  5247. var found = this.find();
  5248. if (found) { signalLater(this, "clear", found.from, found.to); }
  5249. }
  5250. var min = null, max = null;
  5251. for (var i = 0; i < this.lines.length; ++i) {
  5252. var line = this.lines[i];
  5253. var span = getMarkedSpanFor(line.markedSpans, this);
  5254. if (cm && !this.collapsed) { regLineChange(cm, lineNo(line), "text"); }
  5255. else if (cm) {
  5256. if (span.to != null) { max = lineNo(line); }
  5257. if (span.from != null) { min = lineNo(line); }
  5258. }
  5259. line.markedSpans = removeMarkedSpan(line.markedSpans, span);
  5260. if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm)
  5261. { updateLineHeight(line, textHeight(cm.display)); }
  5262. }
  5263. if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) {
  5264. var visual = visualLine(this.lines[i$1]), len = lineLength(visual);
  5265. if (len > cm.display.maxLineLength) {
  5266. cm.display.maxLine = visual;
  5267. cm.display.maxLineLength = len;
  5268. cm.display.maxLineChanged = true;
  5269. }
  5270. } }
  5271. if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1); }
  5272. this.lines.length = 0;
  5273. this.explicitlyCleared = true;
  5274. if (this.atomic && this.doc.cantEdit) {
  5275. this.doc.cantEdit = false;
  5276. if (cm) { reCheckSelection(cm.doc); }
  5277. }
  5278. if (cm) { signalLater(cm, "markerCleared", cm, this, min, max); }
  5279. if (withOp) { endOperation(cm); }
  5280. if (this.parent) { this.parent.clear(); }
  5281. };
  5282. // Find the position of the marker in the document. Returns a {from,
  5283. // to} object by default. Side can be passed to get a specific side
  5284. // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the
  5285. // Pos objects returned contain a line object, rather than a line
  5286. // number (used to prevent looking up the same line twice).
  5287. TextMarker.prototype.find = function (side, lineObj) {
  5288. if (side == null && this.type == "bookmark") { side = 1; }
  5289. var from, to;
  5290. for (var i = 0; i < this.lines.length; ++i) {
  5291. var line = this.lines[i];
  5292. var span = getMarkedSpanFor(line.markedSpans, this);
  5293. if (span.from != null) {
  5294. from = Pos(lineObj ? line : lineNo(line), span.from);
  5295. if (side == -1) { return from }
  5296. }
  5297. if (span.to != null) {
  5298. to = Pos(lineObj ? line : lineNo(line), span.to);
  5299. if (side == 1) { return to }
  5300. }
  5301. }
  5302. return from && {from: from, to: to}
  5303. };
  5304. // Signals that the marker's widget changed, and surrounding layout
  5305. // should be recomputed.
  5306. TextMarker.prototype.changed = function () {
  5307. var this$1 = this;
  5308. var pos = this.find(-1, true), widget = this, cm = this.doc.cm;
  5309. if (!pos || !cm) { return }
  5310. runInOp(cm, function () {
  5311. var line = pos.line, lineN = lineNo(pos.line);
  5312. var view = findViewForLine(cm, lineN);
  5313. if (view) {
  5314. clearLineMeasurementCacheFor(view);
  5315. cm.curOp.selectionChanged = cm.curOp.forceUpdate = true;
  5316. }
  5317. cm.curOp.updateMaxLine = true;
  5318. if (!lineIsHidden(widget.doc, line) && widget.height != null) {
  5319. var oldHeight = widget.height;
  5320. widget.height = null;
  5321. var dHeight = widgetHeight(widget) - oldHeight;
  5322. if (dHeight)
  5323. { updateLineHeight(line, line.height + dHeight); }
  5324. }
  5325. signalLater(cm, "markerChanged", cm, this$1);
  5326. });
  5327. };
  5328. TextMarker.prototype.attachLine = function (line) {
  5329. if (!this.lines.length && this.doc.cm) {
  5330. var op = this.doc.cm.curOp;
  5331. if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
  5332. { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); }
  5333. }
  5334. this.lines.push(line);
  5335. };
  5336. TextMarker.prototype.detachLine = function (line) {
  5337. this.lines.splice(indexOf(this.lines, line), 1);
  5338. if (!this.lines.length && this.doc.cm) {
  5339. var op = this.doc.cm.curOp
  5340. ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this);
  5341. }
  5342. };
  5343. eventMixin(TextMarker);
  5344. // Create a marker, wire it up to the right lines, and
  5345. function markText(doc, from, to, options, type) {
  5346. // Shared markers (across linked documents) are handled separately
  5347. // (markTextShared will call out to this again, once per
  5348. // document).
  5349. if (options && options.shared) { return markTextShared(doc, from, to, options, type) }
  5350. // Ensure we are in an operation.
  5351. if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) }
  5352. var marker = new TextMarker(doc, type), diff = cmp(from, to);
  5353. if (options) { copyObj(options, marker, false); }
  5354. // Don't connect empty markers unless clearWhenEmpty is false
  5355. if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
  5356. { return marker }
  5357. if (marker.replacedWith) {
  5358. // Showing up as a widget implies collapsed (widget replaces text)
  5359. marker.collapsed = true;
  5360. marker.widgetNode = eltP("span", [marker.replacedWith], "CodeMirror-widget");
  5361. if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true"); }
  5362. if (options.insertLeft) { marker.widgetNode.insertLeft = true; }
  5363. }
  5364. if (marker.collapsed) {
  5365. if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
  5366. from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
  5367. { throw new Error("Inserting collapsed marker partially overlapping an existing one") }
  5368. seeCollapsedSpans();
  5369. }
  5370. if (marker.addToHistory)
  5371. { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); }
  5372. var curLine = from.line, cm = doc.cm, updateMaxLine;
  5373. doc.iter(curLine, to.line + 1, function (line) {
  5374. if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
  5375. { updateMaxLine = true; }
  5376. if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); }
  5377. addMarkedSpan(line, new MarkedSpan(marker,
  5378. curLine == from.line ? from.ch : null,
  5379. curLine == to.line ? to.ch : null));
  5380. ++curLine;
  5381. });
  5382. // lineIsHidden depends on the presence of the spans, so needs a second pass
  5383. if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) {
  5384. if (lineIsHidden(doc, line)) { updateLineHeight(line, 0); }
  5385. }); }
  5386. if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }); }
  5387. if (marker.readOnly) {
  5388. seeReadOnlySpans();
  5389. if (doc.history.done.length || doc.history.undone.length)
  5390. { doc.clearHistory(); }
  5391. }
  5392. if (marker.collapsed) {
  5393. marker.id = ++nextMarkerId;
  5394. marker.atomic = true;
  5395. }
  5396. if (cm) {
  5397. // Sync editor state
  5398. if (updateMaxLine) { cm.curOp.updateMaxLine = true; }
  5399. if (marker.collapsed)
  5400. { regChange(cm, from.line, to.line + 1); }
  5401. else if (marker.className || marker.startStyle || marker.endStyle || marker.css ||
  5402. marker.attributes || marker.title)
  5403. { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text"); } }
  5404. if (marker.atomic) { reCheckSelection(cm.doc); }
  5405. signalLater(cm, "markerAdded", cm, marker);
  5406. }
  5407. return marker
  5408. }
  5409. // SHARED TEXTMARKERS
  5410. // A shared marker spans multiple linked documents. It is
  5411. // implemented as a meta-marker-object controlling multiple normal
  5412. // markers.
  5413. var SharedTextMarker = function(markers, primary) {
  5414. this.markers = markers;
  5415. this.primary = primary;
  5416. for (var i = 0; i < markers.length; ++i)
  5417. { markers[i].parent = this; }
  5418. };
  5419. SharedTextMarker.prototype.clear = function () {
  5420. if (this.explicitlyCleared) { return }
  5421. this.explicitlyCleared = true;
  5422. for (var i = 0; i < this.markers.length; ++i)
  5423. { this.markers[i].clear(); }
  5424. signalLater(this, "clear");
  5425. };
  5426. SharedTextMarker.prototype.find = function (side, lineObj) {
  5427. return this.primary.find(side, lineObj)
  5428. };
  5429. eventMixin(SharedTextMarker);
  5430. function markTextShared(doc, from, to, options, type) {
  5431. options = copyObj(options);
  5432. options.shared = false;
  5433. var markers = [markText(doc, from, to, options, type)], primary = markers[0];
  5434. var widget = options.widgetNode;
  5435. linkedDocs(doc, function (doc) {
  5436. if (widget) { options.widgetNode = widget.cloneNode(true); }
  5437. markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type));
  5438. for (var i = 0; i < doc.linked.length; ++i)
  5439. { if (doc.linked[i].isParent) { return } }
  5440. primary = lst(markers);
  5441. });
  5442. return new SharedTextMarker(markers, primary)
  5443. }
  5444. function findSharedMarkers(doc) {
  5445. return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; })
  5446. }
  5447. function copySharedMarkers(doc, markers) {
  5448. for (var i = 0; i < markers.length; i++) {
  5449. var marker = markers[i], pos = marker.find();
  5450. var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to);
  5451. if (cmp(mFrom, mTo)) {
  5452. var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type);
  5453. marker.markers.push(subMark);
  5454. subMark.parent = marker;
  5455. }
  5456. }
  5457. }
  5458. function detachSharedMarkers(markers) {
  5459. var loop = function ( i ) {
  5460. var marker = markers[i], linked = [marker.primary.doc];
  5461. linkedDocs(marker.primary.doc, function (d) { return linked.push(d); });
  5462. for (var j = 0; j < marker.markers.length; j++) {
  5463. var subMarker = marker.markers[j];
  5464. if (indexOf(linked, subMarker.doc) == -1) {
  5465. subMarker.parent = null;
  5466. marker.markers.splice(j--, 1);
  5467. }
  5468. }
  5469. };
  5470. for (var i = 0; i < markers.length; i++) loop( i );
  5471. }
  5472. var nextDocId = 0;
  5473. var Doc = function(text, mode, firstLine, lineSep, direction) {
  5474. if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep, direction) }
  5475. if (firstLine == null) { firstLine = 0; }
  5476. BranchChunk.call(this, [new LeafChunk([new Line("", null)])]);
  5477. this.first = firstLine;
  5478. this.scrollTop = this.scrollLeft = 0;
  5479. this.cantEdit = false;
  5480. this.cleanGeneration = 1;
  5481. this.modeFrontier = this.highlightFrontier = firstLine;
  5482. var start = Pos(firstLine, 0);
  5483. this.sel = simpleSelection(start);
  5484. this.history = new History(null);
  5485. this.id = ++nextDocId;
  5486. this.modeOption = mode;
  5487. this.lineSep = lineSep;
  5488. this.direction = (direction == "rtl") ? "rtl" : "ltr";
  5489. this.extend = false;
  5490. if (typeof text == "string") { text = this.splitLines(text); }
  5491. updateDoc(this, {from: start, to: start, text: text});
  5492. setSelection(this, simpleSelection(start), sel_dontScroll);
  5493. };
  5494. Doc.prototype = createObj(BranchChunk.prototype, {
  5495. constructor: Doc,
  5496. // Iterate over the document. Supports two forms -- with only one
  5497. // argument, it calls that for each line in the document. With
  5498. // three, it iterates over the range given by the first two (with
  5499. // the second being non-inclusive).
  5500. iter: function(from, to, op) {
  5501. if (op) { this.iterN(from - this.first, to - from, op); }
  5502. else { this.iterN(this.first, this.first + this.size, from); }
  5503. },
  5504. // Non-public interface for adding and removing lines.
  5505. insert: function(at, lines) {
  5506. var height = 0;
  5507. for (var i = 0; i < lines.length; ++i) { height += lines[i].height; }
  5508. this.insertInner(at - this.first, lines, height);
  5509. },
  5510. remove: function(at, n) { this.removeInner(at - this.first, n); },
  5511. // From here, the methods are part of the public interface. Most
  5512. // are also available from CodeMirror (editor) instances.
  5513. getValue: function(lineSep) {
  5514. var lines = getLines(this, this.first, this.first + this.size);
  5515. if (lineSep === false) { return lines }
  5516. return lines.join(lineSep || this.lineSeparator())
  5517. },
  5518. setValue: docMethodOp(function(code) {
  5519. var top = Pos(this.first, 0), last = this.first + this.size - 1;
  5520. makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
  5521. text: this.splitLines(code), origin: "setValue", full: true}, true);
  5522. if (this.cm) { scrollToCoords(this.cm, 0, 0); }
  5523. setSelection(this, simpleSelection(top), sel_dontScroll);
  5524. }),
  5525. replaceRange: function(code, from, to, origin) {
  5526. from = clipPos(this, from);
  5527. to = to ? clipPos(this, to) : from;
  5528. replaceRange(this, code, from, to, origin);
  5529. },
  5530. getRange: function(from, to, lineSep) {
  5531. var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
  5532. if (lineSep === false) { return lines }
  5533. return lines.join(lineSep || this.lineSeparator())
  5534. },
  5535. getLine: function(line) {var l = this.getLineHandle(line); return l && l.text},
  5536. getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }},
  5537. getLineNumber: function(line) {return lineNo(line)},
  5538. getLineHandleVisualStart: function(line) {
  5539. if (typeof line == "number") { line = getLine(this, line); }
  5540. return visualLine(line)
  5541. },
  5542. lineCount: function() {return this.size},
  5543. firstLine: function() {return this.first},
  5544. lastLine: function() {return this.first + this.size - 1},
  5545. clipPos: function(pos) {return clipPos(this, pos)},
  5546. getCursor: function(start) {
  5547. var range = this.sel.primary(), pos;
  5548. if (start == null || start == "head") { pos = range.head; }
  5549. else if (start == "anchor") { pos = range.anchor; }
  5550. else if (start == "end" || start == "to" || start === false) { pos = range.to(); }
  5551. else { pos = range.from(); }
  5552. return pos
  5553. },
  5554. listSelections: function() { return this.sel.ranges },
  5555. somethingSelected: function() {return this.sel.somethingSelected()},
  5556. setCursor: docMethodOp(function(line, ch, options) {
  5557. setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options);
  5558. }),
  5559. setSelection: docMethodOp(function(anchor, head, options) {
  5560. setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options);
  5561. }),
  5562. extendSelection: docMethodOp(function(head, other, options) {
  5563. extendSelection(this, clipPos(this, head), other && clipPos(this, other), options);
  5564. }),
  5565. extendSelections: docMethodOp(function(heads, options) {
  5566. extendSelections(this, clipPosArray(this, heads), options);
  5567. }),
  5568. extendSelectionsBy: docMethodOp(function(f, options) {
  5569. var heads = map(this.sel.ranges, f);
  5570. extendSelections(this, clipPosArray(this, heads), options);
  5571. }),
  5572. setSelections: docMethodOp(function(ranges, primary, options) {
  5573. if (!ranges.length) { return }
  5574. var out = [];
  5575. for (var i = 0; i < ranges.length; i++)
  5576. { out[i] = new Range(clipPos(this, ranges[i].anchor),
  5577. clipPos(this, ranges[i].head)); }
  5578. if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex); }
  5579. setSelection(this, normalizeSelection(this.cm, out, primary), options);
  5580. }),
  5581. addSelection: docMethodOp(function(anchor, head, options) {
  5582. var ranges = this.sel.ranges.slice(0);
  5583. ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)));
  5584. setSelection(this, normalizeSelection(this.cm, ranges, ranges.length - 1), options);
  5585. }),
  5586. getSelection: function(lineSep) {
  5587. var ranges = this.sel.ranges, lines;
  5588. for (var i = 0; i < ranges.length; i++) {
  5589. var sel = getBetween(this, ranges[i].from(), ranges[i].to());
  5590. lines = lines ? lines.concat(sel) : sel;
  5591. }
  5592. if (lineSep === false) { return lines }
  5593. else { return lines.join(lineSep || this.lineSeparator()) }
  5594. },
  5595. getSelections: function(lineSep) {
  5596. var parts = [], ranges = this.sel.ranges;
  5597. for (var i = 0; i < ranges.length; i++) {
  5598. var sel = getBetween(this, ranges[i].from(), ranges[i].to());
  5599. if (lineSep !== false) { sel = sel.join(lineSep || this.lineSeparator()); }
  5600. parts[i] = sel;
  5601. }
  5602. return parts
  5603. },
  5604. replaceSelection: function(code, collapse, origin) {
  5605. var dup = [];
  5606. for (var i = 0; i < this.sel.ranges.length; i++)
  5607. { dup[i] = code; }
  5608. this.replaceSelections(dup, collapse, origin || "+input");
  5609. },
  5610. replaceSelections: docMethodOp(function(code, collapse, origin) {
  5611. var changes = [], sel = this.sel;
  5612. for (var i = 0; i < sel.ranges.length; i++) {
  5613. var range = sel.ranges[i];
  5614. changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin};
  5615. }
  5616. var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);
  5617. for (var i$1 = changes.length - 1; i$1 >= 0; i$1--)
  5618. { makeChange(this, changes[i$1]); }
  5619. if (newSel) { setSelectionReplaceHistory(this, newSel); }
  5620. else if (this.cm) { ensureCursorVisible(this.cm); }
  5621. }),
  5622. undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}),
  5623. redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}),
  5624. undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}),
  5625. redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}),
  5626. setExtending: function(val) {this.extend = val;},
  5627. getExtending: function() {return this.extend},
  5628. historySize: function() {
  5629. var hist = this.history, done = 0, undone = 0;
  5630. for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done; } }
  5631. for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone; } }
  5632. return {undo: done, redo: undone}
  5633. },
  5634. clearHistory: function() {
  5635. var this$1 = this;
  5636. this.history = new History(this.history.maxGeneration);
  5637. linkedDocs(this, function (doc) { return doc.history = this$1.history; }, true);
  5638. },
  5639. markClean: function() {
  5640. this.cleanGeneration = this.changeGeneration(true);
  5641. },
  5642. changeGeneration: function(forceSplit) {
  5643. if (forceSplit)
  5644. { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; }
  5645. return this.history.generation
  5646. },
  5647. isClean: function (gen) {
  5648. return this.history.generation == (gen || this.cleanGeneration)
  5649. },
  5650. getHistory: function() {
  5651. return {done: copyHistoryArray(this.history.done),
  5652. undone: copyHistoryArray(this.history.undone)}
  5653. },
  5654. setHistory: function(histData) {
  5655. var hist = this.history = new History(this.history.maxGeneration);
  5656. hist.done = copyHistoryArray(histData.done.slice(0), null, true);
  5657. hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);
  5658. },
  5659. setGutterMarker: docMethodOp(function(line, gutterID, value) {
  5660. return changeLine(this, line, "gutter", function (line) {
  5661. var markers = line.gutterMarkers || (line.gutterMarkers = {});
  5662. markers[gutterID] = value;
  5663. if (!value && isEmpty(markers)) { line.gutterMarkers = null; }
  5664. return true
  5665. })
  5666. }),
  5667. clearGutter: docMethodOp(function(gutterID) {
  5668. var this$1 = this;
  5669. this.iter(function (line) {
  5670. if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
  5671. changeLine(this$1, line, "gutter", function () {
  5672. line.gutterMarkers[gutterID] = null;
  5673. if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null; }
  5674. return true
  5675. });
  5676. }
  5677. });
  5678. }),
  5679. lineInfo: function(line) {
  5680. var n;
  5681. if (typeof line == "number") {
  5682. if (!isLine(this, line)) { return null }
  5683. n = line;
  5684. line = getLine(this, line);
  5685. if (!line) { return null }
  5686. } else {
  5687. n = lineNo(line);
  5688. if (n == null) { return null }
  5689. }
  5690. return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
  5691. textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
  5692. widgets: line.widgets}
  5693. },
  5694. addLineClass: docMethodOp(function(handle, where, cls) {
  5695. return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) {
  5696. var prop = where == "text" ? "textClass"
  5697. : where == "background" ? "bgClass"
  5698. : where == "gutter" ? "gutterClass" : "wrapClass";
  5699. if (!line[prop]) { line[prop] = cls; }
  5700. else if (classTest(cls).test(line[prop])) { return false }
  5701. else { line[prop] += " " + cls; }
  5702. return true
  5703. })
  5704. }),
  5705. removeLineClass: docMethodOp(function(handle, where, cls) {
  5706. return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) {
  5707. var prop = where == "text" ? "textClass"
  5708. : where == "background" ? "bgClass"
  5709. : where == "gutter" ? "gutterClass" : "wrapClass";
  5710. var cur = line[prop];
  5711. if (!cur) { return false }
  5712. else if (cls == null) { line[prop] = null; }
  5713. else {
  5714. var found = cur.match(classTest(cls));
  5715. if (!found) { return false }
  5716. var end = found.index + found[0].length;
  5717. line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null;
  5718. }
  5719. return true
  5720. })
  5721. }),
  5722. addLineWidget: docMethodOp(function(handle, node, options) {
  5723. return addLineWidget(this, handle, node, options)
  5724. }),
  5725. removeLineWidget: function(widget) { widget.clear(); },
  5726. markText: function(from, to, options) {
  5727. return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range")
  5728. },
  5729. setBookmark: function(pos, options) {
  5730. var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
  5731. insertLeft: options && options.insertLeft,
  5732. clearWhenEmpty: false, shared: options && options.shared,
  5733. handleMouseEvents: options && options.handleMouseEvents};
  5734. pos = clipPos(this, pos);
  5735. return markText(this, pos, pos, realOpts, "bookmark")
  5736. },
  5737. findMarksAt: function(pos) {
  5738. pos = clipPos(this, pos);
  5739. var markers = [], spans = getLine(this, pos.line).markedSpans;
  5740. if (spans) { for (var i = 0; i < spans.length; ++i) {
  5741. var span = spans[i];
  5742. if ((span.from == null || span.from <= pos.ch) &&
  5743. (span.to == null || span.to >= pos.ch))
  5744. { markers.push(span.marker.parent || span.marker); }
  5745. } }
  5746. return markers
  5747. },
  5748. findMarks: function(from, to, filter) {
  5749. from = clipPos(this, from); to = clipPos(this, to);
  5750. var found = [], lineNo = from.line;
  5751. this.iter(from.line, to.line + 1, function (line) {
  5752. var spans = line.markedSpans;
  5753. if (spans) { for (var i = 0; i < spans.length; i++) {
  5754. var span = spans[i];
  5755. if (!(span.to != null && lineNo == from.line && from.ch >= span.to ||
  5756. span.from == null && lineNo != from.line ||
  5757. span.from != null && lineNo == to.line && span.from >= to.ch) &&
  5758. (!filter || filter(span.marker)))
  5759. { found.push(span.marker.parent || span.marker); }
  5760. } }
  5761. ++lineNo;
  5762. });
  5763. return found
  5764. },
  5765. getAllMarks: function() {
  5766. var markers = [];
  5767. this.iter(function (line) {
  5768. var sps = line.markedSpans;
  5769. if (sps) { for (var i = 0; i < sps.length; ++i)
  5770. { if (sps[i].from != null) { markers.push(sps[i].marker); } } }
  5771. });
  5772. return markers
  5773. },
  5774. posFromIndex: function(off) {
  5775. var ch, lineNo = this.first, sepSize = this.lineSeparator().length;
  5776. this.iter(function (line) {
  5777. var sz = line.text.length + sepSize;
  5778. if (sz > off) { ch = off; return true }
  5779. off -= sz;
  5780. ++lineNo;
  5781. });
  5782. return clipPos(this, Pos(lineNo, ch))
  5783. },
  5784. indexFromPos: function (coords) {
  5785. coords = clipPos(this, coords);
  5786. var index = coords.ch;
  5787. if (coords.line < this.first || coords.ch < 0) { return 0 }
  5788. var sepSize = this.lineSeparator().length;
  5789. this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value
  5790. index += line.text.length + sepSize;
  5791. });
  5792. return index
  5793. },
  5794. copy: function(copyHistory) {
  5795. var doc = new Doc(getLines(this, this.first, this.first + this.size),
  5796. this.modeOption, this.first, this.lineSep, this.direction);
  5797. doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft;
  5798. doc.sel = this.sel;
  5799. doc.extend = false;
  5800. if (copyHistory) {
  5801. doc.history.undoDepth = this.history.undoDepth;
  5802. doc.setHistory(this.getHistory());
  5803. }
  5804. return doc
  5805. },
  5806. linkedDoc: function(options) {
  5807. if (!options) { options = {}; }
  5808. var from = this.first, to = this.first + this.size;
  5809. if (options.from != null && options.from > from) { from = options.from; }
  5810. if (options.to != null && options.to < to) { to = options.to; }
  5811. var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep, this.direction);
  5812. if (options.sharedHist) { copy.history = this.history
  5813. ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist});
  5814. copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}];
  5815. copySharedMarkers(copy, findSharedMarkers(this));
  5816. return copy
  5817. },
  5818. unlinkDoc: function(other) {
  5819. if (other instanceof CodeMirror) { other = other.doc; }
  5820. if (this.linked) { for (var i = 0; i < this.linked.length; ++i) {
  5821. var link = this.linked[i];
  5822. if (link.doc != other) { continue }
  5823. this.linked.splice(i, 1);
  5824. other.unlinkDoc(this);
  5825. detachSharedMarkers(findSharedMarkers(this));
  5826. break
  5827. } }
  5828. // If the histories were shared, split them again
  5829. if (other.history == this.history) {
  5830. var splitIds = [other.id];
  5831. linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true);
  5832. other.history = new History(null);
  5833. other.history.done = copyHistoryArray(this.history.done, splitIds);
  5834. other.history.undone = copyHistoryArray(this.history.undone, splitIds);
  5835. }
  5836. },
  5837. iterLinkedDocs: function(f) {linkedDocs(this, f);},
  5838. getMode: function() {return this.mode},
  5839. getEditor: function() {return this.cm},
  5840. splitLines: function(str) {
  5841. if (this.lineSep) { return str.split(this.lineSep) }
  5842. return splitLinesAuto(str)
  5843. },
  5844. lineSeparator: function() { return this.lineSep || "\n" },
  5845. setDirection: docMethodOp(function (dir) {
  5846. if (dir != "rtl") { dir = "ltr"; }
  5847. if (dir == this.direction) { return }
  5848. this.direction = dir;
  5849. this.iter(function (line) { return line.order = null; });
  5850. if (this.cm) { directionChanged(this.cm); }
  5851. })
  5852. });
  5853. // Public alias.
  5854. Doc.prototype.eachLine = Doc.prototype.iter;
  5855. // Kludge to work around strange IE behavior where it'll sometimes
  5856. // re-fire a series of drag-related events right after the drop (#1551)
  5857. var lastDrop = 0;
  5858. function onDrop(e) {
  5859. var cm = this;
  5860. clearDragCursor(cm);
  5861. if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
  5862. { return }
  5863. e_preventDefault(e);
  5864. if (ie) { lastDrop = +new Date; }
  5865. var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files;
  5866. if (!pos || cm.isReadOnly()) { return }
  5867. // Might be a file drop, in which case we simply extract the text
  5868. // and insert it.
  5869. if (files && files.length && window.FileReader && window.File) {
  5870. var n = files.length, text = Array(n), read = 0;
  5871. var markAsReadAndPasteIfAllFilesAreRead = function () {
  5872. if (++read == n) {
  5873. operation(cm, function () {
  5874. pos = clipPos(cm.doc, pos);
  5875. var change = {from: pos, to: pos,
  5876. text: cm.doc.splitLines(
  5877. text.filter(function (t) { return t != null; }).join(cm.doc.lineSeparator())),
  5878. origin: "paste"};
  5879. makeChange(cm.doc, change);
  5880. setSelectionReplaceHistory(cm.doc, simpleSelection(clipPos(cm.doc, pos), clipPos(cm.doc, changeEnd(change))));
  5881. })();
  5882. }
  5883. };
  5884. var readTextFromFile = function (file, i) {
  5885. if (cm.options.allowDropFileTypes &&
  5886. indexOf(cm.options.allowDropFileTypes, file.type) == -1) {
  5887. markAsReadAndPasteIfAllFilesAreRead();
  5888. return
  5889. }
  5890. var reader = new FileReader;
  5891. reader.onerror = function () { return markAsReadAndPasteIfAllFilesAreRead(); };
  5892. reader.onload = function () {
  5893. var content = reader.result;
  5894. if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) {
  5895. markAsReadAndPasteIfAllFilesAreRead();
  5896. return
  5897. }
  5898. text[i] = content;
  5899. markAsReadAndPasteIfAllFilesAreRead();
  5900. };
  5901. reader.readAsText(file);
  5902. };
  5903. for (var i = 0; i < files.length; i++) { readTextFromFile(files[i], i); }
  5904. } else { // Normal drop
  5905. // Don't do a replace if the drop happened inside of the selected text.
  5906. if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
  5907. cm.state.draggingText(e);
  5908. // Ensure the editor is re-focused
  5909. setTimeout(function () { return cm.display.input.focus(); }, 20);
  5910. return
  5911. }
  5912. try {
  5913. var text$1 = e.dataTransfer.getData("Text");
  5914. if (text$1) {
  5915. var selected;
  5916. if (cm.state.draggingText && !cm.state.draggingText.copy)
  5917. { selected = cm.listSelections(); }
  5918. setSelectionNoUndo(cm.doc, simpleSelection(pos, pos));
  5919. if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1)
  5920. { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag"); } }
  5921. cm.replaceSelection(text$1, "around", "paste");
  5922. cm.display.input.focus();
  5923. }
  5924. }
  5925. catch(e$1){}
  5926. }
  5927. }
  5928. function onDragStart(cm, e) {
  5929. if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return }
  5930. if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return }
  5931. e.dataTransfer.setData("Text", cm.getSelection());
  5932. e.dataTransfer.effectAllowed = "copyMove";
  5933. // Use dummy image instead of default browsers image.
  5934. // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
  5935. if (e.dataTransfer.setDragImage && !safari) {
  5936. var img = elt("img", null, null, "position: fixed; left: 0; top: 0;");
  5937. img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==";
  5938. if (presto) {
  5939. img.width = img.height = 1;
  5940. cm.display.wrapper.appendChild(img);
  5941. // Force a relayout, or Opera won't use our image for some obscure reason
  5942. img._top = img.offsetTop;
  5943. }
  5944. e.dataTransfer.setDragImage(img, 0, 0);
  5945. if (presto) { img.parentNode.removeChild(img); }
  5946. }
  5947. }
  5948. function onDragOver(cm, e) {
  5949. var pos = posFromMouse(cm, e);
  5950. if (!pos) { return }
  5951. var frag = document.createDocumentFragment();
  5952. drawSelectionCursor(cm, pos, frag);
  5953. if (!cm.display.dragCursor) {
  5954. cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors");
  5955. cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv);
  5956. }
  5957. removeChildrenAndAdd(cm.display.dragCursor, frag);
  5958. }
  5959. function clearDragCursor(cm) {
  5960. if (cm.display.dragCursor) {
  5961. cm.display.lineSpace.removeChild(cm.display.dragCursor);
  5962. cm.display.dragCursor = null;
  5963. }
  5964. }
  5965. // These must be handled carefully, because naively registering a
  5966. // handler for each editor will cause the editors to never be
  5967. // garbage collected.
  5968. function forEachCodeMirror(f) {
  5969. if (!document.getElementsByClassName) { return }
  5970. var byClass = document.getElementsByClassName("CodeMirror"), editors = [];
  5971. for (var i = 0; i < byClass.length; i++) {
  5972. var cm = byClass[i].CodeMirror;
  5973. if (cm) { editors.push(cm); }
  5974. }
  5975. if (editors.length) { editors[0].operation(function () {
  5976. for (var i = 0; i < editors.length; i++) { f(editors[i]); }
  5977. }); }
  5978. }
  5979. var globalsRegistered = false;
  5980. function ensureGlobalHandlers() {
  5981. if (globalsRegistered) { return }
  5982. registerGlobalHandlers();
  5983. globalsRegistered = true;
  5984. }
  5985. function registerGlobalHandlers() {
  5986. // When the window resizes, we need to refresh active editors.
  5987. var resizeTimer;
  5988. on(window, "resize", function () {
  5989. if (resizeTimer == null) { resizeTimer = setTimeout(function () {
  5990. resizeTimer = null;
  5991. forEachCodeMirror(onResize);
  5992. }, 100); }
  5993. });
  5994. // When the window loses focus, we want to show the editor as blurred
  5995. on(window, "blur", function () { return forEachCodeMirror(onBlur); });
  5996. }
  5997. // Called when the window resizes
  5998. function onResize(cm) {
  5999. var d = cm.display;
  6000. // Might be a text scaling operation, clear size caches.
  6001. d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null;
  6002. d.scrollbarsClipped = false;
  6003. cm.setSize();
  6004. }
  6005. var keyNames = {
  6006. 3: "Pause", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
  6007. 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
  6008. 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
  6009. 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
  6010. 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 145: "ScrollLock",
  6011. 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
  6012. 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
  6013. 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
  6014. };
  6015. // Number keys
  6016. for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i); }
  6017. // Alphabetic keys
  6018. for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1); }
  6019. // Function keys
  6020. for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2; }
  6021. var keyMap = {};
  6022. keyMap.basic = {
  6023. "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
  6024. "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
  6025. "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
  6026. "Tab": "defaultTab", "Shift-Tab": "indentAuto",
  6027. "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",
  6028. "Esc": "singleSelection"
  6029. };
  6030. // Note that the save and find-related commands aren't defined by
  6031. // default. User code or addons can define them. Unknown commands
  6032. // are simply ignored.
  6033. keyMap.pcDefault = {
  6034. "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
  6035. "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",
  6036. "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
  6037. "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
  6038. "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
  6039. "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
  6040. "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
  6041. "fallthrough": "basic"
  6042. };
  6043. // Very basic readline/emacs-style bindings, which are standard on Mac.
  6044. keyMap.emacsy = {
  6045. "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
  6046. "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
  6047. "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
  6048. "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars",
  6049. "Ctrl-O": "openLine"
  6050. };
  6051. keyMap.macDefault = {
  6052. "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
  6053. "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
  6054. "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
  6055. "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
  6056. "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
  6057. "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
  6058. "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
  6059. "fallthrough": ["basic", "emacsy"]
  6060. };
  6061. keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault;
  6062. // KEYMAP DISPATCH
  6063. function normalizeKeyName(name) {
  6064. var parts = name.split(/-(?!$)/);
  6065. name = parts[parts.length - 1];
  6066. var alt, ctrl, shift, cmd;
  6067. for (var i = 0; i < parts.length - 1; i++) {
  6068. var mod = parts[i];
  6069. if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true; }
  6070. else if (/^a(lt)?$/i.test(mod)) { alt = true; }
  6071. else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true; }
  6072. else if (/^s(hift)?$/i.test(mod)) { shift = true; }
  6073. else { throw new Error("Unrecognized modifier name: " + mod) }
  6074. }
  6075. if (alt) { name = "Alt-" + name; }
  6076. if (ctrl) { name = "Ctrl-" + name; }
  6077. if (cmd) { name = "Cmd-" + name; }
  6078. if (shift) { name = "Shift-" + name; }
  6079. return name
  6080. }
  6081. // This is a kludge to keep keymaps mostly working as raw objects
  6082. // (backwards compatibility) while at the same time support features
  6083. // like normalization and multi-stroke key bindings. It compiles a
  6084. // new normalized keymap, and then updates the old object to reflect
  6085. // this.
  6086. function normalizeKeyMap(keymap) {
  6087. var copy = {};
  6088. for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) {
  6089. var value = keymap[keyname];
  6090. if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue }
  6091. if (value == "...") { delete keymap[keyname]; continue }
  6092. var keys = map(keyname.split(" "), normalizeKeyName);
  6093. for (var i = 0; i < keys.length; i++) {
  6094. var val = (void 0), name = (void 0);
  6095. if (i == keys.length - 1) {
  6096. name = keys.join(" ");
  6097. val = value;
  6098. } else {
  6099. name = keys.slice(0, i + 1).join(" ");
  6100. val = "...";
  6101. }
  6102. var prev = copy[name];
  6103. if (!prev) { copy[name] = val; }
  6104. else if (prev != val) { throw new Error("Inconsistent bindings for " + name) }
  6105. }
  6106. delete keymap[keyname];
  6107. } }
  6108. for (var prop in copy) { keymap[prop] = copy[prop]; }
  6109. return keymap
  6110. }
  6111. function lookupKey(key, map, handle, context) {
  6112. map = getKeyMap(map);
  6113. var found = map.call ? map.call(key, context) : map[key];
  6114. if (found === false) { return "nothing" }
  6115. if (found === "...") { return "multi" }
  6116. if (found != null && handle(found)) { return "handled" }
  6117. if (map.fallthrough) {
  6118. if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
  6119. { return lookupKey(key, map.fallthrough, handle, context) }
  6120. for (var i = 0; i < map.fallthrough.length; i++) {
  6121. var result = lookupKey(key, map.fallthrough[i], handle, context);
  6122. if (result) { return result }
  6123. }
  6124. }
  6125. }
  6126. // Modifier key presses don't count as 'real' key presses for the
  6127. // purpose of keymap fallthrough.
  6128. function isModifierKey(value) {
  6129. var name = typeof value == "string" ? value : keyNames[value.keyCode];
  6130. return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"
  6131. }
  6132. function addModifierNames(name, event, noShift) {
  6133. var base = name;
  6134. if (event.altKey && base != "Alt") { name = "Alt-" + name; }
  6135. if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name; }
  6136. if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") { name = "Cmd-" + name; }
  6137. if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name; }
  6138. return name
  6139. }
  6140. // Look up the name of a key as indicated by an event object.
  6141. function keyName(event, noShift) {
  6142. if (presto && event.keyCode == 34 && event["char"]) { return false }
  6143. var name = keyNames[event.keyCode];
  6144. if (name == null || event.altGraphKey) { return false }
  6145. // Ctrl-ScrollLock has keyCode 3, same as Ctrl-Pause,
  6146. // so we'll use event.code when available (Chrome 48+, FF 38+, Safari 10.1+)
  6147. if (event.keyCode == 3 && event.code) { name = event.code; }
  6148. return addModifierNames(name, event, noShift)
  6149. }
  6150. function getKeyMap(val) {
  6151. return typeof val == "string" ? keyMap[val] : val
  6152. }
  6153. // Helper for deleting text near the selection(s), used to implement
  6154. // backspace, delete, and similar functionality.
  6155. function deleteNearSelection(cm, compute) {
  6156. var ranges = cm.doc.sel.ranges, kill = [];
  6157. // Build up a set of ranges to kill first, merging overlapping
  6158. // ranges.
  6159. for (var i = 0; i < ranges.length; i++) {
  6160. var toKill = compute(ranges[i]);
  6161. while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {
  6162. var replaced = kill.pop();
  6163. if (cmp(replaced.from, toKill.from) < 0) {
  6164. toKill.from = replaced.from;
  6165. break
  6166. }
  6167. }
  6168. kill.push(toKill);
  6169. }
  6170. // Next, remove those actual ranges.
  6171. runInOp(cm, function () {
  6172. for (var i = kill.length - 1; i >= 0; i--)
  6173. { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); }
  6174. ensureCursorVisible(cm);
  6175. });
  6176. }
  6177. function moveCharLogically(line, ch, dir) {
  6178. var target = skipExtendingChars(line.text, ch + dir, dir);
  6179. return target < 0 || target > line.text.length ? null : target
  6180. }
  6181. function moveLogically(line, start, dir) {
  6182. var ch = moveCharLogically(line, start.ch, dir);
  6183. return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before")
  6184. }
  6185. function endOfLine(visually, cm, lineObj, lineNo, dir) {
  6186. if (visually) {
  6187. if (cm.doc.direction == "rtl") { dir = -dir; }
  6188. var order = getOrder(lineObj, cm.doc.direction);
  6189. if (order) {
  6190. var part = dir < 0 ? lst(order) : order[0];
  6191. var moveInStorageOrder = (dir < 0) == (part.level == 1);
  6192. var sticky = moveInStorageOrder ? "after" : "before";
  6193. var ch;
  6194. // With a wrapped rtl chunk (possibly spanning multiple bidi parts),
  6195. // it could be that the last bidi part is not on the last visual line,
  6196. // since visual lines contain content order-consecutive chunks.
  6197. // Thus, in rtl, we are looking for the first (content-order) character
  6198. // in the rtl chunk that is on the last line (that is, the same line
  6199. // as the last (content-order) character).
  6200. if (part.level > 0 || cm.doc.direction == "rtl") {
  6201. var prep = prepareMeasureForLine(cm, lineObj);
  6202. ch = dir < 0 ? lineObj.text.length - 1 : 0;
  6203. var targetTop = measureCharPrepared(cm, prep, ch).top;
  6204. ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch);
  6205. if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1); }
  6206. } else { ch = dir < 0 ? part.to : part.from; }
  6207. return new Pos(lineNo, ch, sticky)
  6208. }
  6209. }
  6210. return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after")
  6211. }
  6212. function moveVisually(cm, line, start, dir) {
  6213. var bidi = getOrder(line, cm.doc.direction);
  6214. if (!bidi) { return moveLogically(line, start, dir) }
  6215. if (start.ch >= line.text.length) {
  6216. start.ch = line.text.length;
  6217. start.sticky = "before";
  6218. } else if (start.ch <= 0) {
  6219. start.ch = 0;
  6220. start.sticky = "after";
  6221. }
  6222. var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos];
  6223. if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) {
  6224. // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines,
  6225. // nothing interesting happens.
  6226. return moveLogically(line, start, dir)
  6227. }
  6228. var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); };
  6229. var prep;
  6230. var getWrappedLineExtent = function (ch) {
  6231. if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} }
  6232. prep = prep || prepareMeasureForLine(cm, line);
  6233. return wrappedLineExtentChar(cm, line, prep, ch)
  6234. };
  6235. var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch);
  6236. if (cm.doc.direction == "rtl" || part.level == 1) {
  6237. var moveInStorageOrder = (part.level == 1) == (dir < 0);
  6238. var ch = mv(start, moveInStorageOrder ? 1 : -1);
  6239. if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) {
  6240. // Case 2: We move within an rtl part or in an rtl editor on the same visual line
  6241. var sticky = moveInStorageOrder ? "before" : "after";
  6242. return new Pos(start.line, ch, sticky)
  6243. }
  6244. }
  6245. // Case 3: Could not move within this bidi part in this visual line, so leave
  6246. // the current bidi part
  6247. var searchInVisualLine = function (partPos, dir, wrappedLineExtent) {
  6248. var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder
  6249. ? new Pos(start.line, mv(ch, 1), "before")
  6250. : new Pos(start.line, ch, "after"); };
  6251. for (; partPos >= 0 && partPos < bidi.length; partPos += dir) {
  6252. var part = bidi[partPos];
  6253. var moveInStorageOrder = (dir > 0) == (part.level != 1);
  6254. var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1);
  6255. if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) }
  6256. ch = moveInStorageOrder ? part.from : mv(part.to, -1);
  6257. if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) }
  6258. }
  6259. };
  6260. // Case 3a: Look for other bidi parts on the same visual line
  6261. var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent);
  6262. if (res) { return res }
  6263. // Case 3b: Look for other bidi parts on the next visual line
  6264. var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1);
  6265. if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) {
  6266. res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh));
  6267. if (res) { return res }
  6268. }
  6269. // Case 4: Nowhere to move
  6270. return null
  6271. }
  6272. // Commands are parameter-less actions that can be performed on an
  6273. // editor, mostly used for keybindings.
  6274. var commands = {
  6275. selectAll: selectAll,
  6276. singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); },
  6277. killLine: function (cm) { return deleteNearSelection(cm, function (range) {
  6278. if (range.empty()) {
  6279. var len = getLine(cm.doc, range.head.line).text.length;
  6280. if (range.head.ch == len && range.head.line < cm.lastLine())
  6281. { return {from: range.head, to: Pos(range.head.line + 1, 0)} }
  6282. else
  6283. { return {from: range.head, to: Pos(range.head.line, len)} }
  6284. } else {
  6285. return {from: range.from(), to: range.to()}
  6286. }
  6287. }); },
  6288. deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({
  6289. from: Pos(range.from().line, 0),
  6290. to: clipPos(cm.doc, Pos(range.to().line + 1, 0))
  6291. }); }); },
  6292. delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({
  6293. from: Pos(range.from().line, 0), to: range.from()
  6294. }); }); },
  6295. delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) {
  6296. var top = cm.charCoords(range.head, "div").top + 5;
  6297. var leftPos = cm.coordsChar({left: 0, top: top}, "div");
  6298. return {from: leftPos, to: range.from()}
  6299. }); },
  6300. delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) {
  6301. var top = cm.charCoords(range.head, "div").top + 5;
  6302. var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div");
  6303. return {from: range.from(), to: rightPos }
  6304. }); },
  6305. undo: function (cm) { return cm.undo(); },
  6306. redo: function (cm) { return cm.redo(); },
  6307. undoSelection: function (cm) { return cm.undoSelection(); },
  6308. redoSelection: function (cm) { return cm.redoSelection(); },
  6309. goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); },
  6310. goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); },
  6311. goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); },
  6312. {origin: "+move", bias: 1}
  6313. ); },
  6314. goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); },
  6315. {origin: "+move", bias: 1}
  6316. ); },
  6317. goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); },
  6318. {origin: "+move", bias: -1}
  6319. ); },
  6320. goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) {
  6321. var top = cm.cursorCoords(range.head, "div").top + 5;
  6322. return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div")
  6323. }, sel_move); },
  6324. goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) {
  6325. var top = cm.cursorCoords(range.head, "div").top + 5;
  6326. return cm.coordsChar({left: 0, top: top}, "div")
  6327. }, sel_move); },
  6328. goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) {
  6329. var top = cm.cursorCoords(range.head, "div").top + 5;
  6330. var pos = cm.coordsChar({left: 0, top: top}, "div");
  6331. if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) }
  6332. return pos
  6333. }, sel_move); },
  6334. goLineUp: function (cm) { return cm.moveV(-1, "line"); },
  6335. goLineDown: function (cm) { return cm.moveV(1, "line"); },
  6336. goPageUp: function (cm) { return cm.moveV(-1, "page"); },
  6337. goPageDown: function (cm) { return cm.moveV(1, "page"); },
  6338. goCharLeft: function (cm) { return cm.moveH(-1, "char"); },
  6339. goCharRight: function (cm) { return cm.moveH(1, "char"); },
  6340. goColumnLeft: function (cm) { return cm.moveH(-1, "column"); },
  6341. goColumnRight: function (cm) { return cm.moveH(1, "column"); },
  6342. goWordLeft: function (cm) { return cm.moveH(-1, "word"); },
  6343. goGroupRight: function (cm) { return cm.moveH(1, "group"); },
  6344. goGroupLeft: function (cm) { return cm.moveH(-1, "group"); },
  6345. goWordRight: function (cm) { return cm.moveH(1, "word"); },
  6346. delCharBefore: function (cm) { return cm.deleteH(-1, "char"); },
  6347. delCharAfter: function (cm) { return cm.deleteH(1, "char"); },
  6348. delWordBefore: function (cm) { return cm.deleteH(-1, "word"); },
  6349. delWordAfter: function (cm) { return cm.deleteH(1, "word"); },
  6350. delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); },
  6351. delGroupAfter: function (cm) { return cm.deleteH(1, "group"); },
  6352. indentAuto: function (cm) { return cm.indentSelection("smart"); },
  6353. indentMore: function (cm) { return cm.indentSelection("add"); },
  6354. indentLess: function (cm) { return cm.indentSelection("subtract"); },
  6355. insertTab: function (cm) { return cm.replaceSelection("\t"); },
  6356. insertSoftTab: function (cm) {
  6357. var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize;
  6358. for (var i = 0; i < ranges.length; i++) {
  6359. var pos = ranges[i].from();
  6360. var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize);
  6361. spaces.push(spaceStr(tabSize - col % tabSize));
  6362. }
  6363. cm.replaceSelections(spaces);
  6364. },
  6365. defaultTab: function (cm) {
  6366. if (cm.somethingSelected()) { cm.indentSelection("add"); }
  6367. else { cm.execCommand("insertTab"); }
  6368. },
  6369. // Swap the two chars left and right of each selection's head.
  6370. // Move cursor behind the two swapped characters afterwards.
  6371. //
  6372. // Doesn't consider line feeds a character.
  6373. // Doesn't scan more than one line above to find a character.
  6374. // Doesn't do anything on an empty line.
  6375. // Doesn't do anything with non-empty selections.
  6376. transposeChars: function (cm) { return runInOp(cm, function () {
  6377. var ranges = cm.listSelections(), newSel = [];
  6378. for (var i = 0; i < ranges.length; i++) {
  6379. if (!ranges[i].empty()) { continue }
  6380. var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text;
  6381. if (line) {
  6382. if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1); }
  6383. if (cur.ch > 0) {
  6384. cur = new Pos(cur.line, cur.ch + 1);
  6385. cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
  6386. Pos(cur.line, cur.ch - 2), cur, "+transpose");
  6387. } else if (cur.line > cm.doc.first) {
  6388. var prev = getLine(cm.doc, cur.line - 1).text;
  6389. if (prev) {
  6390. cur = new Pos(cur.line, 1);
  6391. cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +
  6392. prev.charAt(prev.length - 1),
  6393. Pos(cur.line - 1, prev.length - 1), cur, "+transpose");
  6394. }
  6395. }
  6396. }
  6397. newSel.push(new Range(cur, cur));
  6398. }
  6399. cm.setSelections(newSel);
  6400. }); },
  6401. newlineAndIndent: function (cm) { return runInOp(cm, function () {
  6402. var sels = cm.listSelections();
  6403. for (var i = sels.length - 1; i >= 0; i--)
  6404. { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input"); }
  6405. sels = cm.listSelections();
  6406. for (var i$1 = 0; i$1 < sels.length; i$1++)
  6407. { cm.indentLine(sels[i$1].from().line, null, true); }
  6408. ensureCursorVisible(cm);
  6409. }); },
  6410. openLine: function (cm) { return cm.replaceSelection("\n", "start"); },
  6411. toggleOverwrite: function (cm) { return cm.toggleOverwrite(); }
  6412. };
  6413. function lineStart(cm, lineN) {
  6414. var line = getLine(cm.doc, lineN);
  6415. var visual = visualLine(line);
  6416. if (visual != line) { lineN = lineNo(visual); }
  6417. return endOfLine(true, cm, visual, lineN, 1)
  6418. }
  6419. function lineEnd(cm, lineN) {
  6420. var line = getLine(cm.doc, lineN);
  6421. var visual = visualLineEnd(line);
  6422. if (visual != line) { lineN = lineNo(visual); }
  6423. return endOfLine(true, cm, line, lineN, -1)
  6424. }
  6425. function lineStartSmart(cm, pos) {
  6426. var start = lineStart(cm, pos.line);
  6427. var line = getLine(cm.doc, start.line);
  6428. var order = getOrder(line, cm.doc.direction);
  6429. if (!order || order[0].level == 0) {
  6430. var firstNonWS = Math.max(start.ch, line.text.search(/\S/));
  6431. var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch;
  6432. return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky)
  6433. }
  6434. return start
  6435. }
  6436. // Run a handler that was bound to a key.
  6437. function doHandleBinding(cm, bound, dropShift) {
  6438. if (typeof bound == "string") {
  6439. bound = commands[bound];
  6440. if (!bound) { return false }
  6441. }
  6442. // Ensure previous input has been read, so that the handler sees a
  6443. // consistent view of the document
  6444. cm.display.input.ensurePolled();
  6445. var prevShift = cm.display.shift, done = false;
  6446. try {
  6447. if (cm.isReadOnly()) { cm.state.suppressEdits = true; }
  6448. if (dropShift) { cm.display.shift = false; }
  6449. done = bound(cm) != Pass;
  6450. } finally {
  6451. cm.display.shift = prevShift;
  6452. cm.state.suppressEdits = false;
  6453. }
  6454. return done
  6455. }
  6456. function lookupKeyForEditor(cm, name, handle) {
  6457. for (var i = 0; i < cm.state.keyMaps.length; i++) {
  6458. var result = lookupKey(name, cm.state.keyMaps[i], handle, cm);
  6459. if (result) { return result }
  6460. }
  6461. return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))
  6462. || lookupKey(name, cm.options.keyMap, handle, cm)
  6463. }
  6464. // Note that, despite the name, this function is also used to check
  6465. // for bound mouse clicks.
  6466. var stopSeq = new Delayed;
  6467. function dispatchKey(cm, name, e, handle) {
  6468. var seq = cm.state.keySeq;
  6469. if (seq) {
  6470. if (isModifierKey(name)) { return "handled" }
  6471. if (/\'$/.test(name))
  6472. { cm.state.keySeq = null; }
  6473. else
  6474. { stopSeq.set(50, function () {
  6475. if (cm.state.keySeq == seq) {
  6476. cm.state.keySeq = null;
  6477. cm.display.input.reset();
  6478. }
  6479. }); }
  6480. if (dispatchKeyInner(cm, seq + " " + name, e, handle)) { return true }
  6481. }
  6482. return dispatchKeyInner(cm, name, e, handle)
  6483. }
  6484. function dispatchKeyInner(cm, name, e, handle) {
  6485. var result = lookupKeyForEditor(cm, name, handle);
  6486. if (result == "multi")
  6487. { cm.state.keySeq = name; }
  6488. if (result == "handled")
  6489. { signalLater(cm, "keyHandled", cm, name, e); }
  6490. if (result == "handled" || result == "multi") {
  6491. e_preventDefault(e);
  6492. restartBlink(cm);
  6493. }
  6494. return !!result
  6495. }
  6496. // Handle a key from the keydown event.
  6497. function handleKeyBinding(cm, e) {
  6498. var name = keyName(e, true);
  6499. if (!name) { return false }
  6500. if (e.shiftKey && !cm.state.keySeq) {
  6501. // First try to resolve full name (including 'Shift-'). Failing
  6502. // that, see if there is a cursor-motion command (starting with
  6503. // 'go') bound to the keyname without 'Shift-'.
  6504. return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); })
  6505. || dispatchKey(cm, name, e, function (b) {
  6506. if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
  6507. { return doHandleBinding(cm, b) }
  6508. })
  6509. } else {
  6510. return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); })
  6511. }
  6512. }
  6513. // Handle a key from the keypress event
  6514. function handleCharBinding(cm, e, ch) {
  6515. return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); })
  6516. }
  6517. var lastStoppedKey = null;
  6518. function onKeyDown(e) {
  6519. var cm = this;
  6520. if (e.target && e.target != cm.display.input.getField()) { return }
  6521. cm.curOp.focus = activeElt();
  6522. if (signalDOMEvent(cm, e)) { return }
  6523. // IE does strange things with escape.
  6524. if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false; }
  6525. var code = e.keyCode;
  6526. cm.display.shift = code == 16 || e.shiftKey;
  6527. var handled = handleKeyBinding(cm, e);
  6528. if (presto) {
  6529. lastStoppedKey = handled ? code : null;
  6530. // Opera has no cut event... we try to at least catch the key combo
  6531. if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
  6532. { cm.replaceSelection("", null, "cut"); }
  6533. }
  6534. if (gecko && !mac && !handled && code == 46 && e.shiftKey && !e.ctrlKey && document.execCommand)
  6535. { document.execCommand("cut"); }
  6536. // Turn mouse into crosshair when Alt is held on Mac.
  6537. if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
  6538. { showCrossHair(cm); }
  6539. }
  6540. function showCrossHair(cm) {
  6541. var lineDiv = cm.display.lineDiv;
  6542. addClass(lineDiv, "CodeMirror-crosshair");
  6543. function up(e) {
  6544. if (e.keyCode == 18 || !e.altKey) {
  6545. rmClass(lineDiv, "CodeMirror-crosshair");
  6546. off(document, "keyup", up);
  6547. off(document, "mouseover", up);
  6548. }
  6549. }
  6550. on(document, "keyup", up);
  6551. on(document, "mouseover", up);
  6552. }
  6553. function onKeyUp(e) {
  6554. if (e.keyCode == 16) { this.doc.sel.shift = false; }
  6555. signalDOMEvent(this, e);
  6556. }
  6557. function onKeyPress(e) {
  6558. var cm = this;
  6559. if (e.target && e.target != cm.display.input.getField()) { return }
  6560. if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return }
  6561. var keyCode = e.keyCode, charCode = e.charCode;
  6562. if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return}
  6563. if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return }
  6564. var ch = String.fromCharCode(charCode == null ? keyCode : charCode);
  6565. // Some browsers fire keypress events for backspace
  6566. if (ch == "\x08") { return }
  6567. if (handleCharBinding(cm, e, ch)) { return }
  6568. cm.display.input.onKeyPress(e);
  6569. }
  6570. var DOUBLECLICK_DELAY = 400;
  6571. var PastClick = function(time, pos, button) {
  6572. this.time = time;
  6573. this.pos = pos;
  6574. this.button = button;
  6575. };
  6576. PastClick.prototype.compare = function (time, pos, button) {
  6577. return this.time + DOUBLECLICK_DELAY > time &&
  6578. cmp(pos, this.pos) == 0 && button == this.button
  6579. };
  6580. var lastClick, lastDoubleClick;
  6581. function clickRepeat(pos, button) {
  6582. var now = +new Date;
  6583. if (lastDoubleClick && lastDoubleClick.compare(now, pos, button)) {
  6584. lastClick = lastDoubleClick = null;
  6585. return "triple"
  6586. } else if (lastClick && lastClick.compare(now, pos, button)) {
  6587. lastDoubleClick = new PastClick(now, pos, button);
  6588. lastClick = null;
  6589. return "double"
  6590. } else {
  6591. lastClick = new PastClick(now, pos, button);
  6592. lastDoubleClick = null;
  6593. return "single"
  6594. }
  6595. }
  6596. // A mouse down can be a single click, double click, triple click,
  6597. // start of selection drag, start of text drag, new cursor
  6598. // (ctrl-click), rectangle drag (alt-drag), or xwin
  6599. // middle-click-paste. Or it might be a click on something we should
  6600. // not interfere with, such as a scrollbar or widget.
  6601. function onMouseDown(e) {
  6602. var cm = this, display = cm.display;
  6603. if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return }
  6604. display.input.ensurePolled();
  6605. display.shift = e.shiftKey;
  6606. if (eventInWidget(display, e)) {
  6607. if (!webkit) {
  6608. // Briefly turn off draggability, to allow widgets to do
  6609. // normal dragging things.
  6610. display.scroller.draggable = false;
  6611. setTimeout(function () { return display.scroller.draggable = true; }, 100);
  6612. }
  6613. return
  6614. }
  6615. if (clickInGutter(cm, e)) { return }
  6616. var pos = posFromMouse(cm, e), button = e_button(e), repeat = pos ? clickRepeat(pos, button) : "single";
  6617. window.focus();
  6618. // #3261: make sure, that we're not starting a second selection
  6619. if (button == 1 && cm.state.selectingText)
  6620. { cm.state.selectingText(e); }
  6621. if (pos && handleMappedButton(cm, button, pos, repeat, e)) { return }
  6622. if (button == 1) {
  6623. if (pos) { leftButtonDown(cm, pos, repeat, e); }
  6624. else if (e_target(e) == display.scroller) { e_preventDefault(e); }
  6625. } else if (button == 2) {
  6626. if (pos) { extendSelection(cm.doc, pos); }
  6627. setTimeout(function () { return display.input.focus(); }, 20);
  6628. } else if (button == 3) {
  6629. if (captureRightClick) { cm.display.input.onContextMenu(e); }
  6630. else { delayBlurEvent(cm); }
  6631. }
  6632. }
  6633. function handleMappedButton(cm, button, pos, repeat, event) {
  6634. var name = "Click";
  6635. if (repeat == "double") { name = "Double" + name; }
  6636. else if (repeat == "triple") { name = "Triple" + name; }
  6637. name = (button == 1 ? "Left" : button == 2 ? "Middle" : "Right") + name;
  6638. return dispatchKey(cm, addModifierNames(name, event), event, function (bound) {
  6639. if (typeof bound == "string") { bound = commands[bound]; }
  6640. if (!bound) { return false }
  6641. var done = false;
  6642. try {
  6643. if (cm.isReadOnly()) { cm.state.suppressEdits = true; }
  6644. done = bound(cm, pos) != Pass;
  6645. } finally {
  6646. cm.state.suppressEdits = false;
  6647. }
  6648. return done
  6649. })
  6650. }
  6651. function configureMouse(cm, repeat, event) {
  6652. var option = cm.getOption("configureMouse");
  6653. var value = option ? option(cm, repeat, event) : {};
  6654. if (value.unit == null) {
  6655. var rect = chromeOS ? event.shiftKey && event.metaKey : event.altKey;
  6656. value.unit = rect ? "rectangle" : repeat == "single" ? "char" : repeat == "double" ? "word" : "line";
  6657. }
  6658. if (value.extend == null || cm.doc.extend) { value.extend = cm.doc.extend || event.shiftKey; }
  6659. if (value.addNew == null) { value.addNew = mac ? event.metaKey : event.ctrlKey; }
  6660. if (value.moveOnDrag == null) { value.moveOnDrag = !(mac ? event.altKey : event.ctrlKey); }
  6661. return value
  6662. }
  6663. function leftButtonDown(cm, pos, repeat, event) {
  6664. if (ie) { setTimeout(bind(ensureFocus, cm), 0); }
  6665. else { cm.curOp.focus = activeElt(); }
  6666. var behavior = configureMouse(cm, repeat, event);
  6667. var sel = cm.doc.sel, contained;
  6668. if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() &&
  6669. repeat == "single" && (contained = sel.contains(pos)) > -1 &&
  6670. (cmp((contained = sel.ranges[contained]).from(), pos) < 0 || pos.xRel > 0) &&
  6671. (cmp(contained.to(), pos) > 0 || pos.xRel < 0))
  6672. { leftButtonStartDrag(cm, event, pos, behavior); }
  6673. else
  6674. { leftButtonSelect(cm, event, pos, behavior); }
  6675. }
  6676. // Start a text drag. When it ends, see if any dragging actually
  6677. // happen, and treat as a click if it didn't.
  6678. function leftButtonStartDrag(cm, event, pos, behavior) {
  6679. var display = cm.display, moved = false;
  6680. var dragEnd = operation(cm, function (e) {
  6681. if (webkit) { display.scroller.draggable = false; }
  6682. cm.state.draggingText = false;
  6683. off(display.wrapper.ownerDocument, "mouseup", dragEnd);
  6684. off(display.wrapper.ownerDocument, "mousemove", mouseMove);
  6685. off(display.scroller, "dragstart", dragStart);
  6686. off(display.scroller, "drop", dragEnd);
  6687. if (!moved) {
  6688. e_preventDefault(e);
  6689. if (!behavior.addNew)
  6690. { extendSelection(cm.doc, pos, null, null, behavior.extend); }
  6691. // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
  6692. if ((webkit && !safari) || ie && ie_version == 9)
  6693. { setTimeout(function () {display.wrapper.ownerDocument.body.focus({preventScroll: true}); display.input.focus();}, 20); }
  6694. else
  6695. { display.input.focus(); }
  6696. }
  6697. });
  6698. var mouseMove = function(e2) {
  6699. moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10;
  6700. };
  6701. var dragStart = function () { return moved = true; };
  6702. // Let the drag handler handle this.
  6703. if (webkit) { display.scroller.draggable = true; }
  6704. cm.state.draggingText = dragEnd;
  6705. dragEnd.copy = !behavior.moveOnDrag;
  6706. // IE's approach to draggable
  6707. if (display.scroller.dragDrop) { display.scroller.dragDrop(); }
  6708. on(display.wrapper.ownerDocument, "mouseup", dragEnd);
  6709. on(display.wrapper.ownerDocument, "mousemove", mouseMove);
  6710. on(display.scroller, "dragstart", dragStart);
  6711. on(display.scroller, "drop", dragEnd);
  6712. delayBlurEvent(cm);
  6713. setTimeout(function () { return display.input.focus(); }, 20);
  6714. }
  6715. function rangeForUnit(cm, pos, unit) {
  6716. if (unit == "char") { return new Range(pos, pos) }
  6717. if (unit == "word") { return cm.findWordAt(pos) }
  6718. if (unit == "line") { return new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) }
  6719. var result = unit(cm, pos);
  6720. return new Range(result.from, result.to)
  6721. }
  6722. // Normal selection, as opposed to text dragging.
  6723. function leftButtonSelect(cm, event, start, behavior) {
  6724. var display = cm.display, doc = cm.doc;
  6725. e_preventDefault(event);
  6726. var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;
  6727. if (behavior.addNew && !behavior.extend) {
  6728. ourIndex = doc.sel.contains(start);
  6729. if (ourIndex > -1)
  6730. { ourRange = ranges[ourIndex]; }
  6731. else
  6732. { ourRange = new Range(start, start); }
  6733. } else {
  6734. ourRange = doc.sel.primary();
  6735. ourIndex = doc.sel.primIndex;
  6736. }
  6737. if (behavior.unit == "rectangle") {
  6738. if (!behavior.addNew) { ourRange = new Range(start, start); }
  6739. start = posFromMouse(cm, event, true, true);
  6740. ourIndex = -1;
  6741. } else {
  6742. var range = rangeForUnit(cm, start, behavior.unit);
  6743. if (behavior.extend)
  6744. { ourRange = extendRange(ourRange, range.anchor, range.head, behavior.extend); }
  6745. else
  6746. { ourRange = range; }
  6747. }
  6748. if (!behavior.addNew) {
  6749. ourIndex = 0;
  6750. setSelection(doc, new Selection([ourRange], 0), sel_mouse);
  6751. startSel = doc.sel;
  6752. } else if (ourIndex == -1) {
  6753. ourIndex = ranges.length;
  6754. setSelection(doc, normalizeSelection(cm, ranges.concat([ourRange]), ourIndex),
  6755. {scroll: false, origin: "*mouse"});
  6756. } else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == "char" && !behavior.extend) {
  6757. setSelection(doc, normalizeSelection(cm, ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),
  6758. {scroll: false, origin: "*mouse"});
  6759. startSel = doc.sel;
  6760. } else {
  6761. replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
  6762. }
  6763. var lastPos = start;
  6764. function extendTo(pos) {
  6765. if (cmp(lastPos, pos) == 0) { return }
  6766. lastPos = pos;
  6767. if (behavior.unit == "rectangle") {
  6768. var ranges = [], tabSize = cm.options.tabSize;
  6769. var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize);
  6770. var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize);
  6771. var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);
  6772. for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
  6773. line <= end; line++) {
  6774. var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize);
  6775. if (left == right)
  6776. { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); }
  6777. else if (text.length > leftPos)
  6778. { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); }
  6779. }
  6780. if (!ranges.length) { ranges.push(new Range(start, start)); }
  6781. setSelection(doc, normalizeSelection(cm, startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
  6782. {origin: "*mouse", scroll: false});
  6783. cm.scrollIntoView(pos);
  6784. } else {
  6785. var oldRange = ourRange;
  6786. var range = rangeForUnit(cm, pos, behavior.unit);
  6787. var anchor = oldRange.anchor, head;
  6788. if (cmp(range.anchor, anchor) > 0) {
  6789. head = range.head;
  6790. anchor = minPos(oldRange.from(), range.anchor);
  6791. } else {
  6792. head = range.anchor;
  6793. anchor = maxPos(oldRange.to(), range.head);
  6794. }
  6795. var ranges$1 = startSel.ranges.slice(0);
  6796. ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc, anchor), head));
  6797. setSelection(doc, normalizeSelection(cm, ranges$1, ourIndex), sel_mouse);
  6798. }
  6799. }
  6800. var editorSize = display.wrapper.getBoundingClientRect();
  6801. // Used to ensure timeout re-tries don't fire when another extend
  6802. // happened in the meantime (clearTimeout isn't reliable -- at
  6803. // least on Chrome, the timeouts still happen even when cleared,
  6804. // if the clear happens after their scheduled firing time).
  6805. var counter = 0;
  6806. function extend(e) {
  6807. var curCount = ++counter;
  6808. var cur = posFromMouse(cm, e, true, behavior.unit == "rectangle");
  6809. if (!cur) { return }
  6810. if (cmp(cur, lastPos) != 0) {
  6811. cm.curOp.focus = activeElt();
  6812. extendTo(cur);
  6813. var visible = visibleLines(display, doc);
  6814. if (cur.line >= visible.to || cur.line < visible.from)
  6815. { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e); }}), 150); }
  6816. } else {
  6817. var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0;
  6818. if (outside) { setTimeout(operation(cm, function () {
  6819. if (counter != curCount) { return }
  6820. display.scroller.scrollTop += outside;
  6821. extend(e);
  6822. }), 50); }
  6823. }
  6824. }
  6825. function done(e) {
  6826. cm.state.selectingText = false;
  6827. counter = Infinity;
  6828. // If e is null or undefined we interpret this as someone trying
  6829. // to explicitly cancel the selection rather than the user
  6830. // letting go of the mouse button.
  6831. if (e) {
  6832. e_preventDefault(e);
  6833. display.input.focus();
  6834. }
  6835. off(display.wrapper.ownerDocument, "mousemove", move);
  6836. off(display.wrapper.ownerDocument, "mouseup", up);
  6837. doc.history.lastSelOrigin = null;
  6838. }
  6839. var move = operation(cm, function (e) {
  6840. if (e.buttons === 0 || !e_button(e)) { done(e); }
  6841. else { extend(e); }
  6842. });
  6843. var up = operation(cm, done);
  6844. cm.state.selectingText = up;
  6845. on(display.wrapper.ownerDocument, "mousemove", move);
  6846. on(display.wrapper.ownerDocument, "mouseup", up);
  6847. }
  6848. // Used when mouse-selecting to adjust the anchor to the proper side
  6849. // of a bidi jump depending on the visual position of the head.
  6850. function bidiSimplify(cm, range) {
  6851. var anchor = range.anchor;
  6852. var head = range.head;
  6853. var anchorLine = getLine(cm.doc, anchor.line);
  6854. if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range }
  6855. var order = getOrder(anchorLine);
  6856. if (!order) { return range }
  6857. var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index];
  6858. if (part.from != anchor.ch && part.to != anchor.ch) { return range }
  6859. var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1);
  6860. if (boundary == 0 || boundary == order.length) { return range }
  6861. // Compute the relative visual position of the head compared to the
  6862. // anchor (<0 is to the left, >0 to the right)
  6863. var leftSide;
  6864. if (head.line != anchor.line) {
  6865. leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0;
  6866. } else {
  6867. var headIndex = getBidiPartAt(order, head.ch, head.sticky);
  6868. var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1);
  6869. if (headIndex == boundary - 1 || headIndex == boundary)
  6870. { leftSide = dir < 0; }
  6871. else
  6872. { leftSide = dir > 0; }
  6873. }
  6874. var usePart = order[boundary + (leftSide ? -1 : 0)];
  6875. var from = leftSide == (usePart.level == 1);
  6876. var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before";
  6877. return anchor.ch == ch && anchor.sticky == sticky ? range : new Range(new Pos(anchor.line, ch, sticky), head)
  6878. }
  6879. // Determines whether an event happened in the gutter, and fires the
  6880. // handlers for the corresponding event.
  6881. function gutterEvent(cm, e, type, prevent) {
  6882. var mX, mY;
  6883. if (e.touches) {
  6884. mX = e.touches[0].clientX;
  6885. mY = e.touches[0].clientY;
  6886. } else {
  6887. try { mX = e.clientX; mY = e.clientY; }
  6888. catch(e$1) { return false }
  6889. }
  6890. if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false }
  6891. if (prevent) { e_preventDefault(e); }
  6892. var display = cm.display;
  6893. var lineBox = display.lineDiv.getBoundingClientRect();
  6894. if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) }
  6895. mY -= lineBox.top - display.viewOffset;
  6896. for (var i = 0; i < cm.display.gutterSpecs.length; ++i) {
  6897. var g = display.gutters.childNodes[i];
  6898. if (g && g.getBoundingClientRect().right >= mX) {
  6899. var line = lineAtHeight(cm.doc, mY);
  6900. var gutter = cm.display.gutterSpecs[i];
  6901. signal(cm, type, cm, line, gutter.className, e);
  6902. return e_defaultPrevented(e)
  6903. }
  6904. }
  6905. }
  6906. function clickInGutter(cm, e) {
  6907. return gutterEvent(cm, e, "gutterClick", true)
  6908. }
  6909. // CONTEXT MENU HANDLING
  6910. // To make the context menu work, we need to briefly unhide the
  6911. // textarea (making it as unobtrusive as possible) to let the
  6912. // right-click take effect on it.
  6913. function onContextMenu(cm, e) {
  6914. if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return }
  6915. if (signalDOMEvent(cm, e, "contextmenu")) { return }
  6916. if (!captureRightClick) { cm.display.input.onContextMenu(e); }
  6917. }
  6918. function contextMenuInGutter(cm, e) {
  6919. if (!hasHandler(cm, "gutterContextMenu")) { return false }
  6920. return gutterEvent(cm, e, "gutterContextMenu", false)
  6921. }
  6922. function themeChanged(cm) {
  6923. cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
  6924. cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-");
  6925. clearCaches(cm);
  6926. }
  6927. var Init = {toString: function(){return "CodeMirror.Init"}};
  6928. var defaults = {};
  6929. var optionHandlers = {};
  6930. function defineOptions(CodeMirror) {
  6931. var optionHandlers = CodeMirror.optionHandlers;
  6932. function option(name, deflt, handle, notOnInit) {
  6933. CodeMirror.defaults[name] = deflt;
  6934. if (handle) { optionHandlers[name] =
  6935. notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old); }} : handle; }
  6936. }
  6937. CodeMirror.defineOption = option;
  6938. // Passed to option handlers when there is no old value.
  6939. CodeMirror.Init = Init;
  6940. // These two are, on init, called from the constructor because they
  6941. // have to be initialized before the editor can start at all.
  6942. option("value", "", function (cm, val) { return cm.setValue(val); }, true);
  6943. option("mode", null, function (cm, val) {
  6944. cm.doc.modeOption = val;
  6945. loadMode(cm);
  6946. }, true);
  6947. option("indentUnit", 2, loadMode, true);
  6948. option("indentWithTabs", false);
  6949. option("smartIndent", true);
  6950. option("tabSize", 4, function (cm) {
  6951. resetModeState(cm);
  6952. clearCaches(cm);
  6953. regChange(cm);
  6954. }, true);
  6955. option("lineSeparator", null, function (cm, val) {
  6956. cm.doc.lineSep = val;
  6957. if (!val) { return }
  6958. var newBreaks = [], lineNo = cm.doc.first;
  6959. cm.doc.iter(function (line) {
  6960. for (var pos = 0;;) {
  6961. var found = line.text.indexOf(val, pos);
  6962. if (found == -1) { break }
  6963. pos = found + val.length;
  6964. newBreaks.push(Pos(lineNo, found));
  6965. }
  6966. lineNo++;
  6967. });
  6968. for (var i = newBreaks.length - 1; i >= 0; i--)
  6969. { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); }
  6970. });
  6971. option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200c\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, function (cm, val, old) {
  6972. cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
  6973. if (old != Init) { cm.refresh(); }
  6974. });
  6975. option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true);
  6976. option("electricChars", true);
  6977. option("inputStyle", mobile ? "contenteditable" : "textarea", function () {
  6978. throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME
  6979. }, true);
  6980. option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true);
  6981. option("autocorrect", false, function (cm, val) { return cm.getInputField().autocorrect = val; }, true);
  6982. option("autocapitalize", false, function (cm, val) { return cm.getInputField().autocapitalize = val; }, true);
  6983. option("rtlMoveVisually", !windows);
  6984. option("wholeLineUpdateBefore", true);
  6985. option("theme", "default", function (cm) {
  6986. themeChanged(cm);
  6987. updateGutters(cm);
  6988. }, true);
  6989. option("keyMap", "default", function (cm, val, old) {
  6990. var next = getKeyMap(val);
  6991. var prev = old != Init && getKeyMap(old);
  6992. if (prev && prev.detach) { prev.detach(cm, next); }
  6993. if (next.attach) { next.attach(cm, prev || null); }
  6994. });
  6995. option("extraKeys", null);
  6996. option("configureMouse", null);
  6997. option("lineWrapping", false, wrappingChanged, true);
  6998. option("gutters", [], function (cm, val) {
  6999. cm.display.gutterSpecs = getGutters(val, cm.options.lineNumbers);
  7000. updateGutters(cm);
  7001. }, true);
  7002. option("fixedGutter", true, function (cm, val) {
  7003. cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0";
  7004. cm.refresh();
  7005. }, true);
  7006. option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true);
  7007. option("scrollbarStyle", "native", function (cm) {
  7008. initScrollbars(cm);
  7009. updateScrollbars(cm);
  7010. cm.display.scrollbars.setScrollTop(cm.doc.scrollTop);
  7011. cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft);
  7012. }, true);
  7013. option("lineNumbers", false, function (cm, val) {
  7014. cm.display.gutterSpecs = getGutters(cm.options.gutters, val);
  7015. updateGutters(cm);
  7016. }, true);
  7017. option("firstLineNumber", 1, updateGutters, true);
  7018. option("lineNumberFormatter", function (integer) { return integer; }, updateGutters, true);
  7019. option("showCursorWhenSelecting", false, updateSelection, true);
  7020. option("resetSelectionOnContextMenu", true);
  7021. option("lineWiseCopyCut", true);
  7022. option("pasteLinesPerSelection", true);
  7023. option("selectionsMayTouch", false);
  7024. option("readOnly", false, function (cm, val) {
  7025. if (val == "nocursor") {
  7026. onBlur(cm);
  7027. cm.display.input.blur();
  7028. }
  7029. cm.display.input.readOnlyChanged(val);
  7030. });
  7031. option("screenReaderLabel", null, function (cm, val) {
  7032. val = (val === '') ? null : val;
  7033. cm.display.input.screenReaderLabelChanged(val);
  7034. });
  7035. option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset(); }}, true);
  7036. option("dragDrop", true, dragDropChanged);
  7037. option("allowDropFileTypes", null);
  7038. option("cursorBlinkRate", 530);
  7039. option("cursorScrollMargin", 0);
  7040. option("cursorHeight", 1, updateSelection, true);
  7041. option("singleCursorHeightPerLine", true, updateSelection, true);
  7042. option("workTime", 100);
  7043. option("workDelay", 100);
  7044. option("flattenSpans", true, resetModeState, true);
  7045. option("addModeClass", false, resetModeState, true);
  7046. option("pollInterval", 100);
  7047. option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; });
  7048. option("historyEventDelay", 1250);
  7049. option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true);
  7050. option("maxHighlightLength", 10000, resetModeState, true);
  7051. option("moveInputWithCursor", true, function (cm, val) {
  7052. if (!val) { cm.display.input.resetPosition(); }
  7053. });
  7054. option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; });
  7055. option("autofocus", null);
  7056. option("direction", "ltr", function (cm, val) { return cm.doc.setDirection(val); }, true);
  7057. option("phrases", null);
  7058. }
  7059. function dragDropChanged(cm, value, old) {
  7060. var wasOn = old && old != Init;
  7061. if (!value != !wasOn) {
  7062. var funcs = cm.display.dragFunctions;
  7063. var toggle = value ? on : off;
  7064. toggle(cm.display.scroller, "dragstart", funcs.start);
  7065. toggle(cm.display.scroller, "dragenter", funcs.enter);
  7066. toggle(cm.display.scroller, "dragover", funcs.over);
  7067. toggle(cm.display.scroller, "dragleave", funcs.leave);
  7068. toggle(cm.display.scroller, "drop", funcs.drop);
  7069. }
  7070. }
  7071. function wrappingChanged(cm) {
  7072. if (cm.options.lineWrapping) {
  7073. addClass(cm.display.wrapper, "CodeMirror-wrap");
  7074. cm.display.sizer.style.minWidth = "";
  7075. cm.display.sizerWidth = null;
  7076. } else {
  7077. rmClass(cm.display.wrapper, "CodeMirror-wrap");
  7078. findMaxLine(cm);
  7079. }
  7080. estimateLineHeights(cm);
  7081. regChange(cm);
  7082. clearCaches(cm);
  7083. setTimeout(function () { return updateScrollbars(cm); }, 100);
  7084. }
  7085. // A CodeMirror instance represents an editor. This is the object
  7086. // that user code is usually dealing with.
  7087. function CodeMirror(place, options) {
  7088. var this$1 = this;
  7089. if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) }
  7090. this.options = options = options ? copyObj(options) : {};
  7091. // Determine effective options based on given values and defaults.
  7092. copyObj(defaults, options, false);
  7093. var doc = options.value;
  7094. if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction); }
  7095. else if (options.mode) { doc.modeOption = options.mode; }
  7096. this.doc = doc;
  7097. var input = new CodeMirror.inputStyles[options.inputStyle](this);
  7098. var display = this.display = new Display(place, doc, input, options);
  7099. display.wrapper.CodeMirror = this;
  7100. themeChanged(this);
  7101. if (options.lineWrapping)
  7102. { this.display.wrapper.className += " CodeMirror-wrap"; }
  7103. initScrollbars(this);
  7104. this.state = {
  7105. keyMaps: [], // stores maps added by addKeyMap
  7106. overlays: [], // highlighting overlays, as added by addOverlay
  7107. modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info
  7108. overwrite: false,
  7109. delayingBlurEvent: false,
  7110. focused: false,
  7111. suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
  7112. pasteIncoming: -1, cutIncoming: -1, // help recognize paste/cut edits in input.poll
  7113. selectingText: false,
  7114. draggingText: false,
  7115. highlight: new Delayed(), // stores highlight worker timeout
  7116. keySeq: null, // Unfinished key sequence
  7117. specialChars: null
  7118. };
  7119. if (options.autofocus && !mobile) { display.input.focus(); }
  7120. // Override magic textarea content restore that IE sometimes does
  7121. // on our hidden textarea on reload
  7122. if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20); }
  7123. registerEventHandlers(this);
  7124. ensureGlobalHandlers();
  7125. startOperation(this);
  7126. this.curOp.forceUpdate = true;
  7127. attachDoc(this, doc);
  7128. if ((options.autofocus && !mobile) || this.hasFocus())
  7129. { setTimeout(bind(onFocus, this), 20); }
  7130. else
  7131. { onBlur(this); }
  7132. for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt))
  7133. { optionHandlers[opt](this, options[opt], Init); } }
  7134. maybeUpdateLineNumberWidth(this);
  7135. if (options.finishInit) { options.finishInit(this); }
  7136. for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this); }
  7137. endOperation(this);
  7138. // Suppress optimizelegibility in Webkit, since it breaks text
  7139. // measuring on line wrapping boundaries.
  7140. if (webkit && options.lineWrapping &&
  7141. getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
  7142. { display.lineDiv.style.textRendering = "auto"; }
  7143. }
  7144. // The default configuration options.
  7145. CodeMirror.defaults = defaults;
  7146. // Functions to run when options are changed.
  7147. CodeMirror.optionHandlers = optionHandlers;
  7148. // Attach the necessary event handlers when initializing the editor
  7149. function registerEventHandlers(cm) {
  7150. var d = cm.display;
  7151. on(d.scroller, "mousedown", operation(cm, onMouseDown));
  7152. // Older IE's will not fire a second mousedown for a double click
  7153. if (ie && ie_version < 11)
  7154. { on(d.scroller, "dblclick", operation(cm, function (e) {
  7155. if (signalDOMEvent(cm, e)) { return }
  7156. var pos = posFromMouse(cm, e);
  7157. if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return }
  7158. e_preventDefault(e);
  7159. var word = cm.findWordAt(pos);
  7160. extendSelection(cm.doc, word.anchor, word.head);
  7161. })); }
  7162. else
  7163. { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }); }
  7164. // Some browsers fire contextmenu *after* opening the menu, at
  7165. // which point we can't mess with it anymore. Context menu is
  7166. // handled in onMouseDown for these browsers.
  7167. on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); });
  7168. on(d.input.getField(), "contextmenu", function (e) {
  7169. if (!d.scroller.contains(e.target)) { onContextMenu(cm, e); }
  7170. });
  7171. // Used to suppress mouse event handling when a touch happens
  7172. var touchFinished, prevTouch = {end: 0};
  7173. function finishTouch() {
  7174. if (d.activeTouch) {
  7175. touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000);
  7176. prevTouch = d.activeTouch;
  7177. prevTouch.end = +new Date;
  7178. }
  7179. }
  7180. function isMouseLikeTouchEvent(e) {
  7181. if (e.touches.length != 1) { return false }
  7182. var touch = e.touches[0];
  7183. return touch.radiusX <= 1 && touch.radiusY <= 1
  7184. }
  7185. function farAway(touch, other) {
  7186. if (other.left == null) { return true }
  7187. var dx = other.left - touch.left, dy = other.top - touch.top;
  7188. return dx * dx + dy * dy > 20 * 20
  7189. }
  7190. on(d.scroller, "touchstart", function (e) {
  7191. if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) {
  7192. d.input.ensurePolled();
  7193. clearTimeout(touchFinished);
  7194. var now = +new Date;
  7195. d.activeTouch = {start: now, moved: false,
  7196. prev: now - prevTouch.end <= 300 ? prevTouch : null};
  7197. if (e.touches.length == 1) {
  7198. d.activeTouch.left = e.touches[0].pageX;
  7199. d.activeTouch.top = e.touches[0].pageY;
  7200. }
  7201. }
  7202. });
  7203. on(d.scroller, "touchmove", function () {
  7204. if (d.activeTouch) { d.activeTouch.moved = true; }
  7205. });
  7206. on(d.scroller, "touchend", function (e) {
  7207. var touch = d.activeTouch;
  7208. if (touch && !eventInWidget(d, e) && touch.left != null &&
  7209. !touch.moved && new Date - touch.start < 300) {
  7210. var pos = cm.coordsChar(d.activeTouch, "page"), range;
  7211. if (!touch.prev || farAway(touch, touch.prev)) // Single tap
  7212. { range = new Range(pos, pos); }
  7213. else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
  7214. { range = cm.findWordAt(pos); }
  7215. else // Triple tap
  7216. { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); }
  7217. cm.setSelection(range.anchor, range.head);
  7218. cm.focus();
  7219. e_preventDefault(e);
  7220. }
  7221. finishTouch();
  7222. });
  7223. on(d.scroller, "touchcancel", finishTouch);
  7224. // Sync scrolling between fake scrollbars and real scrollable
  7225. // area, ensure viewport is updated when scrolling.
  7226. on(d.scroller, "scroll", function () {
  7227. if (d.scroller.clientHeight) {
  7228. updateScrollTop(cm, d.scroller.scrollTop);
  7229. setScrollLeft(cm, d.scroller.scrollLeft, true);
  7230. signal(cm, "scroll", cm);
  7231. }
  7232. });
  7233. // Listen to wheel events in order to try and update the viewport on time.
  7234. on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); });
  7235. on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); });
  7236. // Prevent wrapper from ever scrolling
  7237. on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; });
  7238. d.dragFunctions = {
  7239. enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e); }},
  7240. over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }},
  7241. start: function (e) { return onDragStart(cm, e); },
  7242. drop: operation(cm, onDrop),
  7243. leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }}
  7244. };
  7245. var inp = d.input.getField();
  7246. on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); });
  7247. on(inp, "keydown", operation(cm, onKeyDown));
  7248. on(inp, "keypress", operation(cm, onKeyPress));
  7249. on(inp, "focus", function (e) { return onFocus(cm, e); });
  7250. on(inp, "blur", function (e) { return onBlur(cm, e); });
  7251. }
  7252. var initHooks = [];
  7253. CodeMirror.defineInitHook = function (f) { return initHooks.push(f); };
  7254. // Indent the given line. The how parameter can be "smart",
  7255. // "add"/null, "subtract", or "prev". When aggressive is false
  7256. // (typically set to true for forced single-line indents), empty
  7257. // lines are not indented, and places where the mode returns Pass
  7258. // are left alone.
  7259. function indentLine(cm, n, how, aggressive) {
  7260. var doc = cm.doc, state;
  7261. if (how == null) { how = "add"; }
  7262. if (how == "smart") {
  7263. // Fall back to "prev" when the mode doesn't have an indentation
  7264. // method.
  7265. if (!doc.mode.indent) { how = "prev"; }
  7266. else { state = getContextBefore(cm, n).state; }
  7267. }
  7268. var tabSize = cm.options.tabSize;
  7269. var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize);
  7270. if (line.stateAfter) { line.stateAfter = null; }
  7271. var curSpaceString = line.text.match(/^\s*/)[0], indentation;
  7272. if (!aggressive && !/\S/.test(line.text)) {
  7273. indentation = 0;
  7274. how = "not";
  7275. } else if (how == "smart") {
  7276. indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text);
  7277. if (indentation == Pass || indentation > 150) {
  7278. if (!aggressive) { return }
  7279. how = "prev";
  7280. }
  7281. }
  7282. if (how == "prev") {
  7283. if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize); }
  7284. else { indentation = 0; }
  7285. } else if (how == "add") {
  7286. indentation = curSpace + cm.options.indentUnit;
  7287. } else if (how == "subtract") {
  7288. indentation = curSpace - cm.options.indentUnit;
  7289. } else if (typeof how == "number") {
  7290. indentation = curSpace + how;
  7291. }
  7292. indentation = Math.max(0, indentation);
  7293. var indentString = "", pos = 0;
  7294. if (cm.options.indentWithTabs)
  7295. { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} }
  7296. if (pos < indentation) { indentString += spaceStr(indentation - pos); }
  7297. if (indentString != curSpaceString) {
  7298. replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input");
  7299. line.stateAfter = null;
  7300. return true
  7301. } else {
  7302. // Ensure that, if the cursor was in the whitespace at the start
  7303. // of the line, it is moved to the end of that space.
  7304. for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) {
  7305. var range = doc.sel.ranges[i$1];
  7306. if (range.head.line == n && range.head.ch < curSpaceString.length) {
  7307. var pos$1 = Pos(n, curSpaceString.length);
  7308. replaceOneSelection(doc, i$1, new Range(pos$1, pos$1));
  7309. break
  7310. }
  7311. }
  7312. }
  7313. }
  7314. // This will be set to a {lineWise: bool, text: [string]} object, so
  7315. // that, when pasting, we know what kind of selections the copied
  7316. // text was made out of.
  7317. var lastCopied = null;
  7318. function setLastCopied(newLastCopied) {
  7319. lastCopied = newLastCopied;
  7320. }
  7321. function applyTextInput(cm, inserted, deleted, sel, origin) {
  7322. var doc = cm.doc;
  7323. cm.display.shift = false;
  7324. if (!sel) { sel = doc.sel; }
  7325. var recent = +new Date - 200;
  7326. var paste = origin == "paste" || cm.state.pasteIncoming > recent;
  7327. var textLines = splitLinesAuto(inserted), multiPaste = null;
  7328. // When pasting N lines into N selections, insert one line per selection
  7329. if (paste && sel.ranges.length > 1) {
  7330. if (lastCopied && lastCopied.text.join("\n") == inserted) {
  7331. if (sel.ranges.length % lastCopied.text.length == 0) {
  7332. multiPaste = [];
  7333. for (var i = 0; i < lastCopied.text.length; i++)
  7334. { multiPaste.push(doc.splitLines(lastCopied.text[i])); }
  7335. }
  7336. } else if (textLines.length == sel.ranges.length && cm.options.pasteLinesPerSelection) {
  7337. multiPaste = map(textLines, function (l) { return [l]; });
  7338. }
  7339. }
  7340. var updateInput = cm.curOp.updateInput;
  7341. // Normal behavior is to insert the new text into every selection
  7342. for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) {
  7343. var range = sel.ranges[i$1];
  7344. var from = range.from(), to = range.to();
  7345. if (range.empty()) {
  7346. if (deleted && deleted > 0) // Handle deletion
  7347. { from = Pos(from.line, from.ch - deleted); }
  7348. else if (cm.state.overwrite && !paste) // Handle overwrite
  7349. { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); }
  7350. else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == textLines.join("\n"))
  7351. { from = to = Pos(from.line, 0); }
  7352. }
  7353. var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines,
  7354. origin: origin || (paste ? "paste" : cm.state.cutIncoming > recent ? "cut" : "+input")};
  7355. makeChange(cm.doc, changeEvent);
  7356. signalLater(cm, "inputRead", cm, changeEvent);
  7357. }
  7358. if (inserted && !paste)
  7359. { triggerElectric(cm, inserted); }
  7360. ensureCursorVisible(cm);
  7361. if (cm.curOp.updateInput < 2) { cm.curOp.updateInput = updateInput; }
  7362. cm.curOp.typing = true;
  7363. cm.state.pasteIncoming = cm.state.cutIncoming = -1;
  7364. }
  7365. function handlePaste(e, cm) {
  7366. var pasted = e.clipboardData && e.clipboardData.getData("Text");
  7367. if (pasted) {
  7368. e.preventDefault();
  7369. if (!cm.isReadOnly() && !cm.options.disableInput)
  7370. { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }); }
  7371. return true
  7372. }
  7373. }
  7374. function triggerElectric(cm, inserted) {
  7375. // When an 'electric' character is inserted, immediately trigger a reindent
  7376. if (!cm.options.electricChars || !cm.options.smartIndent) { return }
  7377. var sel = cm.doc.sel;
  7378. for (var i = sel.ranges.length - 1; i >= 0; i--) {
  7379. var range = sel.ranges[i];
  7380. if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) { continue }
  7381. var mode = cm.getModeAt(range.head);
  7382. var indented = false;
  7383. if (mode.electricChars) {
  7384. for (var j = 0; j < mode.electricChars.length; j++)
  7385. { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
  7386. indented = indentLine(cm, range.head.line, "smart");
  7387. break
  7388. } }
  7389. } else if (mode.electricInput) {
  7390. if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
  7391. { indented = indentLine(cm, range.head.line, "smart"); }
  7392. }
  7393. if (indented) { signalLater(cm, "electricInput", cm, range.head.line); }
  7394. }
  7395. }
  7396. function copyableRanges(cm) {
  7397. var text = [], ranges = [];
  7398. for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
  7399. var line = cm.doc.sel.ranges[i].head.line;
  7400. var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)};
  7401. ranges.push(lineRange);
  7402. text.push(cm.getRange(lineRange.anchor, lineRange.head));
  7403. }
  7404. return {text: text, ranges: ranges}
  7405. }
  7406. function disableBrowserMagic(field, spellcheck, autocorrect, autocapitalize) {
  7407. field.setAttribute("autocorrect", autocorrect ? "" : "off");
  7408. field.setAttribute("autocapitalize", autocapitalize ? "" : "off");
  7409. field.setAttribute("spellcheck", !!spellcheck);
  7410. }
  7411. function hiddenTextarea() {
  7412. var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none");
  7413. var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
  7414. // The textarea is kept positioned near the cursor to prevent the
  7415. // fact that it'll be scrolled into view on input from scrolling
  7416. // our fake cursor out of view. On webkit, when wrap=off, paste is
  7417. // very slow. So make the area wide instead.
  7418. if (webkit) { te.style.width = "1000px"; }
  7419. else { te.setAttribute("wrap", "off"); }
  7420. // If border: 0; -- iOS fails to open keyboard (issue #1287)
  7421. if (ios) { te.style.border = "1px solid black"; }
  7422. disableBrowserMagic(te);
  7423. return div
  7424. }
  7425. // The publicly visible API. Note that methodOp(f) means
  7426. // 'wrap f in an operation, performed on its `this` parameter'.
  7427. // This is not the complete set of editor methods. Most of the
  7428. // methods defined on the Doc type are also injected into
  7429. // CodeMirror.prototype, for backwards compatibility and
  7430. // convenience.
  7431. function addEditorMethods(CodeMirror) {
  7432. var optionHandlers = CodeMirror.optionHandlers;
  7433. var helpers = CodeMirror.helpers = {};
  7434. CodeMirror.prototype = {
  7435. constructor: CodeMirror,
  7436. focus: function(){window.focus(); this.display.input.focus();},
  7437. setOption: function(option, value) {
  7438. var options = this.options, old = options[option];
  7439. if (options[option] == value && option != "mode") { return }
  7440. options[option] = value;
  7441. if (optionHandlers.hasOwnProperty(option))
  7442. { operation(this, optionHandlers[option])(this, value, old); }
  7443. signal(this, "optionChange", this, option);
  7444. },
  7445. getOption: function(option) {return this.options[option]},
  7446. getDoc: function() {return this.doc},
  7447. addKeyMap: function(map, bottom) {
  7448. this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map));
  7449. },
  7450. removeKeyMap: function(map) {
  7451. var maps = this.state.keyMaps;
  7452. for (var i = 0; i < maps.length; ++i)
  7453. { if (maps[i] == map || maps[i].name == map) {
  7454. maps.splice(i, 1);
  7455. return true
  7456. } }
  7457. },
  7458. addOverlay: methodOp(function(spec, options) {
  7459. var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec);
  7460. if (mode.startState) { throw new Error("Overlays may not be stateful.") }
  7461. insertSorted(this.state.overlays,
  7462. {mode: mode, modeSpec: spec, opaque: options && options.opaque,
  7463. priority: (options && options.priority) || 0},
  7464. function (overlay) { return overlay.priority; });
  7465. this.state.modeGen++;
  7466. regChange(this);
  7467. }),
  7468. removeOverlay: methodOp(function(spec) {
  7469. var overlays = this.state.overlays;
  7470. for (var i = 0; i < overlays.length; ++i) {
  7471. var cur = overlays[i].modeSpec;
  7472. if (cur == spec || typeof spec == "string" && cur.name == spec) {
  7473. overlays.splice(i, 1);
  7474. this.state.modeGen++;
  7475. regChange(this);
  7476. return
  7477. }
  7478. }
  7479. }),
  7480. indentLine: methodOp(function(n, dir, aggressive) {
  7481. if (typeof dir != "string" && typeof dir != "number") {
  7482. if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev"; }
  7483. else { dir = dir ? "add" : "subtract"; }
  7484. }
  7485. if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive); }
  7486. }),
  7487. indentSelection: methodOp(function(how) {
  7488. var ranges = this.doc.sel.ranges, end = -1;
  7489. for (var i = 0; i < ranges.length; i++) {
  7490. var range = ranges[i];
  7491. if (!range.empty()) {
  7492. var from = range.from(), to = range.to();
  7493. var start = Math.max(end, from.line);
  7494. end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
  7495. for (var j = start; j < end; ++j)
  7496. { indentLine(this, j, how); }
  7497. var newRanges = this.doc.sel.ranges;
  7498. if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
  7499. { replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); }
  7500. } else if (range.head.line > end) {
  7501. indentLine(this, range.head.line, how, true);
  7502. end = range.head.line;
  7503. if (i == this.doc.sel.primIndex) { ensureCursorVisible(this); }
  7504. }
  7505. }
  7506. }),
  7507. // Fetch the parser token for a given character. Useful for hacks
  7508. // that want to inspect the mode state (say, for completion).
  7509. getTokenAt: function(pos, precise) {
  7510. return takeToken(this, pos, precise)
  7511. },
  7512. getLineTokens: function(line, precise) {
  7513. return takeToken(this, Pos(line), precise, true)
  7514. },
  7515. getTokenTypeAt: function(pos) {
  7516. pos = clipPos(this.doc, pos);
  7517. var styles = getLineStyles(this, getLine(this.doc, pos.line));
  7518. var before = 0, after = (styles.length - 1) / 2, ch = pos.ch;
  7519. var type;
  7520. if (ch == 0) { type = styles[2]; }
  7521. else { for (;;) {
  7522. var mid = (before + after) >> 1;
  7523. if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid; }
  7524. else if (styles[mid * 2 + 1] < ch) { before = mid + 1; }
  7525. else { type = styles[mid * 2 + 2]; break }
  7526. } }
  7527. var cut = type ? type.indexOf("overlay ") : -1;
  7528. return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1)
  7529. },
  7530. getModeAt: function(pos) {
  7531. var mode = this.doc.mode;
  7532. if (!mode.innerMode) { return mode }
  7533. return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode
  7534. },
  7535. getHelper: function(pos, type) {
  7536. return this.getHelpers(pos, type)[0]
  7537. },
  7538. getHelpers: function(pos, type) {
  7539. var found = [];
  7540. if (!helpers.hasOwnProperty(type)) { return found }
  7541. var help = helpers[type], mode = this.getModeAt(pos);
  7542. if (typeof mode[type] == "string") {
  7543. if (help[mode[type]]) { found.push(help[mode[type]]); }
  7544. } else if (mode[type]) {
  7545. for (var i = 0; i < mode[type].length; i++) {
  7546. var val = help[mode[type][i]];
  7547. if (val) { found.push(val); }
  7548. }
  7549. } else if (mode.helperType && help[mode.helperType]) {
  7550. found.push(help[mode.helperType]);
  7551. } else if (help[mode.name]) {
  7552. found.push(help[mode.name]);
  7553. }
  7554. for (var i$1 = 0; i$1 < help._global.length; i$1++) {
  7555. var cur = help._global[i$1];
  7556. if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)
  7557. { found.push(cur.val); }
  7558. }
  7559. return found
  7560. },
  7561. getStateAfter: function(line, precise) {
  7562. var doc = this.doc;
  7563. line = clipLine(doc, line == null ? doc.first + doc.size - 1: line);
  7564. return getContextBefore(this, line + 1, precise).state
  7565. },
  7566. cursorCoords: function(start, mode) {
  7567. var pos, range = this.doc.sel.primary();
  7568. if (start == null) { pos = range.head; }
  7569. else if (typeof start == "object") { pos = clipPos(this.doc, start); }
  7570. else { pos = start ? range.from() : range.to(); }
  7571. return cursorCoords(this, pos, mode || "page")
  7572. },
  7573. charCoords: function(pos, mode) {
  7574. return charCoords(this, clipPos(this.doc, pos), mode || "page")
  7575. },
  7576. coordsChar: function(coords, mode) {
  7577. coords = fromCoordSystem(this, coords, mode || "page");
  7578. return coordsChar(this, coords.left, coords.top)
  7579. },
  7580. lineAtHeight: function(height, mode) {
  7581. height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top;
  7582. return lineAtHeight(this.doc, height + this.display.viewOffset)
  7583. },
  7584. heightAtLine: function(line, mode, includeWidgets) {
  7585. var end = false, lineObj;
  7586. if (typeof line == "number") {
  7587. var last = this.doc.first + this.doc.size - 1;
  7588. if (line < this.doc.first) { line = this.doc.first; }
  7589. else if (line > last) { line = last; end = true; }
  7590. lineObj = getLine(this.doc, line);
  7591. } else {
  7592. lineObj = line;
  7593. }
  7594. return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets || end).top +
  7595. (end ? this.doc.height - heightAtLine(lineObj) : 0)
  7596. },
  7597. defaultTextHeight: function() { return textHeight(this.display) },
  7598. defaultCharWidth: function() { return charWidth(this.display) },
  7599. getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}},
  7600. addWidget: function(pos, node, scroll, vert, horiz) {
  7601. var display = this.display;
  7602. pos = cursorCoords(this, clipPos(this.doc, pos));
  7603. var top = pos.bottom, left = pos.left;
  7604. node.style.position = "absolute";
  7605. node.setAttribute("cm-ignore-events", "true");
  7606. this.display.input.setUneditable(node);
  7607. display.sizer.appendChild(node);
  7608. if (vert == "over") {
  7609. top = pos.top;
  7610. } else if (vert == "above" || vert == "near") {
  7611. var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
  7612. hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth);
  7613. // Default to positioning above (if specified and possible); otherwise default to positioning below
  7614. if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
  7615. { top = pos.top - node.offsetHeight; }
  7616. else if (pos.bottom + node.offsetHeight <= vspace)
  7617. { top = pos.bottom; }
  7618. if (left + node.offsetWidth > hspace)
  7619. { left = hspace - node.offsetWidth; }
  7620. }
  7621. node.style.top = top + "px";
  7622. node.style.left = node.style.right = "";
  7623. if (horiz == "right") {
  7624. left = display.sizer.clientWidth - node.offsetWidth;
  7625. node.style.right = "0px";
  7626. } else {
  7627. if (horiz == "left") { left = 0; }
  7628. else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2; }
  7629. node.style.left = left + "px";
  7630. }
  7631. if (scroll)
  7632. { scrollIntoView(this, {left: left, top: top, right: left + node.offsetWidth, bottom: top + node.offsetHeight}); }
  7633. },
  7634. triggerOnKeyDown: methodOp(onKeyDown),
  7635. triggerOnKeyPress: methodOp(onKeyPress),
  7636. triggerOnKeyUp: onKeyUp,
  7637. triggerOnMouseDown: methodOp(onMouseDown),
  7638. execCommand: function(cmd) {
  7639. if (commands.hasOwnProperty(cmd))
  7640. { return commands[cmd].call(null, this) }
  7641. },
  7642. triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),
  7643. findPosH: function(from, amount, unit, visually) {
  7644. var dir = 1;
  7645. if (amount < 0) { dir = -1; amount = -amount; }
  7646. var cur = clipPos(this.doc, from);
  7647. for (var i = 0; i < amount; ++i) {
  7648. cur = findPosH(this.doc, cur, dir, unit, visually);
  7649. if (cur.hitSide) { break }
  7650. }
  7651. return cur
  7652. },
  7653. moveH: methodOp(function(dir, unit) {
  7654. var this$1 = this;
  7655. this.extendSelectionsBy(function (range) {
  7656. if (this$1.display.shift || this$1.doc.extend || range.empty())
  7657. { return findPosH(this$1.doc, range.head, dir, unit, this$1.options.rtlMoveVisually) }
  7658. else
  7659. { return dir < 0 ? range.from() : range.to() }
  7660. }, sel_move);
  7661. }),
  7662. deleteH: methodOp(function(dir, unit) {
  7663. var sel = this.doc.sel, doc = this.doc;
  7664. if (sel.somethingSelected())
  7665. { doc.replaceSelection("", null, "+delete"); }
  7666. else
  7667. { deleteNearSelection(this, function (range) {
  7668. var other = findPosH(doc, range.head, dir, unit, false);
  7669. return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other}
  7670. }); }
  7671. }),
  7672. findPosV: function(from, amount, unit, goalColumn) {
  7673. var dir = 1, x = goalColumn;
  7674. if (amount < 0) { dir = -1; amount = -amount; }
  7675. var cur = clipPos(this.doc, from);
  7676. for (var i = 0; i < amount; ++i) {
  7677. var coords = cursorCoords(this, cur, "div");
  7678. if (x == null) { x = coords.left; }
  7679. else { coords.left = x; }
  7680. cur = findPosV(this, coords, dir, unit);
  7681. if (cur.hitSide) { break }
  7682. }
  7683. return cur
  7684. },
  7685. moveV: methodOp(function(dir, unit) {
  7686. var this$1 = this;
  7687. var doc = this.doc, goals = [];
  7688. var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected();
  7689. doc.extendSelectionsBy(function (range) {
  7690. if (collapse)
  7691. { return dir < 0 ? range.from() : range.to() }
  7692. var headPos = cursorCoords(this$1, range.head, "div");
  7693. if (range.goalColumn != null) { headPos.left = range.goalColumn; }
  7694. goals.push(headPos.left);
  7695. var pos = findPosV(this$1, headPos, dir, unit);
  7696. if (unit == "page" && range == doc.sel.primary())
  7697. { addToScrollTop(this$1, charCoords(this$1, pos, "div").top - headPos.top); }
  7698. return pos
  7699. }, sel_move);
  7700. if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++)
  7701. { doc.sel.ranges[i].goalColumn = goals[i]; } }
  7702. }),
  7703. // Find the word at the given position (as returned by coordsChar).
  7704. findWordAt: function(pos) {
  7705. var doc = this.doc, line = getLine(doc, pos.line).text;
  7706. var start = pos.ch, end = pos.ch;
  7707. if (line) {
  7708. var helper = this.getHelper(pos, "wordChars");
  7709. if ((pos.sticky == "before" || end == line.length) && start) { --start; } else { ++end; }
  7710. var startChar = line.charAt(start);
  7711. var check = isWordChar(startChar, helper)
  7712. ? function (ch) { return isWordChar(ch, helper); }
  7713. : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); }
  7714. : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); };
  7715. while (start > 0 && check(line.charAt(start - 1))) { --start; }
  7716. while (end < line.length && check(line.charAt(end))) { ++end; }
  7717. }
  7718. return new Range(Pos(pos.line, start), Pos(pos.line, end))
  7719. },
  7720. toggleOverwrite: function(value) {
  7721. if (value != null && value == this.state.overwrite) { return }
  7722. if (this.state.overwrite = !this.state.overwrite)
  7723. { addClass(this.display.cursorDiv, "CodeMirror-overwrite"); }
  7724. else
  7725. { rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); }
  7726. signal(this, "overwriteToggle", this, this.state.overwrite);
  7727. },
  7728. hasFocus: function() { return this.display.input.getField() == activeElt() },
  7729. isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) },
  7730. scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y); }),
  7731. getScrollInfo: function() {
  7732. var scroller = this.display.scroller;
  7733. return {left: scroller.scrollLeft, top: scroller.scrollTop,
  7734. height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,
  7735. width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,
  7736. clientHeight: displayHeight(this), clientWidth: displayWidth(this)}
  7737. },
  7738. scrollIntoView: methodOp(function(range, margin) {
  7739. if (range == null) {
  7740. range = {from: this.doc.sel.primary().head, to: null};
  7741. if (margin == null) { margin = this.options.cursorScrollMargin; }
  7742. } else if (typeof range == "number") {
  7743. range = {from: Pos(range, 0), to: null};
  7744. } else if (range.from == null) {
  7745. range = {from: range, to: null};
  7746. }
  7747. if (!range.to) { range.to = range.from; }
  7748. range.margin = margin || 0;
  7749. if (range.from.line != null) {
  7750. scrollToRange(this, range);
  7751. } else {
  7752. scrollToCoordsRange(this, range.from, range.to, range.margin);
  7753. }
  7754. }),
  7755. setSize: methodOp(function(width, height) {
  7756. var this$1 = this;
  7757. var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; };
  7758. if (width != null) { this.display.wrapper.style.width = interpret(width); }
  7759. if (height != null) { this.display.wrapper.style.height = interpret(height); }
  7760. if (this.options.lineWrapping) { clearLineMeasurementCache(this); }
  7761. var lineNo = this.display.viewFrom;
  7762. this.doc.iter(lineNo, this.display.viewTo, function (line) {
  7763. if (line.widgets) { for (var i = 0; i < line.widgets.length; i++)
  7764. { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo, "widget"); break } } }
  7765. ++lineNo;
  7766. });
  7767. this.curOp.forceUpdate = true;
  7768. signal(this, "refresh", this);
  7769. }),
  7770. operation: function(f){return runInOp(this, f)},
  7771. startOperation: function(){return startOperation(this)},
  7772. endOperation: function(){return endOperation(this)},
  7773. refresh: methodOp(function() {
  7774. var oldHeight = this.display.cachedTextHeight;
  7775. regChange(this);
  7776. this.curOp.forceUpdate = true;
  7777. clearCaches(this);
  7778. scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop);
  7779. updateGutterSpace(this.display);
  7780. if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5 || this.options.lineWrapping)
  7781. { estimateLineHeights(this); }
  7782. signal(this, "refresh", this);
  7783. }),
  7784. swapDoc: methodOp(function(doc) {
  7785. var old = this.doc;
  7786. old.cm = null;
  7787. // Cancel the current text selection if any (#5821)
  7788. if (this.state.selectingText) { this.state.selectingText(); }
  7789. attachDoc(this, doc);
  7790. clearCaches(this);
  7791. this.display.input.reset();
  7792. scrollToCoords(this, doc.scrollLeft, doc.scrollTop);
  7793. this.curOp.forceScroll = true;
  7794. signalLater(this, "swapDoc", this, old);
  7795. return old
  7796. }),
  7797. phrase: function(phraseText) {
  7798. var phrases = this.options.phrases;
  7799. return phrases && Object.prototype.hasOwnProperty.call(phrases, phraseText) ? phrases[phraseText] : phraseText
  7800. },
  7801. getInputField: function(){return this.display.input.getField()},
  7802. getWrapperElement: function(){return this.display.wrapper},
  7803. getScrollerElement: function(){return this.display.scroller},
  7804. getGutterElement: function(){return this.display.gutters}
  7805. };
  7806. eventMixin(CodeMirror);
  7807. CodeMirror.registerHelper = function(type, name, value) {
  7808. if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []}; }
  7809. helpers[type][name] = value;
  7810. };
  7811. CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
  7812. CodeMirror.registerHelper(type, name, value);
  7813. helpers[type]._global.push({pred: predicate, val: value});
  7814. };
  7815. }
  7816. // Used for horizontal relative motion. Dir is -1 or 1 (left or
  7817. // right), unit can be "char", "column" (like char, but doesn't
  7818. // cross line boundaries), "word" (across next word), or "group" (to
  7819. // the start of next group of word or non-word-non-whitespace
  7820. // chars). The visually param controls whether, in right-to-left
  7821. // text, direction 1 means to move towards the next index in the
  7822. // string, or towards the character to the right of the current
  7823. // position. The resulting position will have a hitSide=true
  7824. // property if it reached the end of the document.
  7825. function findPosH(doc, pos, dir, unit, visually) {
  7826. var oldPos = pos;
  7827. var origDir = dir;
  7828. var lineObj = getLine(doc, pos.line);
  7829. var lineDir = visually && doc.direction == "rtl" ? -dir : dir;
  7830. function findNextLine() {
  7831. var l = pos.line + lineDir;
  7832. if (l < doc.first || l >= doc.first + doc.size) { return false }
  7833. pos = new Pos(l, pos.ch, pos.sticky);
  7834. return lineObj = getLine(doc, l)
  7835. }
  7836. function moveOnce(boundToLine) {
  7837. var next;
  7838. if (visually) {
  7839. next = moveVisually(doc.cm, lineObj, pos, dir);
  7840. } else {
  7841. next = moveLogically(lineObj, pos, dir);
  7842. }
  7843. if (next == null) {
  7844. if (!boundToLine && findNextLine())
  7845. { pos = endOfLine(visually, doc.cm, lineObj, pos.line, lineDir); }
  7846. else
  7847. { return false }
  7848. } else {
  7849. pos = next;
  7850. }
  7851. return true
  7852. }
  7853. if (unit == "char") {
  7854. moveOnce();
  7855. } else if (unit == "column") {
  7856. moveOnce(true);
  7857. } else if (unit == "word" || unit == "group") {
  7858. var sawType = null, group = unit == "group";
  7859. var helper = doc.cm && doc.cm.getHelper(pos, "wordChars");
  7860. for (var first = true;; first = false) {
  7861. if (dir < 0 && !moveOnce(!first)) { break }
  7862. var cur = lineObj.text.charAt(pos.ch) || "\n";
  7863. var type = isWordChar(cur, helper) ? "w"
  7864. : group && cur == "\n" ? "n"
  7865. : !group || /\s/.test(cur) ? null
  7866. : "p";
  7867. if (group && !first && !type) { type = "s"; }
  7868. if (sawType && sawType != type) {
  7869. if (dir < 0) {dir = 1; moveOnce(); pos.sticky = "after";}
  7870. break
  7871. }
  7872. if (type) { sawType = type; }
  7873. if (dir > 0 && !moveOnce(!first)) { break }
  7874. }
  7875. }
  7876. var result = skipAtomic(doc, pos, oldPos, origDir, true);
  7877. if (equalCursorPos(oldPos, result)) { result.hitSide = true; }
  7878. return result
  7879. }
  7880. // For relative vertical movement. Dir may be -1 or 1. Unit can be
  7881. // "page" or "line". The resulting position will have a hitSide=true
  7882. // property if it reached the end of the document.
  7883. function findPosV(cm, pos, dir, unit) {
  7884. var doc = cm.doc, x = pos.left, y;
  7885. if (unit == "page") {
  7886. var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
  7887. var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3);
  7888. y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount;
  7889. } else if (unit == "line") {
  7890. y = dir > 0 ? pos.bottom + 3 : pos.top - 3;
  7891. }
  7892. var target;
  7893. for (;;) {
  7894. target = coordsChar(cm, x, y);
  7895. if (!target.outside) { break }
  7896. if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break }
  7897. y += dir * 5;
  7898. }
  7899. return target
  7900. }
  7901. // CONTENTEDITABLE INPUT STYLE
  7902. var ContentEditableInput = function(cm) {
  7903. this.cm = cm;
  7904. this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null;
  7905. this.polling = new Delayed();
  7906. this.composing = null;
  7907. this.gracePeriod = false;
  7908. this.readDOMTimeout = null;
  7909. };
  7910. ContentEditableInput.prototype.init = function (display) {
  7911. var this$1 = this;
  7912. var input = this, cm = input.cm;
  7913. var div = input.div = display.lineDiv;
  7914. disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize);
  7915. function belongsToInput(e) {
  7916. for (var t = e.target; t; t = t.parentNode) {
  7917. if (t == div) { return true }
  7918. if (/\bCodeMirror-(?:line)?widget\b/.test(t.className)) { break }
  7919. }
  7920. return false
  7921. }
  7922. on(div, "paste", function (e) {
  7923. if (!belongsToInput(e) || signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }
  7924. // IE doesn't fire input events, so we schedule a read for the pasted content in this way
  7925. if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1.updateFromDOM(); }), 20); }
  7926. });
  7927. on(div, "compositionstart", function (e) {
  7928. this$1.composing = {data: e.data, done: false};
  7929. });
  7930. on(div, "compositionupdate", function (e) {
  7931. if (!this$1.composing) { this$1.composing = {data: e.data, done: false}; }
  7932. });
  7933. on(div, "compositionend", function (e) {
  7934. if (this$1.composing) {
  7935. if (e.data != this$1.composing.data) { this$1.readFromDOMSoon(); }
  7936. this$1.composing.done = true;
  7937. }
  7938. });
  7939. on(div, "touchstart", function () { return input.forceCompositionEnd(); });
  7940. on(div, "input", function () {
  7941. if (!this$1.composing) { this$1.readFromDOMSoon(); }
  7942. });
  7943. function onCopyCut(e) {
  7944. if (!belongsToInput(e) || signalDOMEvent(cm, e)) { return }
  7945. if (cm.somethingSelected()) {
  7946. setLastCopied({lineWise: false, text: cm.getSelections()});
  7947. if (e.type == "cut") { cm.replaceSelection("", null, "cut"); }
  7948. } else if (!cm.options.lineWiseCopyCut) {
  7949. return
  7950. } else {
  7951. var ranges = copyableRanges(cm);
  7952. setLastCopied({lineWise: true, text: ranges.text});
  7953. if (e.type == "cut") {
  7954. cm.operation(function () {
  7955. cm.setSelections(ranges.ranges, 0, sel_dontScroll);
  7956. cm.replaceSelection("", null, "cut");
  7957. });
  7958. }
  7959. }
  7960. if (e.clipboardData) {
  7961. e.clipboardData.clearData();
  7962. var content = lastCopied.text.join("\n");
  7963. // iOS exposes the clipboard API, but seems to discard content inserted into it
  7964. e.clipboardData.setData("Text", content);
  7965. if (e.clipboardData.getData("Text") == content) {
  7966. e.preventDefault();
  7967. return
  7968. }
  7969. }
  7970. // Old-fashioned briefly-focus-a-textarea hack
  7971. var kludge = hiddenTextarea(), te = kludge.firstChild;
  7972. cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
  7973. te.value = lastCopied.text.join("\n");
  7974. var hadFocus = document.activeElement;
  7975. selectInput(te);
  7976. setTimeout(function () {
  7977. cm.display.lineSpace.removeChild(kludge);
  7978. hadFocus.focus();
  7979. if (hadFocus == div) { input.showPrimarySelection(); }
  7980. }, 50);
  7981. }
  7982. on(div, "copy", onCopyCut);
  7983. on(div, "cut", onCopyCut);
  7984. };
  7985. ContentEditableInput.prototype.screenReaderLabelChanged = function (label) {
  7986. // Label for screenreaders, accessibility
  7987. if(label) {
  7988. this.div.setAttribute('aria-label', label);
  7989. } else {
  7990. this.div.removeAttribute('aria-label');
  7991. }
  7992. };
  7993. ContentEditableInput.prototype.prepareSelection = function () {
  7994. var result = prepareSelection(this.cm, false);
  7995. result.focus = document.activeElement == this.div;
  7996. return result
  7997. };
  7998. ContentEditableInput.prototype.showSelection = function (info, takeFocus) {
  7999. if (!info || !this.cm.display.view.length) { return }
  8000. if (info.focus || takeFocus) { this.showPrimarySelection(); }
  8001. this.showMultipleSelections(info);
  8002. };
  8003. ContentEditableInput.prototype.getSelection = function () {
  8004. return this.cm.display.wrapper.ownerDocument.getSelection()
  8005. };
  8006. ContentEditableInput.prototype.showPrimarySelection = function () {
  8007. var sel = this.getSelection(), cm = this.cm, prim = cm.doc.sel.primary();
  8008. var from = prim.from(), to = prim.to();
  8009. if (cm.display.viewTo == cm.display.viewFrom || from.line >= cm.display.viewTo || to.line < cm.display.viewFrom) {
  8010. sel.removeAllRanges();
  8011. return
  8012. }
  8013. var curAnchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
  8014. var curFocus = domToPos(cm, sel.focusNode, sel.focusOffset);
  8015. if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&
  8016. cmp(minPos(curAnchor, curFocus), from) == 0 &&
  8017. cmp(maxPos(curAnchor, curFocus), to) == 0)
  8018. { return }
  8019. var view = cm.display.view;
  8020. var start = (from.line >= cm.display.viewFrom && posToDOM(cm, from)) ||
  8021. {node: view[0].measure.map[2], offset: 0};
  8022. var end = to.line < cm.display.viewTo && posToDOM(cm, to);
  8023. if (!end) {
  8024. var measure = view[view.length - 1].measure;
  8025. var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;
  8026. end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]};
  8027. }
  8028. if (!start || !end) {
  8029. sel.removeAllRanges();
  8030. return
  8031. }
  8032. var old = sel.rangeCount && sel.getRangeAt(0), rng;
  8033. try { rng = range(start.node, start.offset, end.offset, end.node); }
  8034. catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
  8035. if (rng) {
  8036. if (!gecko && cm.state.focused) {
  8037. sel.collapse(start.node, start.offset);
  8038. if (!rng.collapsed) {
  8039. sel.removeAllRanges();
  8040. sel.addRange(rng);
  8041. }
  8042. } else {
  8043. sel.removeAllRanges();
  8044. sel.addRange(rng);
  8045. }
  8046. if (old && sel.anchorNode == null) { sel.addRange(old); }
  8047. else if (gecko) { this.startGracePeriod(); }
  8048. }
  8049. this.rememberSelection();
  8050. };
  8051. ContentEditableInput.prototype.startGracePeriod = function () {
  8052. var this$1 = this;
  8053. clearTimeout(this.gracePeriod);
  8054. this.gracePeriod = setTimeout(function () {
  8055. this$1.gracePeriod = false;
  8056. if (this$1.selectionChanged())
  8057. { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }); }
  8058. }, 20);
  8059. };
  8060. ContentEditableInput.prototype.showMultipleSelections = function (info) {
  8061. removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors);
  8062. removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection);
  8063. };
  8064. ContentEditableInput.prototype.rememberSelection = function () {
  8065. var sel = this.getSelection();
  8066. this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset;
  8067. this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset;
  8068. };
  8069. ContentEditableInput.prototype.selectionInEditor = function () {
  8070. var sel = this.getSelection();
  8071. if (!sel.rangeCount) { return false }
  8072. var node = sel.getRangeAt(0).commonAncestorContainer;
  8073. return contains(this.div, node)
  8074. };
  8075. ContentEditableInput.prototype.focus = function () {
  8076. if (this.cm.options.readOnly != "nocursor") {
  8077. if (!this.selectionInEditor() || document.activeElement != this.div)
  8078. { this.showSelection(this.prepareSelection(), true); }
  8079. this.div.focus();
  8080. }
  8081. };
  8082. ContentEditableInput.prototype.blur = function () { this.div.blur(); };
  8083. ContentEditableInput.prototype.getField = function () { return this.div };
  8084. ContentEditableInput.prototype.supportsTouch = function () { return true };
  8085. ContentEditableInput.prototype.receivedFocus = function () {
  8086. var input = this;
  8087. if (this.selectionInEditor())
  8088. { this.pollSelection(); }
  8089. else
  8090. { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); }
  8091. function poll() {
  8092. if (input.cm.state.focused) {
  8093. input.pollSelection();
  8094. input.polling.set(input.cm.options.pollInterval, poll);
  8095. }
  8096. }
  8097. this.polling.set(this.cm.options.pollInterval, poll);
  8098. };
  8099. ContentEditableInput.prototype.selectionChanged = function () {
  8100. var sel = this.getSelection();
  8101. return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
  8102. sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset
  8103. };
  8104. ContentEditableInput.prototype.pollSelection = function () {
  8105. if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { return }
  8106. var sel = this.getSelection(), cm = this.cm;
  8107. // On Android Chrome (version 56, at least), backspacing into an
  8108. // uneditable block element will put the cursor in that element,
  8109. // and then, because it's not editable, hide the virtual keyboard.
  8110. // Because Android doesn't allow us to actually detect backspace
  8111. // presses in a sane way, this code checks for when that happens
  8112. // and simulates a backspace press in this case.
  8113. if (android && chrome && this.cm.display.gutterSpecs.length && isInGutter(sel.anchorNode)) {
  8114. this.cm.triggerOnKeyDown({type: "keydown", keyCode: 8, preventDefault: Math.abs});
  8115. this.blur();
  8116. this.focus();
  8117. return
  8118. }
  8119. if (this.composing) { return }
  8120. this.rememberSelection();
  8121. var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset);
  8122. var head = domToPos(cm, sel.focusNode, sel.focusOffset);
  8123. if (anchor && head) { runInOp(cm, function () {
  8124. setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll);
  8125. if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true; }
  8126. }); }
  8127. };
  8128. ContentEditableInput.prototype.pollContent = function () {
  8129. if (this.readDOMTimeout != null) {
  8130. clearTimeout(this.readDOMTimeout);
  8131. this.readDOMTimeout = null;
  8132. }
  8133. var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary();
  8134. var from = sel.from(), to = sel.to();
  8135. if (from.ch == 0 && from.line > cm.firstLine())
  8136. { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length); }
  8137. if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine())
  8138. { to = Pos(to.line + 1, 0); }
  8139. if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false }
  8140. var fromIndex, fromLine, fromNode;
  8141. if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {
  8142. fromLine = lineNo(display.view[0].line);
  8143. fromNode = display.view[0].node;
  8144. } else {
  8145. fromLine = lineNo(display.view[fromIndex].line);
  8146. fromNode = display.view[fromIndex - 1].node.nextSibling;
  8147. }
  8148. var toIndex = findViewIndex(cm, to.line);
  8149. var toLine, toNode;
  8150. if (toIndex == display.view.length - 1) {
  8151. toLine = display.viewTo - 1;
  8152. toNode = display.lineDiv.lastChild;
  8153. } else {
  8154. toLine = lineNo(display.view[toIndex + 1].line) - 1;
  8155. toNode = display.view[toIndex + 1].node.previousSibling;
  8156. }
  8157. if (!fromNode) { return false }
  8158. var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine));
  8159. var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length));
  8160. while (newText.length > 1 && oldText.length > 1) {
  8161. if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; }
  8162. else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; }
  8163. else { break }
  8164. }
  8165. var cutFront = 0, cutEnd = 0;
  8166. var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length);
  8167. while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))
  8168. { ++cutFront; }
  8169. var newBot = lst(newText), oldBot = lst(oldText);
  8170. var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),
  8171. oldBot.length - (oldText.length == 1 ? cutFront : 0));
  8172. while (cutEnd < maxCutEnd &&
  8173. newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))
  8174. { ++cutEnd; }
  8175. // Try to move start of change to start of selection if ambiguous
  8176. if (newText.length == 1 && oldText.length == 1 && fromLine == from.line) {
  8177. while (cutFront && cutFront > from.ch &&
  8178. newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) {
  8179. cutFront--;
  8180. cutEnd++;
  8181. }
  8182. }
  8183. newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, "");
  8184. newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, "");
  8185. var chFrom = Pos(fromLine, cutFront);
  8186. var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0);
  8187. if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {
  8188. replaceRange(cm.doc, newText, chFrom, chTo, "+input");
  8189. return true
  8190. }
  8191. };
  8192. ContentEditableInput.prototype.ensurePolled = function () {
  8193. this.forceCompositionEnd();
  8194. };
  8195. ContentEditableInput.prototype.reset = function () {
  8196. this.forceCompositionEnd();
  8197. };
  8198. ContentEditableInput.prototype.forceCompositionEnd = function () {
  8199. if (!this.composing) { return }
  8200. clearTimeout(this.readDOMTimeout);
  8201. this.composing = null;
  8202. this.updateFromDOM();
  8203. this.div.blur();
  8204. this.div.focus();
  8205. };
  8206. ContentEditableInput.prototype.readFromDOMSoon = function () {
  8207. var this$1 = this;
  8208. if (this.readDOMTimeout != null) { return }
  8209. this.readDOMTimeout = setTimeout(function () {
  8210. this$1.readDOMTimeout = null;
  8211. if (this$1.composing) {
  8212. if (this$1.composing.done) { this$1.composing = null; }
  8213. else { return }
  8214. }
  8215. this$1.updateFromDOM();
  8216. }, 80);
  8217. };
  8218. ContentEditableInput.prototype.updateFromDOM = function () {
  8219. var this$1 = this;
  8220. if (this.cm.isReadOnly() || !this.pollContent())
  8221. { runInOp(this.cm, function () { return regChange(this$1.cm); }); }
  8222. };
  8223. ContentEditableInput.prototype.setUneditable = function (node) {
  8224. node.contentEditable = "false";
  8225. };
  8226. ContentEditableInput.prototype.onKeyPress = function (e) {
  8227. if (e.charCode == 0 || this.composing) { return }
  8228. e.preventDefault();
  8229. if (!this.cm.isReadOnly())
  8230. { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); }
  8231. };
  8232. ContentEditableInput.prototype.readOnlyChanged = function (val) {
  8233. this.div.contentEditable = String(val != "nocursor");
  8234. };
  8235. ContentEditableInput.prototype.onContextMenu = function () {};
  8236. ContentEditableInput.prototype.resetPosition = function () {};
  8237. ContentEditableInput.prototype.needsContentAttribute = true;
  8238. function posToDOM(cm, pos) {
  8239. var view = findViewForLine(cm, pos.line);
  8240. if (!view || view.hidden) { return null }
  8241. var line = getLine(cm.doc, pos.line);
  8242. var info = mapFromLineView(view, line, pos.line);
  8243. var order = getOrder(line, cm.doc.direction), side = "left";
  8244. if (order) {
  8245. var partPos = getBidiPartAt(order, pos.ch);
  8246. side = partPos % 2 ? "right" : "left";
  8247. }
  8248. var result = nodeAndOffsetInLineMap(info.map, pos.ch, side);
  8249. result.offset = result.collapse == "right" ? result.end : result.start;
  8250. return result
  8251. }
  8252. function isInGutter(node) {
  8253. for (var scan = node; scan; scan = scan.parentNode)
  8254. { if (/CodeMirror-gutter-wrapper/.test(scan.className)) { return true } }
  8255. return false
  8256. }
  8257. function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos }
  8258. function domTextBetween(cm, from, to, fromLine, toLine) {
  8259. var text = "", closing = false, lineSep = cm.doc.lineSeparator(), extraLinebreak = false;
  8260. function recognizeMarker(id) { return function (marker) { return marker.id == id; } }
  8261. function close() {
  8262. if (closing) {
  8263. text += lineSep;
  8264. if (extraLinebreak) { text += lineSep; }
  8265. closing = extraLinebreak = false;
  8266. }
  8267. }
  8268. function addText(str) {
  8269. if (str) {
  8270. close();
  8271. text += str;
  8272. }
  8273. }
  8274. function walk(node) {
  8275. if (node.nodeType == 1) {
  8276. var cmText = node.getAttribute("cm-text");
  8277. if (cmText) {
  8278. addText(cmText);
  8279. return
  8280. }
  8281. var markerID = node.getAttribute("cm-marker"), range;
  8282. if (markerID) {
  8283. var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));
  8284. if (found.length && (range = found[0].find(0)))
  8285. { addText(getBetween(cm.doc, range.from, range.to).join(lineSep)); }
  8286. return
  8287. }
  8288. if (node.getAttribute("contenteditable") == "false") { return }
  8289. var isBlock = /^(pre|div|p|li|table|br)$/i.test(node.nodeName);
  8290. if (!/^br$/i.test(node.nodeName) && node.textContent.length == 0) { return }
  8291. if (isBlock) { close(); }
  8292. for (var i = 0; i < node.childNodes.length; i++)
  8293. { walk(node.childNodes[i]); }
  8294. if (/^(pre|p)$/i.test(node.nodeName)) { extraLinebreak = true; }
  8295. if (isBlock) { closing = true; }
  8296. } else if (node.nodeType == 3) {
  8297. addText(node.nodeValue.replace(/\u200b/g, "").replace(/\u00a0/g, " "));
  8298. }
  8299. }
  8300. for (;;) {
  8301. walk(from);
  8302. if (from == to) { break }
  8303. from = from.nextSibling;
  8304. extraLinebreak = false;
  8305. }
  8306. return text
  8307. }
  8308. function domToPos(cm, node, offset) {
  8309. var lineNode;
  8310. if (node == cm.display.lineDiv) {
  8311. lineNode = cm.display.lineDiv.childNodes[offset];
  8312. if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) }
  8313. node = null; offset = 0;
  8314. } else {
  8315. for (lineNode = node;; lineNode = lineNode.parentNode) {
  8316. if (!lineNode || lineNode == cm.display.lineDiv) { return null }
  8317. if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break }
  8318. }
  8319. }
  8320. for (var i = 0; i < cm.display.view.length; i++) {
  8321. var lineView = cm.display.view[i];
  8322. if (lineView.node == lineNode)
  8323. { return locateNodeInLineView(lineView, node, offset) }
  8324. }
  8325. }
  8326. function locateNodeInLineView(lineView, node, offset) {
  8327. var wrapper = lineView.text.firstChild, bad = false;
  8328. if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) }
  8329. if (node == wrapper) {
  8330. bad = true;
  8331. node = wrapper.childNodes[offset];
  8332. offset = 0;
  8333. if (!node) {
  8334. var line = lineView.rest ? lst(lineView.rest) : lineView.line;
  8335. return badPos(Pos(lineNo(line), line.text.length), bad)
  8336. }
  8337. }
  8338. var textNode = node.nodeType == 3 ? node : null, topNode = node;
  8339. if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
  8340. textNode = node.firstChild;
  8341. if (offset) { offset = textNode.nodeValue.length; }
  8342. }
  8343. while (topNode.parentNode != wrapper) { topNode = topNode.parentNode; }
  8344. var measure = lineView.measure, maps = measure.maps;
  8345. function find(textNode, topNode, offset) {
  8346. for (var i = -1; i < (maps ? maps.length : 0); i++) {
  8347. var map = i < 0 ? measure.map : maps[i];
  8348. for (var j = 0; j < map.length; j += 3) {
  8349. var curNode = map[j + 2];
  8350. if (curNode == textNode || curNode == topNode) {
  8351. var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]);
  8352. var ch = map[j] + offset;
  8353. if (offset < 0 || curNode != textNode) { ch = map[j + (offset ? 1 : 0)]; }
  8354. return Pos(line, ch)
  8355. }
  8356. }
  8357. }
  8358. }
  8359. var found = find(textNode, topNode, offset);
  8360. if (found) { return badPos(found, bad) }
  8361. // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems
  8362. for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {
  8363. found = find(after, after.firstChild, 0);
  8364. if (found)
  8365. { return badPos(Pos(found.line, found.ch - dist), bad) }
  8366. else
  8367. { dist += after.textContent.length; }
  8368. }
  8369. for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) {
  8370. found = find(before, before.firstChild, -1);
  8371. if (found)
  8372. { return badPos(Pos(found.line, found.ch + dist$1), bad) }
  8373. else
  8374. { dist$1 += before.textContent.length; }
  8375. }
  8376. }
  8377. // TEXTAREA INPUT STYLE
  8378. var TextareaInput = function(cm) {
  8379. this.cm = cm;
  8380. // See input.poll and input.reset
  8381. this.prevInput = "";
  8382. // Flag that indicates whether we expect input to appear real soon
  8383. // now (after some event like 'keypress' or 'input') and are
  8384. // polling intensively.
  8385. this.pollingFast = false;
  8386. // Self-resetting timeout for the poller
  8387. this.polling = new Delayed();
  8388. // Used to work around IE issue with selection being forgotten when focus moves away from textarea
  8389. this.hasSelection = false;
  8390. this.composing = null;
  8391. };
  8392. TextareaInput.prototype.init = function (display) {
  8393. var this$1 = this;
  8394. var input = this, cm = this.cm;
  8395. this.createField(display);
  8396. var te = this.textarea;
  8397. display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild);
  8398. // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
  8399. if (ios) { te.style.width = "0px"; }
  8400. on(te, "input", function () {
  8401. if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null; }
  8402. input.poll();
  8403. });
  8404. on(te, "paste", function (e) {
  8405. if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }
  8406. cm.state.pasteIncoming = +new Date;
  8407. input.fastPoll();
  8408. });
  8409. function prepareCopyCut(e) {
  8410. if (signalDOMEvent(cm, e)) { return }
  8411. if (cm.somethingSelected()) {
  8412. setLastCopied({lineWise: false, text: cm.getSelections()});
  8413. } else if (!cm.options.lineWiseCopyCut) {
  8414. return
  8415. } else {
  8416. var ranges = copyableRanges(cm);
  8417. setLastCopied({lineWise: true, text: ranges.text});
  8418. if (e.type == "cut") {
  8419. cm.setSelections(ranges.ranges, null, sel_dontScroll);
  8420. } else {
  8421. input.prevInput = "";
  8422. te.value = ranges.text.join("\n");
  8423. selectInput(te);
  8424. }
  8425. }
  8426. if (e.type == "cut") { cm.state.cutIncoming = +new Date; }
  8427. }
  8428. on(te, "cut", prepareCopyCut);
  8429. on(te, "copy", prepareCopyCut);
  8430. on(display.scroller, "paste", function (e) {
  8431. if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return }
  8432. if (!te.dispatchEvent) {
  8433. cm.state.pasteIncoming = +new Date;
  8434. input.focus();
  8435. return
  8436. }
  8437. // Pass the `paste` event to the textarea so it's handled by its event listener.
  8438. var event = new Event("paste");
  8439. event.clipboardData = e.clipboardData;
  8440. te.dispatchEvent(event);
  8441. });
  8442. // Prevent normal selection in the editor (we handle our own)
  8443. on(display.lineSpace, "selectstart", function (e) {
  8444. if (!eventInWidget(display, e)) { e_preventDefault(e); }
  8445. });
  8446. on(te, "compositionstart", function () {
  8447. var start = cm.getCursor("from");
  8448. if (input.composing) { input.composing.range.clear(); }
  8449. input.composing = {
  8450. start: start,
  8451. range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
  8452. };
  8453. });
  8454. on(te, "compositionend", function () {
  8455. if (input.composing) {
  8456. input.poll();
  8457. input.composing.range.clear();
  8458. input.composing = null;
  8459. }
  8460. });
  8461. };
  8462. TextareaInput.prototype.createField = function (_display) {
  8463. // Wraps and hides input textarea
  8464. this.wrapper = hiddenTextarea();
  8465. // The semihidden textarea that is focused when the editor is
  8466. // focused, and receives input.
  8467. this.textarea = this.wrapper.firstChild;
  8468. };
  8469. TextareaInput.prototype.screenReaderLabelChanged = function (label) {
  8470. // Label for screenreaders, accessibility
  8471. if(label) {
  8472. this.textarea.setAttribute('aria-label', label);
  8473. } else {
  8474. this.textarea.removeAttribute('aria-label');
  8475. }
  8476. };
  8477. TextareaInput.prototype.prepareSelection = function () {
  8478. // Redraw the selection and/or cursor
  8479. var cm = this.cm, display = cm.display, doc = cm.doc;
  8480. var result = prepareSelection(cm);
  8481. // Move the hidden textarea near the cursor to prevent scrolling artifacts
  8482. if (cm.options.moveInputWithCursor) {
  8483. var headPos = cursorCoords(cm, doc.sel.primary().head, "div");
  8484. var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect();
  8485. result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
  8486. headPos.top + lineOff.top - wrapOff.top));
  8487. result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
  8488. headPos.left + lineOff.left - wrapOff.left));
  8489. }
  8490. return result
  8491. };
  8492. TextareaInput.prototype.showSelection = function (drawn) {
  8493. var cm = this.cm, display = cm.display;
  8494. removeChildrenAndAdd(display.cursorDiv, drawn.cursors);
  8495. removeChildrenAndAdd(display.selectionDiv, drawn.selection);
  8496. if (drawn.teTop != null) {
  8497. this.wrapper.style.top = drawn.teTop + "px";
  8498. this.wrapper.style.left = drawn.teLeft + "px";
  8499. }
  8500. };
  8501. // Reset the input to correspond to the selection (or to be empty,
  8502. // when not typing and nothing is selected)
  8503. TextareaInput.prototype.reset = function (typing) {
  8504. if (this.contextMenuPending || this.composing) { return }
  8505. var cm = this.cm;
  8506. if (cm.somethingSelected()) {
  8507. this.prevInput = "";
  8508. var content = cm.getSelection();
  8509. this.textarea.value = content;
  8510. if (cm.state.focused) { selectInput(this.textarea); }
  8511. if (ie && ie_version >= 9) { this.hasSelection = content; }
  8512. } else if (!typing) {
  8513. this.prevInput = this.textarea.value = "";
  8514. if (ie && ie_version >= 9) { this.hasSelection = null; }
  8515. }
  8516. };
  8517. TextareaInput.prototype.getField = function () { return this.textarea };
  8518. TextareaInput.prototype.supportsTouch = function () { return false };
  8519. TextareaInput.prototype.focus = function () {
  8520. if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) {
  8521. try { this.textarea.focus(); }
  8522. catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
  8523. }
  8524. };
  8525. TextareaInput.prototype.blur = function () { this.textarea.blur(); };
  8526. TextareaInput.prototype.resetPosition = function () {
  8527. this.wrapper.style.top = this.wrapper.style.left = 0;
  8528. };
  8529. TextareaInput.prototype.receivedFocus = function () { this.slowPoll(); };
  8530. // Poll for input changes, using the normal rate of polling. This
  8531. // runs as long as the editor is focused.
  8532. TextareaInput.prototype.slowPoll = function () {
  8533. var this$1 = this;
  8534. if (this.pollingFast) { return }
  8535. this.polling.set(this.cm.options.pollInterval, function () {
  8536. this$1.poll();
  8537. if (this$1.cm.state.focused) { this$1.slowPoll(); }
  8538. });
  8539. };
  8540. // When an event has just come in that is likely to add or change
  8541. // something in the input textarea, we poll faster, to ensure that
  8542. // the change appears on the screen quickly.
  8543. TextareaInput.prototype.fastPoll = function () {
  8544. var missed = false, input = this;
  8545. input.pollingFast = true;
  8546. function p() {
  8547. var changed = input.poll();
  8548. if (!changed && !missed) {missed = true; input.polling.set(60, p);}
  8549. else {input.pollingFast = false; input.slowPoll();}
  8550. }
  8551. input.polling.set(20, p);
  8552. };
  8553. // Read input from the textarea, and update the document to match.
  8554. // When something is selected, it is present in the textarea, and
  8555. // selected (unless it is huge, in which case a placeholder is
  8556. // used). When nothing is selected, the cursor sits after previously
  8557. // seen text (can be empty), which is stored in prevInput (we must
  8558. // not reset the textarea when typing, because that breaks IME).
  8559. TextareaInput.prototype.poll = function () {
  8560. var this$1 = this;
  8561. var cm = this.cm, input = this.textarea, prevInput = this.prevInput;
  8562. // Since this is called a *lot*, try to bail out as cheaply as
  8563. // possible when it is clear that nothing happened. hasSelection
  8564. // will be the case when there is a lot of text in the textarea,
  8565. // in which case reading its value would be expensive.
  8566. if (this.contextMenuPending || !cm.state.focused ||
  8567. (hasSelection(input) && !prevInput && !this.composing) ||
  8568. cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq)
  8569. { return false }
  8570. var text = input.value;
  8571. // If nothing changed, bail.
  8572. if (text == prevInput && !cm.somethingSelected()) { return false }
  8573. // Work around nonsensical selection resetting in IE9/10, and
  8574. // inexplicable appearance of private area unicode characters on
  8575. // some key combos in Mac (#2689).
  8576. if (ie && ie_version >= 9 && this.hasSelection === text ||
  8577. mac && /[\uf700-\uf7ff]/.test(text)) {
  8578. cm.display.input.reset();
  8579. return false
  8580. }
  8581. if (cm.doc.sel == cm.display.selForContextMenu) {
  8582. var first = text.charCodeAt(0);
  8583. if (first == 0x200b && !prevInput) { prevInput = "\u200b"; }
  8584. if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") }
  8585. }
  8586. // Find the part of the input that is actually new
  8587. var same = 0, l = Math.min(prevInput.length, text.length);
  8588. while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same; }
  8589. runInOp(cm, function () {
  8590. applyTextInput(cm, text.slice(same), prevInput.length - same,
  8591. null, this$1.composing ? "*compose" : null);
  8592. // Don't leave long text in the textarea, since it makes further polling slow
  8593. if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = ""; }
  8594. else { this$1.prevInput = text; }
  8595. if (this$1.composing) {
  8596. this$1.composing.range.clear();
  8597. this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"),
  8598. {className: "CodeMirror-composing"});
  8599. }
  8600. });
  8601. return true
  8602. };
  8603. TextareaInput.prototype.ensurePolled = function () {
  8604. if (this.pollingFast && this.poll()) { this.pollingFast = false; }
  8605. };
  8606. TextareaInput.prototype.onKeyPress = function () {
  8607. if (ie && ie_version >= 9) { this.hasSelection = null; }
  8608. this.fastPoll();
  8609. };
  8610. TextareaInput.prototype.onContextMenu = function (e) {
  8611. var input = this, cm = input.cm, display = cm.display, te = input.textarea;
  8612. if (input.contextMenuPending) { input.contextMenuPending(); }
  8613. var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop;
  8614. if (!pos || presto) { return } // Opera is difficult.
  8615. // Reset the current text selection only if the click is done outside of the selection
  8616. // and 'resetSelectionOnContextMenu' option is true.
  8617. var reset = cm.options.resetSelectionOnContextMenu;
  8618. if (reset && cm.doc.sel.contains(pos) == -1)
  8619. { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); }
  8620. var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText;
  8621. var wrapperBox = input.wrapper.offsetParent.getBoundingClientRect();
  8622. input.wrapper.style.cssText = "position: static";
  8623. te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
  8624. var oldScrollY;
  8625. if (webkit) { oldScrollY = window.scrollY; } // Work around Chrome issue (#2712)
  8626. display.input.focus();
  8627. if (webkit) { window.scrollTo(null, oldScrollY); }
  8628. display.input.reset();
  8629. // Adds "Select all" to context menu in FF
  8630. if (!cm.somethingSelected()) { te.value = input.prevInput = " "; }
  8631. input.contextMenuPending = rehide;
  8632. display.selForContextMenu = cm.doc.sel;
  8633. clearTimeout(display.detectingSelectAll);
  8634. // Select-all will be greyed out if there's nothing to select, so
  8635. // this adds a zero-width space so that we can later check whether
  8636. // it got selected.
  8637. function prepareSelectAllHack() {
  8638. if (te.selectionStart != null) {
  8639. var selected = cm.somethingSelected();
  8640. var extval = "\u200b" + (selected ? te.value : "");
  8641. te.value = "\u21da"; // Used to catch context-menu undo
  8642. te.value = extval;
  8643. input.prevInput = selected ? "" : "\u200b";
  8644. te.selectionStart = 1; te.selectionEnd = extval.length;
  8645. // Re-set this, in case some other handler touched the
  8646. // selection in the meantime.
  8647. display.selForContextMenu = cm.doc.sel;
  8648. }
  8649. }
  8650. function rehide() {
  8651. if (input.contextMenuPending != rehide) { return }
  8652. input.contextMenuPending = false;
  8653. input.wrapper.style.cssText = oldWrapperCSS;
  8654. te.style.cssText = oldCSS;
  8655. if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); }
  8656. // Try to detect the user choosing select-all
  8657. if (te.selectionStart != null) {
  8658. if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack(); }
  8659. var i = 0, poll = function () {
  8660. if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
  8661. te.selectionEnd > 0 && input.prevInput == "\u200b") {
  8662. operation(cm, selectAll)(cm);
  8663. } else if (i++ < 10) {
  8664. display.detectingSelectAll = setTimeout(poll, 500);
  8665. } else {
  8666. display.selForContextMenu = null;
  8667. display.input.reset();
  8668. }
  8669. };
  8670. display.detectingSelectAll = setTimeout(poll, 200);
  8671. }
  8672. }
  8673. if (ie && ie_version >= 9) { prepareSelectAllHack(); }
  8674. if (captureRightClick) {
  8675. e_stop(e);
  8676. var mouseup = function () {
  8677. off(window, "mouseup", mouseup);
  8678. setTimeout(rehide, 20);
  8679. };
  8680. on(window, "mouseup", mouseup);
  8681. } else {
  8682. setTimeout(rehide, 50);
  8683. }
  8684. };
  8685. TextareaInput.prototype.readOnlyChanged = function (val) {
  8686. if (!val) { this.reset(); }
  8687. this.textarea.disabled = val == "nocursor";
  8688. };
  8689. TextareaInput.prototype.setUneditable = function () {};
  8690. TextareaInput.prototype.needsContentAttribute = false;
  8691. function fromTextArea(textarea, options) {
  8692. options = options ? copyObj(options) : {};
  8693. options.value = textarea.value;
  8694. if (!options.tabindex && textarea.tabIndex)
  8695. { options.tabindex = textarea.tabIndex; }
  8696. if (!options.placeholder && textarea.placeholder)
  8697. { options.placeholder = textarea.placeholder; }
  8698. // Set autofocus to true if this textarea is focused, or if it has
  8699. // autofocus and no other element is focused.
  8700. if (options.autofocus == null) {
  8701. var hasFocus = activeElt();
  8702. options.autofocus = hasFocus == textarea ||
  8703. textarea.getAttribute("autofocus") != null && hasFocus == document.body;
  8704. }
  8705. function save() {textarea.value = cm.getValue();}
  8706. var realSubmit;
  8707. if (textarea.form) {
  8708. on(textarea.form, "submit", save);
  8709. // Deplorable hack to make the submit method do the right thing.
  8710. if (!options.leaveSubmitMethodAlone) {
  8711. var form = textarea.form;
  8712. realSubmit = form.submit;
  8713. try {
  8714. var wrappedSubmit = form.submit = function () {
  8715. save();
  8716. form.submit = realSubmit;
  8717. form.submit();
  8718. form.submit = wrappedSubmit;
  8719. };
  8720. } catch(e) {}
  8721. }
  8722. }
  8723. options.finishInit = function (cm) {
  8724. cm.save = save;
  8725. cm.getTextArea = function () { return textarea; };
  8726. cm.toTextArea = function () {
  8727. cm.toTextArea = isNaN; // Prevent this from being ran twice
  8728. save();
  8729. textarea.parentNode.removeChild(cm.getWrapperElement());
  8730. textarea.style.display = "";
  8731. if (textarea.form) {
  8732. off(textarea.form, "submit", save);
  8733. if (!options.leaveSubmitMethodAlone && typeof textarea.form.submit == "function")
  8734. { textarea.form.submit = realSubmit; }
  8735. }
  8736. };
  8737. };
  8738. textarea.style.display = "none";
  8739. var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); },
  8740. options);
  8741. return cm
  8742. }
  8743. function addLegacyProps(CodeMirror) {
  8744. CodeMirror.off = off;
  8745. CodeMirror.on = on;
  8746. CodeMirror.wheelEventPixels = wheelEventPixels;
  8747. CodeMirror.Doc = Doc;
  8748. CodeMirror.splitLines = splitLinesAuto;
  8749. CodeMirror.countColumn = countColumn;
  8750. CodeMirror.findColumn = findColumn;
  8751. CodeMirror.isWordChar = isWordCharBasic;
  8752. CodeMirror.Pass = Pass;
  8753. CodeMirror.signal = signal;
  8754. CodeMirror.Line = Line;
  8755. CodeMirror.changeEnd = changeEnd;
  8756. CodeMirror.scrollbarModel = scrollbarModel;
  8757. CodeMirror.Pos = Pos;
  8758. CodeMirror.cmpPos = cmp;
  8759. CodeMirror.modes = modes;
  8760. CodeMirror.mimeModes = mimeModes;
  8761. CodeMirror.resolveMode = resolveMode;
  8762. CodeMirror.getMode = getMode;
  8763. CodeMirror.modeExtensions = modeExtensions;
  8764. CodeMirror.extendMode = extendMode;
  8765. CodeMirror.copyState = copyState;
  8766. CodeMirror.startState = startState;
  8767. CodeMirror.innerMode = innerMode;
  8768. CodeMirror.commands = commands;
  8769. CodeMirror.keyMap = keyMap;
  8770. CodeMirror.keyName = keyName;
  8771. CodeMirror.isModifierKey = isModifierKey;
  8772. CodeMirror.lookupKey = lookupKey;
  8773. CodeMirror.normalizeKeyMap = normalizeKeyMap;
  8774. CodeMirror.StringStream = StringStream;
  8775. CodeMirror.SharedTextMarker = SharedTextMarker;
  8776. CodeMirror.TextMarker = TextMarker;
  8777. CodeMirror.LineWidget = LineWidget;
  8778. CodeMirror.e_preventDefault = e_preventDefault;
  8779. CodeMirror.e_stopPropagation = e_stopPropagation;
  8780. CodeMirror.e_stop = e_stop;
  8781. CodeMirror.addClass = addClass;
  8782. CodeMirror.contains = contains;
  8783. CodeMirror.rmClass = rmClass;
  8784. CodeMirror.keyNames = keyNames;
  8785. }
  8786. // EDITOR CONSTRUCTOR
  8787. defineOptions(CodeMirror);
  8788. addEditorMethods(CodeMirror);
  8789. // Set up methods on CodeMirror's prototype to redirect to the editor's document.
  8790. var dontDelegate = "iter insert remove copy getEditor constructor".split(" ");
  8791. for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
  8792. { CodeMirror.prototype[prop] = (function(method) {
  8793. return function() {return method.apply(this.doc, arguments)}
  8794. })(Doc.prototype[prop]); } }
  8795. eventMixin(Doc);
  8796. CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput};
  8797. // Extra arguments are stored as the mode's dependencies, which is
  8798. // used by (legacy) mechanisms like loadmode.js to automatically
  8799. // load a mode. (Preferred mechanism is the require/define calls.)
  8800. CodeMirror.defineMode = function(name/*, mode, …*/) {
  8801. if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name; }
  8802. defineMode.apply(this, arguments);
  8803. };
  8804. CodeMirror.defineMIME = defineMIME;
  8805. // Minimal default mode.
  8806. CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); });
  8807. CodeMirror.defineMIME("text/plain", "null");
  8808. // EXTENSIONS
  8809. CodeMirror.defineExtension = function (name, func) {
  8810. CodeMirror.prototype[name] = func;
  8811. };
  8812. CodeMirror.defineDocExtension = function (name, func) {
  8813. Doc.prototype[name] = func;
  8814. };
  8815. CodeMirror.fromTextArea = fromTextArea;
  8816. addLegacyProps(CodeMirror);
  8817. CodeMirror.version = "5.56.0";
  8818. return CodeMirror;
  8819. })));
  8820. /* ---- extension/simple.js ---- */
  8821. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  8822. // Distributed under an MIT license: https://codemirror.net/LICENSE
  8823. (function(mod) {
  8824. if (typeof exports == "object" && typeof module == "object") // CommonJS
  8825. mod(require("../../lib/codemirror"));
  8826. else if (typeof define == "function" && define.amd) // AMD
  8827. define(["../../lib/codemirror"], mod);
  8828. else // Plain browser env
  8829. mod(CodeMirror);
  8830. })(function(CodeMirror) {
  8831. "use strict";
  8832. CodeMirror.defineSimpleMode = function(name, states) {
  8833. CodeMirror.defineMode(name, function(config) {
  8834. return CodeMirror.simpleMode(config, states);
  8835. });
  8836. };
  8837. CodeMirror.simpleMode = function(config, states) {
  8838. ensureState(states, "start");
  8839. var states_ = {}, meta = states.meta || {}, hasIndentation = false;
  8840. for (var state in states) if (state != meta && states.hasOwnProperty(state)) {
  8841. var list = states_[state] = [], orig = states[state];
  8842. for (var i = 0; i < orig.length; i++) {
  8843. var data = orig[i];
  8844. list.push(new Rule(data, states));
  8845. if (data.indent || data.dedent) hasIndentation = true;
  8846. }
  8847. }
  8848. var mode = {
  8849. startState: function() {
  8850. return {state: "start", pending: null,
  8851. local: null, localState: null,
  8852. indent: hasIndentation ? [] : null};
  8853. },
  8854. copyState: function(state) {
  8855. var s = {state: state.state, pending: state.pending,
  8856. local: state.local, localState: null,
  8857. indent: state.indent && state.indent.slice(0)};
  8858. if (state.localState)
  8859. s.localState = CodeMirror.copyState(state.local.mode, state.localState);
  8860. if (state.stack)
  8861. s.stack = state.stack.slice(0);
  8862. for (var pers = state.persistentStates; pers; pers = pers.next)
  8863. s.persistentStates = {mode: pers.mode,
  8864. spec: pers.spec,
  8865. state: pers.state == state.localState ? s.localState : CodeMirror.copyState(pers.mode, pers.state),
  8866. next: s.persistentStates};
  8867. return s;
  8868. },
  8869. token: tokenFunction(states_, config),
  8870. innerMode: function(state) { return state.local && {mode: state.local.mode, state: state.localState}; },
  8871. indent: indentFunction(states_, meta)
  8872. };
  8873. if (meta) for (var prop in meta) if (meta.hasOwnProperty(prop))
  8874. mode[prop] = meta[prop];
  8875. return mode;
  8876. };
  8877. function ensureState(states, name) {
  8878. if (!states.hasOwnProperty(name))
  8879. throw new Error("Undefined state " + name + " in simple mode");
  8880. }
  8881. function toRegex(val, caret) {
  8882. if (!val) return /(?:)/;
  8883. var flags = "";
  8884. if (val instanceof RegExp) {
  8885. if (val.ignoreCase) flags = "i";
  8886. val = val.source;
  8887. } else {
  8888. val = String(val);
  8889. }
  8890. return new RegExp((caret === false ? "" : "^") + "(?:" + val + ")", flags);
  8891. }
  8892. function asToken(val) {
  8893. if (!val) return null;
  8894. if (val.apply) return val
  8895. if (typeof val == "string") return val.replace(/\./g, " ");
  8896. var result = [];
  8897. for (var i = 0; i < val.length; i++)
  8898. result.push(val[i] && val[i].replace(/\./g, " "));
  8899. return result;
  8900. }
  8901. function Rule(data, states) {
  8902. if (data.next || data.push) ensureState(states, data.next || data.push);
  8903. this.regex = toRegex(data.regex);
  8904. this.token = asToken(data.token);
  8905. this.data = data;
  8906. }
  8907. function tokenFunction(states, config) {
  8908. return function(stream, state) {
  8909. if (state.pending) {
  8910. var pend = state.pending.shift();
  8911. if (state.pending.length == 0) state.pending = null;
  8912. stream.pos += pend.text.length;
  8913. return pend.token;
  8914. }
  8915. if (state.local) {
  8916. if (state.local.end && stream.match(state.local.end)) {
  8917. var tok = state.local.endToken || null;
  8918. state.local = state.localState = null;
  8919. return tok;
  8920. } else {
  8921. var tok = state.local.mode.token(stream, state.localState), m;
  8922. if (state.local.endScan && (m = state.local.endScan.exec(stream.current())))
  8923. stream.pos = stream.start + m.index;
  8924. return tok;
  8925. }
  8926. }
  8927. var curState = states[state.state];
  8928. for (var i = 0; i < curState.length; i++) {
  8929. var rule = curState[i];
  8930. var matches = (!rule.data.sol || stream.sol()) && stream.match(rule.regex);
  8931. if (matches) {
  8932. if (rule.data.next) {
  8933. state.state = rule.data.next;
  8934. } else if (rule.data.push) {
  8935. (state.stack || (state.stack = [])).push(state.state);
  8936. state.state = rule.data.push;
  8937. } else if (rule.data.pop && state.stack && state.stack.length) {
  8938. state.state = state.stack.pop();
  8939. }
  8940. if (rule.data.mode)
  8941. enterLocalMode(config, state, rule.data.mode, rule.token);
  8942. if (rule.data.indent)
  8943. state.indent.push(stream.indentation() + config.indentUnit);
  8944. if (rule.data.dedent)
  8945. state.indent.pop();
  8946. var token = rule.token
  8947. if (token && token.apply) token = token(matches)
  8948. if (matches.length > 2 && rule.token && typeof rule.token != "string") {
  8949. state.pending = [];
  8950. for (var j = 2; j < matches.length; j++)
  8951. if (matches[j])
  8952. state.pending.push({text: matches[j], token: rule.token[j - 1]});
  8953. stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));
  8954. return token[0];
  8955. } else if (token && token.join) {
  8956. return token[0];
  8957. } else {
  8958. return token;
  8959. }
  8960. }
  8961. }
  8962. stream.next();
  8963. return null;
  8964. };
  8965. }
  8966. function cmp(a, b) {
  8967. if (a === b) return true;
  8968. if (!a || typeof a != "object" || !b || typeof b != "object") return false;
  8969. var props = 0;
  8970. for (var prop in a) if (a.hasOwnProperty(prop)) {
  8971. if (!b.hasOwnProperty(prop) || !cmp(a[prop], b[prop])) return false;
  8972. props++;
  8973. }
  8974. for (var prop in b) if (b.hasOwnProperty(prop)) props--;
  8975. return props == 0;
  8976. }
  8977. function enterLocalMode(config, state, spec, token) {
  8978. var pers;
  8979. if (spec.persistent) for (var p = state.persistentStates; p && !pers; p = p.next)
  8980. if (spec.spec ? cmp(spec.spec, p.spec) : spec.mode == p.mode) pers = p;
  8981. var mode = pers ? pers.mode : spec.mode || CodeMirror.getMode(config, spec.spec);
  8982. var lState = pers ? pers.state : CodeMirror.startState(mode);
  8983. if (spec.persistent && !pers)
  8984. state.persistentStates = {mode: mode, spec: spec.spec, state: lState, next: state.persistentStates};
  8985. state.localState = lState;
  8986. state.local = {mode: mode,
  8987. end: spec.end && toRegex(spec.end),
  8988. endScan: spec.end && spec.forceEnd !== false && toRegex(spec.end, false),
  8989. endToken: token && token.join ? token[token.length - 1] : token};
  8990. }
  8991. function indexOf(val, arr) {
  8992. for (var i = 0; i < arr.length; i++) if (arr[i] === val) return true;
  8993. }
  8994. function indentFunction(states, meta) {
  8995. return function(state, textAfter, line) {
  8996. if (state.local && state.local.mode.indent)
  8997. return state.local.mode.indent(state.localState, textAfter, line);
  8998. if (state.indent == null || state.local || meta.dontIndentStates && indexOf(state.state, meta.dontIndentStates) > -1)
  8999. return CodeMirror.Pass;
  9000. var pos = state.indent.length - 1, rules = states[state.state];
  9001. scan: for (;;) {
  9002. for (var i = 0; i < rules.length; i++) {
  9003. var rule = rules[i];
  9004. if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {
  9005. var m = rule.regex.exec(textAfter);
  9006. if (m && m[0]) {
  9007. pos--;
  9008. if (rule.next || rule.push) rules = states[rule.next || rule.push];
  9009. textAfter = textAfter.slice(m[0].length);
  9010. continue scan;
  9011. }
  9012. }
  9013. }
  9014. break;
  9015. }
  9016. return pos < 0 ? 0 : state.indent[pos];
  9017. };
  9018. }
  9019. });
  9020. /* ---- extension/sublime.js ---- */
  9021. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  9022. // Distributed under an MIT license: https://codemirror.net/LICENSE
  9023. // A rough approximation of Sublime Text's keybindings
  9024. // Depends on addon/search/searchcursor.js and optionally addon/dialog/dialogs.js
  9025. (function(mod) {
  9026. if (typeof exports == "object" && typeof module == "object") // CommonJS
  9027. mod(require("../lib/codemirror"), require("../addon/search/searchcursor"), require("../addon/edit/matchbrackets"));
  9028. else if (typeof define == "function" && define.amd) // AMD
  9029. define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/edit/matchbrackets"], mod);
  9030. else // Plain browser env
  9031. mod(CodeMirror);
  9032. })(function(CodeMirror) {
  9033. "use strict";
  9034. var cmds = CodeMirror.commands;
  9035. var Pos = CodeMirror.Pos;
  9036. // This is not exactly Sublime's algorithm. I couldn't make heads or tails of that.
  9037. function findPosSubword(doc, start, dir) {
  9038. if (dir < 0 && start.ch == 0) return doc.clipPos(Pos(start.line - 1));
  9039. var line = doc.getLine(start.line);
  9040. if (dir > 0 && start.ch >= line.length) return doc.clipPos(Pos(start.line + 1, 0));
  9041. var state = "start", type, startPos = start.ch;
  9042. for (var pos = startPos, e = dir < 0 ? 0 : line.length, i = 0; pos != e; pos += dir, i++) {
  9043. var next = line.charAt(dir < 0 ? pos - 1 : pos);
  9044. var cat = next != "_" && CodeMirror.isWordChar(next) ? "w" : "o";
  9045. if (cat == "w" && next.toUpperCase() == next) cat = "W";
  9046. if (state == "start") {
  9047. if (cat != "o") { state = "in"; type = cat; }
  9048. else startPos = pos + dir
  9049. } else if (state == "in") {
  9050. if (type != cat) {
  9051. if (type == "w" && cat == "W" && dir < 0) pos--;
  9052. if (type == "W" && cat == "w" && dir > 0) { // From uppercase to lowercase
  9053. if (pos == startPos + 1) { type = "w"; continue; }
  9054. else pos--;
  9055. }
  9056. break;
  9057. }
  9058. }
  9059. }
  9060. return Pos(start.line, pos);
  9061. }
  9062. function moveSubword(cm, dir) {
  9063. cm.extendSelectionsBy(function(range) {
  9064. if (cm.display.shift || cm.doc.extend || range.empty())
  9065. return findPosSubword(cm.doc, range.head, dir);
  9066. else
  9067. return dir < 0 ? range.from() : range.to();
  9068. });
  9069. }
  9070. cmds.goSubwordLeft = function(cm) { moveSubword(cm, -1); };
  9071. cmds.goSubwordRight = function(cm) { moveSubword(cm, 1); };
  9072. cmds.scrollLineUp = function(cm) {
  9073. var info = cm.getScrollInfo();
  9074. if (!cm.somethingSelected()) {
  9075. var visibleBottomLine = cm.lineAtHeight(info.top + info.clientHeight, "local");
  9076. if (cm.getCursor().line >= visibleBottomLine)
  9077. cm.execCommand("goLineUp");
  9078. }
  9079. cm.scrollTo(null, info.top - cm.defaultTextHeight());
  9080. };
  9081. cmds.scrollLineDown = function(cm) {
  9082. var info = cm.getScrollInfo();
  9083. if (!cm.somethingSelected()) {
  9084. var visibleTopLine = cm.lineAtHeight(info.top, "local")+1;
  9085. if (cm.getCursor().line <= visibleTopLine)
  9086. cm.execCommand("goLineDown");
  9087. }
  9088. cm.scrollTo(null, info.top + cm.defaultTextHeight());
  9089. };
  9090. cmds.splitSelectionByLine = function(cm) {
  9091. var ranges = cm.listSelections(), lineRanges = [];
  9092. for (var i = 0; i < ranges.length; i++) {
  9093. var from = ranges[i].from(), to = ranges[i].to();
  9094. for (var line = from.line; line <= to.line; ++line)
  9095. if (!(to.line > from.line && line == to.line && to.ch == 0))
  9096. lineRanges.push({anchor: line == from.line ? from : Pos(line, 0),
  9097. head: line == to.line ? to : Pos(line)});
  9098. }
  9099. cm.setSelections(lineRanges, 0);
  9100. };
  9101. cmds.singleSelectionTop = function(cm) {
  9102. var range = cm.listSelections()[0];
  9103. cm.setSelection(range.anchor, range.head, {scroll: false});
  9104. };
  9105. cmds.selectLine = function(cm) {
  9106. var ranges = cm.listSelections(), extended = [];
  9107. for (var i = 0; i < ranges.length; i++) {
  9108. var range = ranges[i];
  9109. extended.push({anchor: Pos(range.from().line, 0),
  9110. head: Pos(range.to().line + 1, 0)});
  9111. }
  9112. cm.setSelections(extended);
  9113. };
  9114. function insertLine(cm, above) {
  9115. if (cm.isReadOnly()) return CodeMirror.Pass
  9116. cm.operation(function() {
  9117. var len = cm.listSelections().length, newSelection = [], last = -1;
  9118. for (var i = 0; i < len; i++) {
  9119. var head = cm.listSelections()[i].head;
  9120. if (head.line <= last) continue;
  9121. var at = Pos(head.line + (above ? 0 : 1), 0);
  9122. cm.replaceRange("\n", at, null, "+insertLine");
  9123. cm.indentLine(at.line, null, true);
  9124. newSelection.push({head: at, anchor: at});
  9125. last = head.line + 1;
  9126. }
  9127. cm.setSelections(newSelection);
  9128. });
  9129. cm.execCommand("indentAuto");
  9130. }
  9131. cmds.insertLineAfter = function(cm) { return insertLine(cm, false); };
  9132. cmds.insertLineBefore = function(cm) { return insertLine(cm, true); };
  9133. function wordAt(cm, pos) {
  9134. var start = pos.ch, end = start, line = cm.getLine(pos.line);
  9135. while (start && CodeMirror.isWordChar(line.charAt(start - 1))) --start;
  9136. while (end < line.length && CodeMirror.isWordChar(line.charAt(end))) ++end;
  9137. return {from: Pos(pos.line, start), to: Pos(pos.line, end), word: line.slice(start, end)};
  9138. }
  9139. cmds.selectNextOccurrence = function(cm) {
  9140. var from = cm.getCursor("from"), to = cm.getCursor("to");
  9141. var fullWord = cm.state.sublimeFindFullWord == cm.doc.sel;
  9142. if (CodeMirror.cmpPos(from, to) == 0) {
  9143. var word = wordAt(cm, from);
  9144. if (!word.word) return;
  9145. cm.setSelection(word.from, word.to);
  9146. fullWord = true;
  9147. } else {
  9148. var text = cm.getRange(from, to);
  9149. var query = fullWord ? new RegExp("\\b" + text + "\\b") : text;
  9150. var cur = cm.getSearchCursor(query, to);
  9151. var found = cur.findNext();
  9152. if (!found) {
  9153. cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0));
  9154. found = cur.findNext();
  9155. }
  9156. if (!found || isSelectedRange(cm.listSelections(), cur.from(), cur.to())) return
  9157. cm.addSelection(cur.from(), cur.to());
  9158. }
  9159. if (fullWord)
  9160. cm.state.sublimeFindFullWord = cm.doc.sel;
  9161. };
  9162. cmds.skipAndSelectNextOccurrence = function(cm) {
  9163. var prevAnchor = cm.getCursor("anchor"), prevHead = cm.getCursor("head");
  9164. cmds.selectNextOccurrence(cm);
  9165. if (CodeMirror.cmpPos(prevAnchor, prevHead) != 0) {
  9166. cm.doc.setSelections(cm.doc.listSelections()
  9167. .filter(function (sel) {
  9168. return sel.anchor != prevAnchor || sel.head != prevHead;
  9169. }));
  9170. }
  9171. }
  9172. function addCursorToSelection(cm, dir) {
  9173. var ranges = cm.listSelections(), newRanges = [];
  9174. for (var i = 0; i < ranges.length; i++) {
  9175. var range = ranges[i];
  9176. var newAnchor = cm.findPosV(
  9177. range.anchor, dir, "line", range.anchor.goalColumn);
  9178. var newHead = cm.findPosV(
  9179. range.head, dir, "line", range.head.goalColumn);
  9180. newAnchor.goalColumn = range.anchor.goalColumn != null ?
  9181. range.anchor.goalColumn : cm.cursorCoords(range.anchor, "div").left;
  9182. newHead.goalColumn = range.head.goalColumn != null ?
  9183. range.head.goalColumn : cm.cursorCoords(range.head, "div").left;
  9184. var newRange = {anchor: newAnchor, head: newHead};
  9185. newRanges.push(range);
  9186. newRanges.push(newRange);
  9187. }
  9188. cm.setSelections(newRanges);
  9189. }
  9190. cmds.addCursorToPrevLine = function(cm) { addCursorToSelection(cm, -1); };
  9191. cmds.addCursorToNextLine = function(cm) { addCursorToSelection(cm, 1); };
  9192. function isSelectedRange(ranges, from, to) {
  9193. for (var i = 0; i < ranges.length; i++)
  9194. if (CodeMirror.cmpPos(ranges[i].from(), from) == 0 &&
  9195. CodeMirror.cmpPos(ranges[i].to(), to) == 0) return true
  9196. return false
  9197. }
  9198. var mirror = "(){}[]";
  9199. function selectBetweenBrackets(cm) {
  9200. var ranges = cm.listSelections(), newRanges = []
  9201. for (var i = 0; i < ranges.length; i++) {
  9202. var range = ranges[i], pos = range.head, opening = cm.scanForBracket(pos, -1);
  9203. if (!opening) return false;
  9204. for (;;) {
  9205. var closing = cm.scanForBracket(pos, 1);
  9206. if (!closing) return false;
  9207. if (closing.ch == mirror.charAt(mirror.indexOf(opening.ch) + 1)) {
  9208. var startPos = Pos(opening.pos.line, opening.pos.ch + 1);
  9209. if (CodeMirror.cmpPos(startPos, range.from()) == 0 &&
  9210. CodeMirror.cmpPos(closing.pos, range.to()) == 0) {
  9211. opening = cm.scanForBracket(opening.pos, -1);
  9212. if (!opening) return false;
  9213. } else {
  9214. newRanges.push({anchor: startPos, head: closing.pos});
  9215. break;
  9216. }
  9217. }
  9218. pos = Pos(closing.pos.line, closing.pos.ch + 1);
  9219. }
  9220. }
  9221. cm.setSelections(newRanges);
  9222. return true;
  9223. }
  9224. cmds.selectScope = function(cm) {
  9225. selectBetweenBrackets(cm) || cm.execCommand("selectAll");
  9226. };
  9227. cmds.selectBetweenBrackets = function(cm) {
  9228. if (!selectBetweenBrackets(cm)) return CodeMirror.Pass;
  9229. };
  9230. function puncType(type) {
  9231. return !type ? null : /\bpunctuation\b/.test(type) ? type : undefined
  9232. }
  9233. cmds.goToBracket = function(cm) {
  9234. cm.extendSelectionsBy(function(range) {
  9235. var next = cm.scanForBracket(range.head, 1, puncType(cm.getTokenTypeAt(range.head)));
  9236. if (next && CodeMirror.cmpPos(next.pos, range.head) != 0) return next.pos;
  9237. var prev = cm.scanForBracket(range.head, -1, puncType(cm.getTokenTypeAt(Pos(range.head.line, range.head.ch + 1))));
  9238. return prev && Pos(prev.pos.line, prev.pos.ch + 1) || range.head;
  9239. });
  9240. };
  9241. cmds.swapLineUp = function(cm) {
  9242. if (cm.isReadOnly()) return CodeMirror.Pass
  9243. var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1, newSels = [];
  9244. for (var i = 0; i < ranges.length; i++) {
  9245. var range = ranges[i], from = range.from().line - 1, to = range.to().line;
  9246. newSels.push({anchor: Pos(range.anchor.line - 1, range.anchor.ch),
  9247. head: Pos(range.head.line - 1, range.head.ch)});
  9248. if (range.to().ch == 0 && !range.empty()) --to;
  9249. if (from > at) linesToMove.push(from, to);
  9250. else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to;
  9251. at = to;
  9252. }
  9253. cm.operation(function() {
  9254. for (var i = 0; i < linesToMove.length; i += 2) {
  9255. var from = linesToMove[i], to = linesToMove[i + 1];
  9256. var line = cm.getLine(from);
  9257. cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine");
  9258. if (to > cm.lastLine())
  9259. cm.replaceRange("\n" + line, Pos(cm.lastLine()), null, "+swapLine");
  9260. else
  9261. cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine");
  9262. }
  9263. cm.setSelections(newSels);
  9264. cm.scrollIntoView();
  9265. });
  9266. };
  9267. cmds.swapLineDown = function(cm) {
  9268. if (cm.isReadOnly()) return CodeMirror.Pass
  9269. var ranges = cm.listSelections(), linesToMove = [], at = cm.lastLine() + 1;
  9270. for (var i = ranges.length - 1; i >= 0; i--) {
  9271. var range = ranges[i], from = range.to().line + 1, to = range.from().line;
  9272. if (range.to().ch == 0 && !range.empty()) from--;
  9273. if (from < at) linesToMove.push(from, to);
  9274. else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to;
  9275. at = to;
  9276. }
  9277. cm.operation(function() {
  9278. for (var i = linesToMove.length - 2; i >= 0; i -= 2) {
  9279. var from = linesToMove[i], to = linesToMove[i + 1];
  9280. var line = cm.getLine(from);
  9281. if (from == cm.lastLine())
  9282. cm.replaceRange("", Pos(from - 1), Pos(from), "+swapLine");
  9283. else
  9284. cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine");
  9285. cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine");
  9286. }
  9287. cm.scrollIntoView();
  9288. });
  9289. };
  9290. cmds.toggleCommentIndented = function(cm) {
  9291. cm.toggleComment({ indent: true });
  9292. }
  9293. cmds.joinLines = function(cm) {
  9294. var ranges = cm.listSelections(), joined = [];
  9295. for (var i = 0; i < ranges.length; i++) {
  9296. var range = ranges[i], from = range.from();
  9297. var start = from.line, end = range.to().line;
  9298. while (i < ranges.length - 1 && ranges[i + 1].from().line == end)
  9299. end = ranges[++i].to().line;
  9300. joined.push({start: start, end: end, anchor: !range.empty() && from});
  9301. }
  9302. cm.operation(function() {
  9303. var offset = 0, ranges = [];
  9304. for (var i = 0; i < joined.length; i++) {
  9305. var obj = joined[i];
  9306. var anchor = obj.anchor && Pos(obj.anchor.line - offset, obj.anchor.ch), head;
  9307. for (var line = obj.start; line <= obj.end; line++) {
  9308. var actual = line - offset;
  9309. if (line == obj.end) head = Pos(actual, cm.getLine(actual).length + 1);
  9310. if (actual < cm.lastLine()) {
  9311. cm.replaceRange(" ", Pos(actual), Pos(actual + 1, /^\s*/.exec(cm.getLine(actual + 1))[0].length));
  9312. ++offset;
  9313. }
  9314. }
  9315. ranges.push({anchor: anchor || head, head: head});
  9316. }
  9317. cm.setSelections(ranges, 0);
  9318. });
  9319. };
  9320. cmds.duplicateLine = function(cm) {
  9321. cm.operation(function() {
  9322. var rangeCount = cm.listSelections().length;
  9323. for (var i = 0; i < rangeCount; i++) {
  9324. var range = cm.listSelections()[i];
  9325. if (range.empty())
  9326. cm.replaceRange(cm.getLine(range.head.line) + "\n", Pos(range.head.line, 0));
  9327. else
  9328. cm.replaceRange(cm.getRange(range.from(), range.to()), range.from());
  9329. }
  9330. cm.scrollIntoView();
  9331. });
  9332. };
  9333. function sortLines(cm, caseSensitive) {
  9334. if (cm.isReadOnly()) return CodeMirror.Pass
  9335. var ranges = cm.listSelections(), toSort = [], selected;
  9336. for (var i = 0; i < ranges.length; i++) {
  9337. var range = ranges[i];
  9338. if (range.empty()) continue;
  9339. var from = range.from().line, to = range.to().line;
  9340. while (i < ranges.length - 1 && ranges[i + 1].from().line == to)
  9341. to = ranges[++i].to().line;
  9342. if (!ranges[i].to().ch) to--;
  9343. toSort.push(from, to);
  9344. }
  9345. if (toSort.length) selected = true;
  9346. else toSort.push(cm.firstLine(), cm.lastLine());
  9347. cm.operation(function() {
  9348. var ranges = [];
  9349. for (var i = 0; i < toSort.length; i += 2) {
  9350. var from = toSort[i], to = toSort[i + 1];
  9351. var start = Pos(from, 0), end = Pos(to);
  9352. var lines = cm.getRange(start, end, false);
  9353. if (caseSensitive)
  9354. lines.sort();
  9355. else
  9356. lines.sort(function(a, b) {
  9357. var au = a.toUpperCase(), bu = b.toUpperCase();
  9358. if (au != bu) { a = au; b = bu; }
  9359. return a < b ? -1 : a == b ? 0 : 1;
  9360. });
  9361. cm.replaceRange(lines, start, end);
  9362. if (selected) ranges.push({anchor: start, head: Pos(to + 1, 0)});
  9363. }
  9364. if (selected) cm.setSelections(ranges, 0);
  9365. });
  9366. }
  9367. cmds.sortLines = function(cm) { sortLines(cm, true); };
  9368. cmds.sortLinesInsensitive = function(cm) { sortLines(cm, false); };
  9369. cmds.nextBookmark = function(cm) {
  9370. var marks = cm.state.sublimeBookmarks;
  9371. if (marks) while (marks.length) {
  9372. var current = marks.shift();
  9373. var found = current.find();
  9374. if (found) {
  9375. marks.push(current);
  9376. return cm.setSelection(found.from, found.to);
  9377. }
  9378. }
  9379. };
  9380. cmds.prevBookmark = function(cm) {
  9381. var marks = cm.state.sublimeBookmarks;
  9382. if (marks) while (marks.length) {
  9383. marks.unshift(marks.pop());
  9384. var found = marks[marks.length - 1].find();
  9385. if (!found)
  9386. marks.pop();
  9387. else
  9388. return cm.setSelection(found.from, found.to);
  9389. }
  9390. };
  9391. cmds.toggleBookmark = function(cm) {
  9392. var ranges = cm.listSelections();
  9393. var marks = cm.state.sublimeBookmarks || (cm.state.sublimeBookmarks = []);
  9394. for (var i = 0; i < ranges.length; i++) {
  9395. var from = ranges[i].from(), to = ranges[i].to();
  9396. var found = ranges[i].empty() ? cm.findMarksAt(from) : cm.findMarks(from, to);
  9397. for (var j = 0; j < found.length; j++) {
  9398. if (found[j].sublimeBookmark) {
  9399. found[j].clear();
  9400. for (var k = 0; k < marks.length; k++)
  9401. if (marks[k] == found[j])
  9402. marks.splice(k--, 1);
  9403. break;
  9404. }
  9405. }
  9406. if (j == found.length)
  9407. marks.push(cm.markText(from, to, {sublimeBookmark: true, clearWhenEmpty: false}));
  9408. }
  9409. };
  9410. cmds.clearBookmarks = function(cm) {
  9411. var marks = cm.state.sublimeBookmarks;
  9412. if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear();
  9413. marks.length = 0;
  9414. };
  9415. cmds.selectBookmarks = function(cm) {
  9416. var marks = cm.state.sublimeBookmarks, ranges = [];
  9417. if (marks) for (var i = 0; i < marks.length; i++) {
  9418. var found = marks[i].find();
  9419. if (!found)
  9420. marks.splice(i--, 0);
  9421. else
  9422. ranges.push({anchor: found.from, head: found.to});
  9423. }
  9424. if (ranges.length)
  9425. cm.setSelections(ranges, 0);
  9426. };
  9427. function modifyWordOrSelection(cm, mod) {
  9428. cm.operation(function() {
  9429. var ranges = cm.listSelections(), indices = [], replacements = [];
  9430. for (var i = 0; i < ranges.length; i++) {
  9431. var range = ranges[i];
  9432. if (range.empty()) { indices.push(i); replacements.push(""); }
  9433. else replacements.push(mod(cm.getRange(range.from(), range.to())));
  9434. }
  9435. cm.replaceSelections(replacements, "around", "case");
  9436. for (var i = indices.length - 1, at; i >= 0; i--) {
  9437. var range = ranges[indices[i]];
  9438. if (at && CodeMirror.cmpPos(range.head, at) > 0) continue;
  9439. var word = wordAt(cm, range.head);
  9440. at = word.from;
  9441. cm.replaceRange(mod(word.word), word.from, word.to);
  9442. }
  9443. });
  9444. }
  9445. cmds.smartBackspace = function(cm) {
  9446. if (cm.somethingSelected()) return CodeMirror.Pass;
  9447. cm.operation(function() {
  9448. var cursors = cm.listSelections();
  9449. var indentUnit = cm.getOption("indentUnit");
  9450. for (var i = cursors.length - 1; i >= 0; i--) {
  9451. var cursor = cursors[i].head;
  9452. var toStartOfLine = cm.getRange({line: cursor.line, ch: 0}, cursor);
  9453. var column = CodeMirror.countColumn(toStartOfLine, null, cm.getOption("tabSize"));
  9454. // Delete by one character by default
  9455. var deletePos = cm.findPosH(cursor, -1, "char", false);
  9456. if (toStartOfLine && !/\S/.test(toStartOfLine) && column % indentUnit == 0) {
  9457. var prevIndent = new Pos(cursor.line,
  9458. CodeMirror.findColumn(toStartOfLine, column - indentUnit, indentUnit));
  9459. // Smart delete only if we found a valid prevIndent location
  9460. if (prevIndent.ch != cursor.ch) deletePos = prevIndent;
  9461. }
  9462. cm.replaceRange("", deletePos, cursor, "+delete");
  9463. }
  9464. });
  9465. };
  9466. cmds.delLineRight = function(cm) {
  9467. cm.operation(function() {
  9468. var ranges = cm.listSelections();
  9469. for (var i = ranges.length - 1; i >= 0; i--)
  9470. cm.replaceRange("", ranges[i].anchor, Pos(ranges[i].to().line), "+delete");
  9471. cm.scrollIntoView();
  9472. });
  9473. };
  9474. cmds.upcaseAtCursor = function(cm) {
  9475. modifyWordOrSelection(cm, function(str) { return str.toUpperCase(); });
  9476. };
  9477. cmds.downcaseAtCursor = function(cm) {
  9478. modifyWordOrSelection(cm, function(str) { return str.toLowerCase(); });
  9479. };
  9480. cmds.setSublimeMark = function(cm) {
  9481. if (cm.state.sublimeMark) cm.state.sublimeMark.clear();
  9482. cm.state.sublimeMark = cm.setBookmark(cm.getCursor());
  9483. };
  9484. cmds.selectToSublimeMark = function(cm) {
  9485. var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
  9486. if (found) cm.setSelection(cm.getCursor(), found);
  9487. };
  9488. cmds.deleteToSublimeMark = function(cm) {
  9489. var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
  9490. if (found) {
  9491. var from = cm.getCursor(), to = found;
  9492. if (CodeMirror.cmpPos(from, to) > 0) { var tmp = to; to = from; from = tmp; }
  9493. cm.state.sublimeKilled = cm.getRange(from, to);
  9494. cm.replaceRange("", from, to);
  9495. }
  9496. };
  9497. cmds.swapWithSublimeMark = function(cm) {
  9498. var found = cm.state.sublimeMark && cm.state.sublimeMark.find();
  9499. if (found) {
  9500. cm.state.sublimeMark.clear();
  9501. cm.state.sublimeMark = cm.setBookmark(cm.getCursor());
  9502. cm.setCursor(found);
  9503. }
  9504. };
  9505. cmds.sublimeYank = function(cm) {
  9506. if (cm.state.sublimeKilled != null)
  9507. cm.replaceSelection(cm.state.sublimeKilled, null, "paste");
  9508. };
  9509. cmds.showInCenter = function(cm) {
  9510. var pos = cm.cursorCoords(null, "local");
  9511. cm.scrollTo(null, (pos.top + pos.bottom) / 2 - cm.getScrollInfo().clientHeight / 2);
  9512. };
  9513. function getTarget(cm) {
  9514. var from = cm.getCursor("from"), to = cm.getCursor("to");
  9515. if (CodeMirror.cmpPos(from, to) == 0) {
  9516. var word = wordAt(cm, from);
  9517. if (!word.word) return;
  9518. from = word.from;
  9519. to = word.to;
  9520. }
  9521. return {from: from, to: to, query: cm.getRange(from, to), word: word};
  9522. }
  9523. function findAndGoTo(cm, forward) {
  9524. var target = getTarget(cm);
  9525. if (!target) return;
  9526. var query = target.query;
  9527. var cur = cm.getSearchCursor(query, forward ? target.to : target.from);
  9528. if (forward ? cur.findNext() : cur.findPrevious()) {
  9529. cm.setSelection(cur.from(), cur.to());
  9530. } else {
  9531. cur = cm.getSearchCursor(query, forward ? Pos(cm.firstLine(), 0)
  9532. : cm.clipPos(Pos(cm.lastLine())));
  9533. if (forward ? cur.findNext() : cur.findPrevious())
  9534. cm.setSelection(cur.from(), cur.to());
  9535. else if (target.word)
  9536. cm.setSelection(target.from, target.to);
  9537. }
  9538. };
  9539. cmds.findUnder = function(cm) { findAndGoTo(cm, true); };
  9540. cmds.findUnderPrevious = function(cm) { findAndGoTo(cm,false); };
  9541. cmds.findAllUnder = function(cm) {
  9542. var target = getTarget(cm);
  9543. if (!target) return;
  9544. var cur = cm.getSearchCursor(target.query);
  9545. var matches = [];
  9546. var primaryIndex = -1;
  9547. while (cur.findNext()) {
  9548. matches.push({anchor: cur.from(), head: cur.to()});
  9549. if (cur.from().line <= target.from.line && cur.from().ch <= target.from.ch)
  9550. primaryIndex++;
  9551. }
  9552. cm.setSelections(matches, primaryIndex);
  9553. };
  9554. var keyMap = CodeMirror.keyMap;
  9555. keyMap.macSublime = {
  9556. "Cmd-Left": "goLineStartSmart",
  9557. "Shift-Tab": "indentLess",
  9558. "Shift-Ctrl-K": "deleteLine",
  9559. "Alt-Q": "wrapLines",
  9560. "Ctrl-Left": "goSubwordLeft",
  9561. "Ctrl-Right": "goSubwordRight",
  9562. "Ctrl-Alt-Up": "scrollLineUp",
  9563. "Ctrl-Alt-Down": "scrollLineDown",
  9564. "Cmd-L": "selectLine",
  9565. "Shift-Cmd-L": "splitSelectionByLine",
  9566. "Esc": "singleSelectionTop",
  9567. "Cmd-Enter": "insertLineAfter",
  9568. "Shift-Cmd-Enter": "insertLineBefore",
  9569. "Cmd-D": "selectNextOccurrence",
  9570. "Shift-Cmd-Space": "selectScope",
  9571. "Shift-Cmd-M": "selectBetweenBrackets",
  9572. "Cmd-M": "goToBracket",
  9573. "Cmd-Ctrl-Up": "swapLineUp",
  9574. "Cmd-Ctrl-Down": "swapLineDown",
  9575. "Cmd-/": "toggleCommentIndented",
  9576. "Cmd-J": "joinLines",
  9577. "Shift-Cmd-D": "duplicateLine",
  9578. "F5": "sortLines",
  9579. "Cmd-F5": "sortLinesInsensitive",
  9580. "F2": "nextBookmark",
  9581. "Shift-F2": "prevBookmark",
  9582. "Cmd-F2": "toggleBookmark",
  9583. "Shift-Cmd-F2": "clearBookmarks",
  9584. "Alt-F2": "selectBookmarks",
  9585. "Backspace": "smartBackspace",
  9586. "Cmd-K Cmd-D": "skipAndSelectNextOccurrence",
  9587. "Cmd-K Cmd-K": "delLineRight",
  9588. "Cmd-K Cmd-U": "upcaseAtCursor",
  9589. "Cmd-K Cmd-L": "downcaseAtCursor",
  9590. "Cmd-K Cmd-Space": "setSublimeMark",
  9591. "Cmd-K Cmd-A": "selectToSublimeMark",
  9592. "Cmd-K Cmd-W": "deleteToSublimeMark",
  9593. "Cmd-K Cmd-X": "swapWithSublimeMark",
  9594. "Cmd-K Cmd-Y": "sublimeYank",
  9595. "Cmd-K Cmd-C": "showInCenter",
  9596. "Cmd-K Cmd-G": "clearBookmarks",
  9597. "Cmd-K Cmd-Backspace": "delLineLeft",
  9598. "Cmd-K Cmd-1": "foldAll",
  9599. "Cmd-K Cmd-0": "unfoldAll",
  9600. "Cmd-K Cmd-J": "unfoldAll",
  9601. "Ctrl-Shift-Up": "addCursorToPrevLine",
  9602. "Ctrl-Shift-Down": "addCursorToNextLine",
  9603. "Cmd-F3": "findUnder",
  9604. "Shift-Cmd-F3": "findUnderPrevious",
  9605. "Alt-F3": "findAllUnder",
  9606. "Shift-Cmd-[": "fold",
  9607. "Shift-Cmd-]": "unfold",
  9608. "Cmd-I": "findIncremental",
  9609. "Shift-Cmd-I": "findIncrementalReverse",
  9610. "Cmd-H": "replace",
  9611. "F3": "findNext",
  9612. "Shift-F3": "findPrev",
  9613. "fallthrough": "macDefault"
  9614. };
  9615. CodeMirror.normalizeKeyMap(keyMap.macSublime);
  9616. keyMap.pcSublime = {
  9617. "Shift-Tab": "indentLess",
  9618. "Shift-Ctrl-K": "deleteLine",
  9619. "Alt-Q": "wrapLines",
  9620. "Ctrl-T": "transposeChars",
  9621. "Alt-Left": "goSubwordLeft",
  9622. "Alt-Right": "goSubwordRight",
  9623. "Ctrl-Up": "scrollLineUp",
  9624. "Ctrl-Down": "scrollLineDown",
  9625. "Ctrl-L": "selectLine",
  9626. "Shift-Ctrl-L": "splitSelectionByLine",
  9627. "Esc": "singleSelectionTop",
  9628. "Ctrl-Enter": "insertLineAfter",
  9629. "Shift-Ctrl-Enter": "insertLineBefore",
  9630. "Ctrl-D": "selectNextOccurrence",
  9631. "Shift-Ctrl-Space": "selectScope",
  9632. "Shift-Ctrl-M": "selectBetweenBrackets",
  9633. "Ctrl-M": "goToBracket",
  9634. "Shift-Ctrl-Up": "swapLineUp",
  9635. "Shift-Ctrl-Down": "swapLineDown",
  9636. "Ctrl-/": "toggleCommentIndented",
  9637. "Ctrl-J": "joinLines",
  9638. "Shift-Ctrl-D": "duplicateLine",
  9639. "F9": "sortLines",
  9640. "Ctrl-F9": "sortLinesInsensitive",
  9641. "F2": "nextBookmark",
  9642. "Shift-F2": "prevBookmark",
  9643. "Ctrl-F2": "toggleBookmark",
  9644. "Shift-Ctrl-F2": "clearBookmarks",
  9645. "Alt-F2": "selectBookmarks",
  9646. "Backspace": "smartBackspace",
  9647. "Ctrl-K Ctrl-D": "skipAndSelectNextOccurrence",
  9648. "Ctrl-K Ctrl-K": "delLineRight",
  9649. "Ctrl-K Ctrl-U": "upcaseAtCursor",
  9650. "Ctrl-K Ctrl-L": "downcaseAtCursor",
  9651. "Ctrl-K Ctrl-Space": "setSublimeMark",
  9652. "Ctrl-K Ctrl-A": "selectToSublimeMark",
  9653. "Ctrl-K Ctrl-W": "deleteToSublimeMark",
  9654. "Ctrl-K Ctrl-X": "swapWithSublimeMark",
  9655. "Ctrl-K Ctrl-Y": "sublimeYank",
  9656. "Ctrl-K Ctrl-C": "showInCenter",
  9657. "Ctrl-K Ctrl-G": "clearBookmarks",
  9658. "Ctrl-K Ctrl-Backspace": "delLineLeft",
  9659. "Ctrl-K Ctrl-1": "foldAll",
  9660. "Ctrl-K Ctrl-0": "unfoldAll",
  9661. "Ctrl-K Ctrl-J": "unfoldAll",
  9662. "Ctrl-Alt-Up": "addCursorToPrevLine",
  9663. "Ctrl-Alt-Down": "addCursorToNextLine",
  9664. "Ctrl-F3": "findUnder",
  9665. "Shift-Ctrl-F3": "findUnderPrevious",
  9666. "Alt-F3": "findAllUnder",
  9667. "Shift-Ctrl-[": "fold",
  9668. "Shift-Ctrl-]": "unfold",
  9669. "Ctrl-I": "findIncremental",
  9670. "Shift-Ctrl-I": "findIncrementalReverse",
  9671. "Ctrl-H": "replace",
  9672. "F3": "findNext",
  9673. "Shift-F3": "findPrev",
  9674. "fallthrough": "pcDefault"
  9675. };
  9676. CodeMirror.normalizeKeyMap(keyMap.pcSublime);
  9677. var mac = keyMap.default == keyMap.macDefault;
  9678. keyMap.sublime = mac ? keyMap.macSublime : keyMap.pcSublime;
  9679. });
  9680. /* ---- extension/dialog/dialog.js ---- */
  9681. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  9682. // Distributed under an MIT license: https://codemirror.net/LICENSE
  9683. // Open simple dialogs on top of an editor. Relies on dialog.css.
  9684. (function(mod) {
  9685. if (typeof exports == "object" && typeof module == "object") // CommonJS
  9686. mod(require("../../lib/codemirror"));
  9687. else if (typeof define == "function" && define.amd) // AMD
  9688. define(["../../lib/codemirror"], mod);
  9689. else // Plain browser env
  9690. mod(CodeMirror);
  9691. })(function(CodeMirror) {
  9692. function dialogDiv(cm, template, bottom) {
  9693. var wrap = cm.getWrapperElement();
  9694. var dialog;
  9695. dialog = wrap.appendChild(document.createElement("div"));
  9696. if (bottom)
  9697. dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom";
  9698. else
  9699. dialog.className = "CodeMirror-dialog CodeMirror-dialog-top";
  9700. if (typeof template == "string") {
  9701. dialog.innerHTML = template;
  9702. } else { // Assuming it's a detached DOM element.
  9703. dialog.appendChild(template);
  9704. }
  9705. CodeMirror.addClass(wrap, 'dialog-opened');
  9706. return dialog;
  9707. }
  9708. function closeNotification(cm, newVal) {
  9709. if (cm.state.currentNotificationClose)
  9710. cm.state.currentNotificationClose();
  9711. cm.state.currentNotificationClose = newVal;
  9712. }
  9713. CodeMirror.defineExtension("openDialog", function(template, callback, options) {
  9714. if (!options) options = {};
  9715. closeNotification(this, null);
  9716. var dialog = dialogDiv(this, template, options.bottom);
  9717. var closed = false, me = this;
  9718. function close(newVal) {
  9719. if (typeof newVal == 'string') {
  9720. inp.value = newVal;
  9721. } else {
  9722. if (closed) return;
  9723. closed = true;
  9724. CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
  9725. dialog.parentNode.removeChild(dialog);
  9726. me.focus();
  9727. if (options.onClose) options.onClose(dialog);
  9728. }
  9729. }
  9730. var inp = dialog.getElementsByTagName("input")[0], button;
  9731. if (inp) {
  9732. inp.focus();
  9733. if (options.value) {
  9734. inp.value = options.value;
  9735. if (options.selectValueOnOpen !== false) {
  9736. inp.select();
  9737. }
  9738. }
  9739. if (options.onInput)
  9740. CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);});
  9741. if (options.onKeyUp)
  9742. CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
  9743. CodeMirror.on(inp, "keydown", function(e) {
  9744. if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }
  9745. if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) {
  9746. inp.blur();
  9747. CodeMirror.e_stop(e);
  9748. close();
  9749. }
  9750. if (e.keyCode == 13) callback(inp.value, e);
  9751. });
  9752. if (options.closeOnBlur !== false) CodeMirror.on(dialog, "focusout", function (evt) {
  9753. if (evt.relatedTarget !== null) close();
  9754. });
  9755. } else if (button = dialog.getElementsByTagName("button")[0]) {
  9756. CodeMirror.on(button, "click", function() {
  9757. close();
  9758. me.focus();
  9759. });
  9760. if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close);
  9761. button.focus();
  9762. }
  9763. return close;
  9764. });
  9765. CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) {
  9766. closeNotification(this, null);
  9767. var dialog = dialogDiv(this, template, options && options.bottom);
  9768. var buttons = dialog.getElementsByTagName("button");
  9769. var closed = false, me = this, blurring = 1;
  9770. function close() {
  9771. if (closed) return;
  9772. closed = true;
  9773. CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
  9774. dialog.parentNode.removeChild(dialog);
  9775. me.focus();
  9776. }
  9777. buttons[0].focus();
  9778. for (var i = 0; i < buttons.length; ++i) {
  9779. var b = buttons[i];
  9780. (function(callback) {
  9781. CodeMirror.on(b, "click", function(e) {
  9782. CodeMirror.e_preventDefault(e);
  9783. close();
  9784. if (callback) callback(me);
  9785. });
  9786. })(callbacks[i]);
  9787. CodeMirror.on(b, "blur", function() {
  9788. --blurring;
  9789. setTimeout(function() { if (blurring <= 0) close(); }, 200);
  9790. });
  9791. CodeMirror.on(b, "focus", function() { ++blurring; });
  9792. }
  9793. });
  9794. /*
  9795. * openNotification
  9796. * Opens a notification, that can be closed with an optional timer
  9797. * (default 5000ms timer) and always closes on click.
  9798. *
  9799. * If a notification is opened while another is opened, it will close the
  9800. * currently opened one and open the new one immediately.
  9801. */
  9802. CodeMirror.defineExtension("openNotification", function(template, options) {
  9803. closeNotification(this, close);
  9804. var dialog = dialogDiv(this, template, options && options.bottom);
  9805. var closed = false, doneTimer;
  9806. var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000;
  9807. function close() {
  9808. if (closed) return;
  9809. closed = true;
  9810. clearTimeout(doneTimer);
  9811. CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
  9812. dialog.parentNode.removeChild(dialog);
  9813. }
  9814. CodeMirror.on(dialog, 'click', function(e) {
  9815. CodeMirror.e_preventDefault(e);
  9816. close();
  9817. });
  9818. if (duration)
  9819. doneTimer = setTimeout(close, duration);
  9820. return close;
  9821. });
  9822. });
  9823. /* ---- extension/edit/closebrackets.js ---- */
  9824. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  9825. // Distributed under an MIT license: https://codemirror.net/LICENSE
  9826. (function(mod) {
  9827. if (typeof exports == "object" && typeof module == "object") // CommonJS
  9828. mod(require("../../lib/codemirror"));
  9829. else if (typeof define == "function" && define.amd) // AMD
  9830. define(["../../lib/codemirror"], mod);
  9831. else // Plain browser env
  9832. mod(CodeMirror);
  9833. })(function(CodeMirror) {
  9834. var defaults = {
  9835. pairs: "()[]{}''\"\"",
  9836. closeBefore: ")]}'\":;>",
  9837. triples: "",
  9838. explode: "[]{}"
  9839. };
  9840. var Pos = CodeMirror.Pos;
  9841. CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
  9842. if (old && old != CodeMirror.Init) {
  9843. cm.removeKeyMap(keyMap);
  9844. cm.state.closeBrackets = null;
  9845. }
  9846. if (val) {
  9847. ensureBound(getOption(val, "pairs"))
  9848. cm.state.closeBrackets = val;
  9849. cm.addKeyMap(keyMap);
  9850. }
  9851. });
  9852. function getOption(conf, name) {
  9853. if (name == "pairs" && typeof conf == "string") return conf;
  9854. if (typeof conf == "object" && conf[name] != null) return conf[name];
  9855. return defaults[name];
  9856. }
  9857. var keyMap = {Backspace: handleBackspace, Enter: handleEnter};
  9858. function ensureBound(chars) {
  9859. for (var i = 0; i < chars.length; i++) {
  9860. var ch = chars.charAt(i), key = "'" + ch + "'"
  9861. if (!keyMap[key]) keyMap[key] = handler(ch)
  9862. }
  9863. }
  9864. ensureBound(defaults.pairs + "`")
  9865. function handler(ch) {
  9866. return function(cm) { return handleChar(cm, ch); };
  9867. }
  9868. function getConfig(cm) {
  9869. var deflt = cm.state.closeBrackets;
  9870. if (!deflt || deflt.override) return deflt;
  9871. var mode = cm.getModeAt(cm.getCursor());
  9872. return mode.closeBrackets || deflt;
  9873. }
  9874. function handleBackspace(cm) {
  9875. var conf = getConfig(cm);
  9876. if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
  9877. var pairs = getOption(conf, "pairs");
  9878. var ranges = cm.listSelections();
  9879. for (var i = 0; i < ranges.length; i++) {
  9880. if (!ranges[i].empty()) return CodeMirror.Pass;
  9881. var around = charsAround(cm, ranges[i].head);
  9882. if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
  9883. }
  9884. for (var i = ranges.length - 1; i >= 0; i--) {
  9885. var cur = ranges[i].head;
  9886. cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1), "+delete");
  9887. }
  9888. }
  9889. function handleEnter(cm) {
  9890. var conf = getConfig(cm);
  9891. var explode = conf && getOption(conf, "explode");
  9892. if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
  9893. var ranges = cm.listSelections();
  9894. for (var i = 0; i < ranges.length; i++) {
  9895. if (!ranges[i].empty()) return CodeMirror.Pass;
  9896. var around = charsAround(cm, ranges[i].head);
  9897. if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
  9898. }
  9899. cm.operation(function() {
  9900. var linesep = cm.lineSeparator() || "\n";
  9901. cm.replaceSelection(linesep + linesep, null);
  9902. cm.execCommand("goCharLeft");
  9903. ranges = cm.listSelections();
  9904. for (var i = 0; i < ranges.length; i++) {
  9905. var line = ranges[i].head.line;
  9906. cm.indentLine(line, null, true);
  9907. cm.indentLine(line + 1, null, true);
  9908. }
  9909. });
  9910. }
  9911. function contractSelection(sel) {
  9912. var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0;
  9913. return {anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)),
  9914. head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))};
  9915. }
  9916. function handleChar(cm, ch) {
  9917. var conf = getConfig(cm);
  9918. if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
  9919. var pairs = getOption(conf, "pairs");
  9920. var pos = pairs.indexOf(ch);
  9921. if (pos == -1) return CodeMirror.Pass;
  9922. var closeBefore = getOption(conf,"closeBefore");
  9923. var triples = getOption(conf, "triples");
  9924. var identical = pairs.charAt(pos + 1) == ch;
  9925. var ranges = cm.listSelections();
  9926. var opening = pos % 2 == 0;
  9927. var type;
  9928. for (var i = 0; i < ranges.length; i++) {
  9929. var range = ranges[i], cur = range.head, curType;
  9930. var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
  9931. if (opening && !range.empty()) {
  9932. curType = "surround";
  9933. } else if ((identical || !opening) && next == ch) {
  9934. if (identical && stringStartsAfter(cm, cur))
  9935. curType = "both";
  9936. else if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch)
  9937. curType = "skipThree";
  9938. else
  9939. curType = "skip";
  9940. } else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 &&
  9941. cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch) {
  9942. if (cur.ch > 2 && /\bstring/.test(cm.getTokenTypeAt(Pos(cur.line, cur.ch - 2)))) return CodeMirror.Pass;
  9943. curType = "addFour";
  9944. } else if (identical) {
  9945. var prev = cur.ch == 0 ? " " : cm.getRange(Pos(cur.line, cur.ch - 1), cur)
  9946. if (!CodeMirror.isWordChar(next) && prev != ch && !CodeMirror.isWordChar(prev)) curType = "both";
  9947. else return CodeMirror.Pass;
  9948. } else if (opening && (next.length === 0 || /\s/.test(next) || closeBefore.indexOf(next) > -1)) {
  9949. curType = "both";
  9950. } else {
  9951. return CodeMirror.Pass;
  9952. }
  9953. if (!type) type = curType;
  9954. else if (type != curType) return CodeMirror.Pass;
  9955. }
  9956. var left = pos % 2 ? pairs.charAt(pos - 1) : ch;
  9957. var right = pos % 2 ? ch : pairs.charAt(pos + 1);
  9958. cm.operation(function() {
  9959. if (type == "skip") {
  9960. cm.execCommand("goCharRight");
  9961. } else if (type == "skipThree") {
  9962. for (var i = 0; i < 3; i++)
  9963. cm.execCommand("goCharRight");
  9964. } else if (type == "surround") {
  9965. var sels = cm.getSelections();
  9966. for (var i = 0; i < sels.length; i++)
  9967. sels[i] = left + sels[i] + right;
  9968. cm.replaceSelections(sels, "around");
  9969. sels = cm.listSelections().slice();
  9970. for (var i = 0; i < sels.length; i++)
  9971. sels[i] = contractSelection(sels[i]);
  9972. cm.setSelections(sels);
  9973. } else if (type == "both") {
  9974. cm.replaceSelection(left + right, null);
  9975. cm.triggerElectric(left + right);
  9976. cm.execCommand("goCharLeft");
  9977. } else if (type == "addFour") {
  9978. cm.replaceSelection(left + left + left + left, "before");
  9979. cm.execCommand("goCharRight");
  9980. }
  9981. });
  9982. }
  9983. function charsAround(cm, pos) {
  9984. var str = cm.getRange(Pos(pos.line, pos.ch - 1),
  9985. Pos(pos.line, pos.ch + 1));
  9986. return str.length == 2 ? str : null;
  9987. }
  9988. function stringStartsAfter(cm, pos) {
  9989. var token = cm.getTokenAt(Pos(pos.line, pos.ch + 1))
  9990. return /\bstring/.test(token.type) && token.start == pos.ch &&
  9991. (pos.ch == 0 || !/\bstring/.test(cm.getTokenTypeAt(pos)))
  9992. }
  9993. });
  9994. /* ---- extension/edit/closetag.js ---- */
  9995. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  9996. // Distributed under an MIT license: https://codemirror.net/LICENSE
  9997. /**
  9998. * Tag-closer extension for CodeMirror.
  9999. *
  10000. * This extension adds an "autoCloseTags" option that can be set to
  10001. * either true to get the default behavior, or an object to further
  10002. * configure its behavior.
  10003. *
  10004. * These are supported options:
  10005. *
  10006. * `whenClosing` (default true)
  10007. * Whether to autoclose when the '/' of a closing tag is typed.
  10008. * `whenOpening` (default true)
  10009. * Whether to autoclose the tag when the final '>' of an opening
  10010. * tag is typed.
  10011. * `dontCloseTags` (default is empty tags for HTML, none for XML)
  10012. * An array of tag names that should not be autoclosed.
  10013. * `indentTags` (default is block tags for HTML, none for XML)
  10014. * An array of tag names that should, when opened, cause a
  10015. * blank line to be added inside the tag, and the blank line and
  10016. * closing line to be indented.
  10017. * `emptyTags` (default is none)
  10018. * An array of XML tag names that should be autoclosed with '/>'.
  10019. *
  10020. * See demos/closetag.html for a usage example.
  10021. */
  10022. (function(mod) {
  10023. if (typeof exports == "object" && typeof module == "object") // CommonJS
  10024. mod(require("../../lib/codemirror"), require("../fold/xml-fold"));
  10025. else if (typeof define == "function" && define.amd) // AMD
  10026. define(["../../lib/codemirror", "../fold/xml-fold"], mod);
  10027. else // Plain browser env
  10028. mod(CodeMirror);
  10029. })(function(CodeMirror) {
  10030. CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) {
  10031. if (old != CodeMirror.Init && old)
  10032. cm.removeKeyMap("autoCloseTags");
  10033. if (!val) return;
  10034. var map = {name: "autoCloseTags"};
  10035. if (typeof val != "object" || val.whenClosing !== false)
  10036. map["'/'"] = function(cm) { return autoCloseSlash(cm); };
  10037. if (typeof val != "object" || val.whenOpening !== false)
  10038. map["'>'"] = function(cm) { return autoCloseGT(cm); };
  10039. cm.addKeyMap(map);
  10040. });
  10041. var htmlDontClose = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param",
  10042. "source", "track", "wbr"];
  10043. var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4",
  10044. "h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"];
  10045. function autoCloseGT(cm) {
  10046. if (cm.getOption("disableInput")) return CodeMirror.Pass;
  10047. var ranges = cm.listSelections(), replacements = [];
  10048. var opt = cm.getOption("autoCloseTags");
  10049. for (var i = 0; i < ranges.length; i++) {
  10050. if (!ranges[i].empty()) return CodeMirror.Pass;
  10051. var pos = ranges[i].head, tok = cm.getTokenAt(pos);
  10052. var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
  10053. var tagInfo = inner.mode.xmlCurrentTag && inner.mode.xmlCurrentTag(state)
  10054. var tagName = tagInfo && tagInfo.name
  10055. if (!tagName) return CodeMirror.Pass
  10056. var html = inner.mode.configuration == "html";
  10057. var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
  10058. var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);
  10059. if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);
  10060. var lowerTagName = tagName.toLowerCase();
  10061. // Don't process the '>' at the end of an end-tag or self-closing tag
  10062. if (!tagName ||
  10063. tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) ||
  10064. tok.type == "tag" && tagInfo.close ||
  10065. tok.string.indexOf("/") == (pos.ch - tok.start - 1) || // match something like <someTagName />
  10066. dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 ||
  10067. closingTagExists(cm, inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state) || [], tagName, pos, true))
  10068. return CodeMirror.Pass;
  10069. var emptyTags = typeof opt == "object" && opt.emptyTags;
  10070. if (emptyTags && indexOf(emptyTags, tagName) > -1) {
  10071. replacements[i] = { text: "/>", newPos: CodeMirror.Pos(pos.line, pos.ch + 2) };
  10072. continue;
  10073. }
  10074. var indent = indentTags && indexOf(indentTags, lowerTagName) > -1;
  10075. replacements[i] = {indent: indent,
  10076. text: ">" + (indent ? "\n\n" : "") + "</" + tagName + ">",
  10077. newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)};
  10078. }
  10079. var dontIndentOnAutoClose = (typeof opt == "object" && opt.dontIndentOnAutoClose);
  10080. for (var i = ranges.length - 1; i >= 0; i--) {
  10081. var info = replacements[i];
  10082. cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert");
  10083. var sel = cm.listSelections().slice(0);
  10084. sel[i] = {head: info.newPos, anchor: info.newPos};
  10085. cm.setSelections(sel);
  10086. if (!dontIndentOnAutoClose && info.indent) {
  10087. cm.indentLine(info.newPos.line, null, true);
  10088. cm.indentLine(info.newPos.line + 1, null, true);
  10089. }
  10090. }
  10091. }
  10092. function autoCloseCurrent(cm, typingSlash) {
  10093. var ranges = cm.listSelections(), replacements = [];
  10094. var head = typingSlash ? "/" : "</";
  10095. var opt = cm.getOption("autoCloseTags");
  10096. var dontIndentOnAutoClose = (typeof opt == "object" && opt.dontIndentOnSlash);
  10097. for (var i = 0; i < ranges.length; i++) {
  10098. if (!ranges[i].empty()) return CodeMirror.Pass;
  10099. var pos = ranges[i].head, tok = cm.getTokenAt(pos);
  10100. var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
  10101. if (typingSlash && (tok.type == "string" || tok.string.charAt(0) != "<" ||
  10102. tok.start != pos.ch - 1))
  10103. return CodeMirror.Pass;
  10104. // Kludge to get around the fact that we are not in XML mode
  10105. // when completing in JS/CSS snippet in htmlmixed mode. Does not
  10106. // work for other XML embedded languages (there is no general
  10107. // way to go from a mixed mode to its current XML state).
  10108. var replacement, mixed = inner.mode.name != "xml" && cm.getMode().name == "htmlmixed"
  10109. if (mixed && inner.mode.name == "javascript") {
  10110. replacement = head + "script";
  10111. } else if (mixed && inner.mode.name == "css") {
  10112. replacement = head + "style";
  10113. } else {
  10114. var context = inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state)
  10115. if (!context || (context.length && closingTagExists(cm, context, context[context.length - 1], pos)))
  10116. return CodeMirror.Pass;
  10117. replacement = head + context[context.length - 1]
  10118. }
  10119. if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">";
  10120. replacements[i] = replacement;
  10121. }
  10122. cm.replaceSelections(replacements);
  10123. ranges = cm.listSelections();
  10124. if (!dontIndentOnAutoClose) {
  10125. for (var i = 0; i < ranges.length; i++)
  10126. if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line)
  10127. cm.indentLine(ranges[i].head.line);
  10128. }
  10129. }
  10130. function autoCloseSlash(cm) {
  10131. if (cm.getOption("disableInput")) return CodeMirror.Pass;
  10132. return autoCloseCurrent(cm, true);
  10133. }
  10134. CodeMirror.commands.closeTag = function(cm) { return autoCloseCurrent(cm); };
  10135. function indexOf(collection, elt) {
  10136. if (collection.indexOf) return collection.indexOf(elt);
  10137. for (var i = 0, e = collection.length; i < e; ++i)
  10138. if (collection[i] == elt) return i;
  10139. return -1;
  10140. }
  10141. // If xml-fold is loaded, we use its functionality to try and verify
  10142. // whether a given tag is actually unclosed.
  10143. function closingTagExists(cm, context, tagName, pos, newTag) {
  10144. if (!CodeMirror.scanForClosingTag) return false;
  10145. var end = Math.min(cm.lastLine() + 1, pos.line + 500);
  10146. var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end);
  10147. if (!nextClose || nextClose.tag != tagName) return false;
  10148. // If the immediate wrapping context contains onCx instances of
  10149. // the same tag, a closing tag only exists if there are at least
  10150. // that many closing tags of that type following.
  10151. var onCx = newTag ? 1 : 0
  10152. for (var i = context.length - 1; i >= 0; i--) {
  10153. if (context[i] == tagName) ++onCx
  10154. else break
  10155. }
  10156. pos = nextClose.to;
  10157. for (var i = 1; i < onCx; i++) {
  10158. var next = CodeMirror.scanForClosingTag(cm, pos, null, end);
  10159. if (!next || next.tag != tagName) return false;
  10160. pos = next.to;
  10161. }
  10162. return true;
  10163. }
  10164. });
  10165. /* ---- extension/edit/continuelist.js ---- */
  10166. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  10167. // Distributed under an MIT license: https://codemirror.net/LICENSE
  10168. (function(mod) {
  10169. if (typeof exports == "object" && typeof module == "object") // CommonJS
  10170. mod(require("../../lib/codemirror"));
  10171. else if (typeof define == "function" && define.amd) // AMD
  10172. define(["../../lib/codemirror"], mod);
  10173. else // Plain browser env
  10174. mod(CodeMirror);
  10175. })(function(CodeMirror) {
  10176. "use strict";
  10177. var listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/,
  10178. emptyListRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/,
  10179. unorderedListRE = /[*+-]\s/;
  10180. CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
  10181. if (cm.getOption("disableInput")) return CodeMirror.Pass;
  10182. var ranges = cm.listSelections(), replacements = [];
  10183. for (var i = 0; i < ranges.length; i++) {
  10184. var pos = ranges[i].head;
  10185. // If we're not in Markdown mode, fall back to normal newlineAndIndent
  10186. var eolState = cm.getStateAfter(pos.line);
  10187. var inner = CodeMirror.innerMode(cm.getMode(), eolState);
  10188. if (inner.mode.name !== "markdown") {
  10189. cm.execCommand("newlineAndIndent");
  10190. return;
  10191. } else {
  10192. eolState = inner.state;
  10193. }
  10194. var inList = eolState.list !== false;
  10195. var inQuote = eolState.quote !== 0;
  10196. var line = cm.getLine(pos.line), match = listRE.exec(line);
  10197. var cursorBeforeBullet = /^\s*$/.test(line.slice(0, pos.ch));
  10198. if (!ranges[i].empty() || (!inList && !inQuote) || !match || cursorBeforeBullet) {
  10199. cm.execCommand("newlineAndIndent");
  10200. return;
  10201. }
  10202. if (emptyListRE.test(line)) {
  10203. var endOfQuote = inQuote && />\s*$/.test(line)
  10204. var endOfList = !/>\s*$/.test(line)
  10205. if (endOfQuote || endOfList) cm.replaceRange("", {
  10206. line: pos.line, ch: 0
  10207. }, {
  10208. line: pos.line, ch: pos.ch + 1
  10209. });
  10210. replacements[i] = "\n";
  10211. } else {
  10212. var indent = match[1], after = match[5];
  10213. var numbered = !(unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0);
  10214. var bullet = numbered ? (parseInt(match[3], 10) + 1) + match[4] : match[2].replace("x", " ");
  10215. replacements[i] = "\n" + indent + bullet + after;
  10216. if (numbered) incrementRemainingMarkdownListNumbers(cm, pos);
  10217. }
  10218. }
  10219. cm.replaceSelections(replacements);
  10220. };
  10221. // Auto-updating Markdown list numbers when a new item is added to the
  10222. // middle of a list
  10223. function incrementRemainingMarkdownListNumbers(cm, pos) {
  10224. var startLine = pos.line, lookAhead = 0, skipCount = 0;
  10225. var startItem = listRE.exec(cm.getLine(startLine)), startIndent = startItem[1];
  10226. do {
  10227. lookAhead += 1;
  10228. var nextLineNumber = startLine + lookAhead;
  10229. var nextLine = cm.getLine(nextLineNumber), nextItem = listRE.exec(nextLine);
  10230. if (nextItem) {
  10231. var nextIndent = nextItem[1];
  10232. var newNumber = (parseInt(startItem[3], 10) + lookAhead - skipCount);
  10233. var nextNumber = (parseInt(nextItem[3], 10)), itemNumber = nextNumber;
  10234. if (startIndent === nextIndent && !isNaN(nextNumber)) {
  10235. if (newNumber === nextNumber) itemNumber = nextNumber + 1;
  10236. if (newNumber > nextNumber) itemNumber = newNumber + 1;
  10237. cm.replaceRange(
  10238. nextLine.replace(listRE, nextIndent + itemNumber + nextItem[4] + nextItem[5]),
  10239. {
  10240. line: nextLineNumber, ch: 0
  10241. }, {
  10242. line: nextLineNumber, ch: nextLine.length
  10243. });
  10244. } else {
  10245. if (startIndent.length > nextIndent.length) return;
  10246. // This doesn't run if the next line immediatley indents, as it is
  10247. // not clear of the users intention (new indented item or same level)
  10248. if ((startIndent.length < nextIndent.length) && (lookAhead === 1)) return;
  10249. skipCount += 1;
  10250. }
  10251. }
  10252. } while (nextItem);
  10253. }
  10254. });
  10255. /* ---- extension/edit/matchbrackets.js ---- */
  10256. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  10257. // Distributed under an MIT license: https://codemirror.net/LICENSE
  10258. (function(mod) {
  10259. if (typeof exports == "object" && typeof module == "object") // CommonJS
  10260. mod(require("../../lib/codemirror"));
  10261. else if (typeof define == "function" && define.amd) // AMD
  10262. define(["../../lib/codemirror"], mod);
  10263. else // Plain browser env
  10264. mod(CodeMirror);
  10265. })(function(CodeMirror) {
  10266. var ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
  10267. (document.documentMode == null || document.documentMode < 8);
  10268. var Pos = CodeMirror.Pos;
  10269. var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<", "<": ">>", ">": "<<"};
  10270. function bracketRegex(config) {
  10271. return config && config.bracketRegex || /[(){}[\]]/
  10272. }
  10273. function findMatchingBracket(cm, where, config) {
  10274. var line = cm.getLineHandle(where.line), pos = where.ch - 1;
  10275. var afterCursor = config && config.afterCursor
  10276. if (afterCursor == null)
  10277. afterCursor = /(^| )cm-fat-cursor($| )/.test(cm.getWrapperElement().className)
  10278. var re = bracketRegex(config)
  10279. // A cursor is defined as between two characters, but in in vim command mode
  10280. // (i.e. not insert mode), the cursor is visually represented as a
  10281. // highlighted box on top of the 2nd character. Otherwise, we allow matches
  10282. // from before or after the cursor.
  10283. var match = (!afterCursor && pos >= 0 && re.test(line.text.charAt(pos)) && matching[line.text.charAt(pos)]) ||
  10284. re.test(line.text.charAt(pos + 1)) && matching[line.text.charAt(++pos)];
  10285. if (!match) return null;
  10286. var dir = match.charAt(1) == ">" ? 1 : -1;
  10287. if (config && config.strict && (dir > 0) != (pos == where.ch)) return null;
  10288. var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));
  10289. var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);
  10290. if (found == null) return null;
  10291. return {from: Pos(where.line, pos), to: found && found.pos,
  10292. match: found && found.ch == match.charAt(0), forward: dir > 0};
  10293. }
  10294. // bracketRegex is used to specify which type of bracket to scan
  10295. // should be a regexp, e.g. /[[\]]/
  10296. //
  10297. // Note: If "where" is on an open bracket, then this bracket is ignored.
  10298. //
  10299. // Returns false when no bracket was found, null when it reached
  10300. // maxScanLines and gave up
  10301. function scanForBracket(cm, where, dir, style, config) {
  10302. var maxScanLen = (config && config.maxScanLineLength) || 10000;
  10303. var maxScanLines = (config && config.maxScanLines) || 1000;
  10304. var stack = [];
  10305. var re = bracketRegex(config)
  10306. var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1)
  10307. : Math.max(cm.firstLine() - 1, where.line - maxScanLines);
  10308. for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {
  10309. var line = cm.getLine(lineNo);
  10310. if (!line) continue;
  10311. var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1;
  10312. if (line.length > maxScanLen) continue;
  10313. if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0);
  10314. for (; pos != end; pos += dir) {
  10315. var ch = line.charAt(pos);
  10316. if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) {
  10317. var match = matching[ch];
  10318. if (match && (match.charAt(1) == ">") == (dir > 0)) stack.push(ch);
  10319. else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch};
  10320. else stack.pop();
  10321. }
  10322. }
  10323. }
  10324. return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null;
  10325. }
  10326. function matchBrackets(cm, autoclear, config) {
  10327. // Disable brace matching in long lines, since it'll cause hugely slow updates
  10328. var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
  10329. var marks = [], ranges = cm.listSelections();
  10330. for (var i = 0; i < ranges.length; i++) {
  10331. var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, config);
  10332. if (match && cm.getLine(match.from.line).length <= maxHighlightLen) {
  10333. var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
  10334. marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));
  10335. if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen)
  10336. marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style}));
  10337. }
  10338. }
  10339. if (marks.length) {
  10340. // Kludge to work around the IE bug from issue #1193, where text
  10341. // input stops going to the textare whever this fires.
  10342. if (ie_lt8 && cm.state.focused) cm.focus();
  10343. var clear = function() {
  10344. cm.operation(function() {
  10345. for (var i = 0; i < marks.length; i++) marks[i].clear();
  10346. });
  10347. };
  10348. if (autoclear) setTimeout(clear, 800);
  10349. else return clear;
  10350. }
  10351. }
  10352. function doMatchBrackets(cm) {
  10353. cm.operation(function() {
  10354. if (cm.state.matchBrackets.currentlyHighlighted) {
  10355. cm.state.matchBrackets.currentlyHighlighted();
  10356. cm.state.matchBrackets.currentlyHighlighted = null;
  10357. }
  10358. cm.state.matchBrackets.currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);
  10359. });
  10360. }
  10361. CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
  10362. function clear(cm) {
  10363. if (cm.state.matchBrackets && cm.state.matchBrackets.currentlyHighlighted) {
  10364. cm.state.matchBrackets.currentlyHighlighted();
  10365. cm.state.matchBrackets.currentlyHighlighted = null;
  10366. }
  10367. }
  10368. if (old && old != CodeMirror.Init) {
  10369. cm.off("cursorActivity", doMatchBrackets);
  10370. cm.off("focus", doMatchBrackets)
  10371. cm.off("blur", clear)
  10372. clear(cm);
  10373. }
  10374. if (val) {
  10375. cm.state.matchBrackets = typeof val == "object" ? val : {};
  10376. cm.on("cursorActivity", doMatchBrackets);
  10377. cm.on("focus", doMatchBrackets)
  10378. cm.on("blur", clear)
  10379. }
  10380. });
  10381. CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
  10382. CodeMirror.defineExtension("findMatchingBracket", function(pos, config, oldConfig){
  10383. // Backwards-compatibility kludge
  10384. if (oldConfig || typeof config == "boolean") {
  10385. if (!oldConfig) {
  10386. config = config ? {strict: true} : null
  10387. } else {
  10388. oldConfig.strict = config
  10389. config = oldConfig
  10390. }
  10391. }
  10392. return findMatchingBracket(this, pos, config)
  10393. });
  10394. CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){
  10395. return scanForBracket(this, pos, dir, style, config);
  10396. });
  10397. });
  10398. /* ---- extension/edit/matchtags.js ---- */
  10399. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  10400. // Distributed under an MIT license: https://codemirror.net/LICENSE
  10401. (function(mod) {
  10402. if (typeof exports == "object" && typeof module == "object") // CommonJS
  10403. mod(require("../../lib/codemirror"), require("../fold/xml-fold"));
  10404. else if (typeof define == "function" && define.amd) // AMD
  10405. define(["../../lib/codemirror", "../fold/xml-fold"], mod);
  10406. else // Plain browser env
  10407. mod(CodeMirror);
  10408. })(function(CodeMirror) {
  10409. "use strict";
  10410. CodeMirror.defineOption("matchTags", false, function(cm, val, old) {
  10411. if (old && old != CodeMirror.Init) {
  10412. cm.off("cursorActivity", doMatchTags);
  10413. cm.off("viewportChange", maybeUpdateMatch);
  10414. clear(cm);
  10415. }
  10416. if (val) {
  10417. cm.state.matchBothTags = typeof val == "object" && val.bothTags;
  10418. cm.on("cursorActivity", doMatchTags);
  10419. cm.on("viewportChange", maybeUpdateMatch);
  10420. doMatchTags(cm);
  10421. }
  10422. });
  10423. function clear(cm) {
  10424. if (cm.state.tagHit) cm.state.tagHit.clear();
  10425. if (cm.state.tagOther) cm.state.tagOther.clear();
  10426. cm.state.tagHit = cm.state.tagOther = null;
  10427. }
  10428. function doMatchTags(cm) {
  10429. cm.state.failedTagMatch = false;
  10430. cm.operation(function() {
  10431. clear(cm);
  10432. if (cm.somethingSelected()) return;
  10433. var cur = cm.getCursor(), range = cm.getViewport();
  10434. range.from = Math.min(range.from, cur.line); range.to = Math.max(cur.line + 1, range.to);
  10435. var match = CodeMirror.findMatchingTag(cm, cur, range);
  10436. if (!match) return;
  10437. if (cm.state.matchBothTags) {
  10438. var hit = match.at == "open" ? match.open : match.close;
  10439. if (hit) cm.state.tagHit = cm.markText(hit.from, hit.to, {className: "CodeMirror-matchingtag"});
  10440. }
  10441. var other = match.at == "close" ? match.open : match.close;
  10442. if (other)
  10443. cm.state.tagOther = cm.markText(other.from, other.to, {className: "CodeMirror-matchingtag"});
  10444. else
  10445. cm.state.failedTagMatch = true;
  10446. });
  10447. }
  10448. function maybeUpdateMatch(cm) {
  10449. if (cm.state.failedTagMatch) doMatchTags(cm);
  10450. }
  10451. CodeMirror.commands.toMatchingTag = function(cm) {
  10452. var found = CodeMirror.findMatchingTag(cm, cm.getCursor());
  10453. if (found) {
  10454. var other = found.at == "close" ? found.open : found.close;
  10455. if (other) cm.extendSelection(other.to, other.from);
  10456. }
  10457. };
  10458. });
  10459. /* ---- extension/edit/trailingspace.js ---- */
  10460. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  10461. // Distributed under an MIT license: https://codemirror.net/LICENSE
  10462. (function(mod) {
  10463. if (typeof exports == "object" && typeof module == "object") // CommonJS
  10464. mod(require("../../lib/codemirror"));
  10465. else if (typeof define == "function" && define.amd) // AMD
  10466. define(["../../lib/codemirror"], mod);
  10467. else // Plain browser env
  10468. mod(CodeMirror);
  10469. })(function(CodeMirror) {
  10470. CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) {
  10471. if (prev == CodeMirror.Init) prev = false;
  10472. if (prev && !val)
  10473. cm.removeOverlay("trailingspace");
  10474. else if (!prev && val)
  10475. cm.addOverlay({
  10476. token: function(stream) {
  10477. for (var l = stream.string.length, i = l; i && /\s/.test(stream.string.charAt(i - 1)); --i) {}
  10478. if (i > stream.pos) { stream.pos = i; return null; }
  10479. stream.pos = l;
  10480. return "trailingspace";
  10481. },
  10482. name: "trailingspace"
  10483. });
  10484. });
  10485. });
  10486. /* ---- extension/fold/brace-fold.js ---- */
  10487. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  10488. // Distributed under an MIT license: https://codemirror.net/LICENSE
  10489. (function(mod) {
  10490. if (typeof exports == "object" && typeof module == "object") // CommonJS
  10491. mod(require("../../lib/codemirror"));
  10492. else if (typeof define == "function" && define.amd) // AMD
  10493. define(["../../lib/codemirror"], mod);
  10494. else // Plain browser env
  10495. mod(CodeMirror);
  10496. })(function(CodeMirror) {
  10497. "use strict";
  10498. CodeMirror.registerHelper("fold", "brace", function(cm, start) {
  10499. var line = start.line, lineText = cm.getLine(line);
  10500. var tokenType;
  10501. function findOpening(openCh) {
  10502. for (var at = start.ch, pass = 0;;) {
  10503. var found = at <= 0 ? -1 : lineText.lastIndexOf(openCh, at - 1);
  10504. if (found == -1) {
  10505. if (pass == 1) break;
  10506. pass = 1;
  10507. at = lineText.length;
  10508. continue;
  10509. }
  10510. if (pass == 1 && found < start.ch) break;
  10511. tokenType = cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1));
  10512. if (!/^(comment|string)/.test(tokenType)) return found + 1;
  10513. at = found - 1;
  10514. }
  10515. }
  10516. var startToken = "{", endToken = "}", startCh = findOpening("{");
  10517. if (startCh == null) {
  10518. startToken = "[", endToken = "]";
  10519. startCh = findOpening("[");
  10520. }
  10521. if (startCh == null) return;
  10522. var count = 1, lastLine = cm.lastLine(), end, endCh;
  10523. outer: for (var i = line; i <= lastLine; ++i) {
  10524. var text = cm.getLine(i), pos = i == line ? startCh : 0;
  10525. for (;;) {
  10526. var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
  10527. if (nextOpen < 0) nextOpen = text.length;
  10528. if (nextClose < 0) nextClose = text.length;
  10529. pos = Math.min(nextOpen, nextClose);
  10530. if (pos == text.length) break;
  10531. if (cm.getTokenTypeAt(CodeMirror.Pos(i, pos + 1)) == tokenType) {
  10532. if (pos == nextOpen) ++count;
  10533. else if (!--count) { end = i; endCh = pos; break outer; }
  10534. }
  10535. ++pos;
  10536. }
  10537. }
  10538. if (end == null || line == end) return;
  10539. return {from: CodeMirror.Pos(line, startCh),
  10540. to: CodeMirror.Pos(end, endCh)};
  10541. });
  10542. CodeMirror.registerHelper("fold", "import", function(cm, start) {
  10543. function hasImport(line) {
  10544. if (line < cm.firstLine() || line > cm.lastLine()) return null;
  10545. var start = cm.getTokenAt(CodeMirror.Pos(line, 1));
  10546. if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1));
  10547. if (start.type != "keyword" || start.string != "import") return null;
  10548. // Now find closing semicolon, return its position
  10549. for (var i = line, e = Math.min(cm.lastLine(), line + 10); i <= e; ++i) {
  10550. var text = cm.getLine(i), semi = text.indexOf(";");
  10551. if (semi != -1) return {startCh: start.end, end: CodeMirror.Pos(i, semi)};
  10552. }
  10553. }
  10554. var startLine = start.line, has = hasImport(startLine), prev;
  10555. if (!has || hasImport(startLine - 1) || ((prev = hasImport(startLine - 2)) && prev.end.line == startLine - 1))
  10556. return null;
  10557. for (var end = has.end;;) {
  10558. var next = hasImport(end.line + 1);
  10559. if (next == null) break;
  10560. end = next.end;
  10561. }
  10562. return {from: cm.clipPos(CodeMirror.Pos(startLine, has.startCh + 1)), to: end};
  10563. });
  10564. CodeMirror.registerHelper("fold", "include", function(cm, start) {
  10565. function hasInclude(line) {
  10566. if (line < cm.firstLine() || line > cm.lastLine()) return null;
  10567. var start = cm.getTokenAt(CodeMirror.Pos(line, 1));
  10568. if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1));
  10569. if (start.type == "meta" && start.string.slice(0, 8) == "#include") return start.start + 8;
  10570. }
  10571. var startLine = start.line, has = hasInclude(startLine);
  10572. if (has == null || hasInclude(startLine - 1) != null) return null;
  10573. for (var end = startLine;;) {
  10574. var next = hasInclude(end + 1);
  10575. if (next == null) break;
  10576. ++end;
  10577. }
  10578. return {from: CodeMirror.Pos(startLine, has + 1),
  10579. to: cm.clipPos(CodeMirror.Pos(end))};
  10580. });
  10581. });
  10582. /* ---- extension/fold/comment-fold.js ---- */
  10583. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  10584. // Distributed under an MIT license: https://codemirror.net/LICENSE
  10585. (function(mod) {
  10586. if (typeof exports == "object" && typeof module == "object") // CommonJS
  10587. mod(require("../../lib/codemirror"));
  10588. else if (typeof define == "function" && define.amd) // AMD
  10589. define(["../../lib/codemirror"], mod);
  10590. else // Plain browser env
  10591. mod(CodeMirror);
  10592. })(function(CodeMirror) {
  10593. "use strict";
  10594. CodeMirror.registerGlobalHelper("fold", "comment", function(mode) {
  10595. return mode.blockCommentStart && mode.blockCommentEnd;
  10596. }, function(cm, start) {
  10597. var mode = cm.getModeAt(start), startToken = mode.blockCommentStart, endToken = mode.blockCommentEnd;
  10598. if (!startToken || !endToken) return;
  10599. var line = start.line, lineText = cm.getLine(line);
  10600. var startCh;
  10601. for (var at = start.ch, pass = 0;;) {
  10602. var found = at <= 0 ? -1 : lineText.lastIndexOf(startToken, at - 1);
  10603. if (found == -1) {
  10604. if (pass == 1) return;
  10605. pass = 1;
  10606. at = lineText.length;
  10607. continue;
  10608. }
  10609. if (pass == 1 && found < start.ch) return;
  10610. if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1))) &&
  10611. (found == 0 || lineText.slice(found - endToken.length, found) == endToken ||
  10612. !/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found))))) {
  10613. startCh = found + startToken.length;
  10614. break;
  10615. }
  10616. at = found - 1;
  10617. }
  10618. var depth = 1, lastLine = cm.lastLine(), end, endCh;
  10619. outer: for (var i = line; i <= lastLine; ++i) {
  10620. var text = cm.getLine(i), pos = i == line ? startCh : 0;
  10621. for (;;) {
  10622. var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
  10623. if (nextOpen < 0) nextOpen = text.length;
  10624. if (nextClose < 0) nextClose = text.length;
  10625. pos = Math.min(nextOpen, nextClose);
  10626. if (pos == text.length) break;
  10627. if (pos == nextOpen) ++depth;
  10628. else if (!--depth) { end = i; endCh = pos; break outer; }
  10629. ++pos;
  10630. }
  10631. }
  10632. if (end == null || line == end && endCh == startCh) return;
  10633. return {from: CodeMirror.Pos(line, startCh),
  10634. to: CodeMirror.Pos(end, endCh)};
  10635. });
  10636. });
  10637. /* ---- extension/fold/foldcode.js ---- */
  10638. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  10639. // Distributed under an MIT license: https://codemirror.net/LICENSE
  10640. (function(mod) {
  10641. if (typeof exports == "object" && typeof module == "object") // CommonJS
  10642. mod(require("../../lib/codemirror"));
  10643. else if (typeof define == "function" && define.amd) // AMD
  10644. define(["../../lib/codemirror"], mod);
  10645. else // Plain browser env
  10646. mod(CodeMirror);
  10647. })(function(CodeMirror) {
  10648. "use strict";
  10649. function doFold(cm, pos, options, force) {
  10650. if (options && options.call) {
  10651. var finder = options;
  10652. options = null;
  10653. } else {
  10654. var finder = getOption(cm, options, "rangeFinder");
  10655. }
  10656. if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0);
  10657. var minSize = getOption(cm, options, "minFoldSize");
  10658. function getRange(allowFolded) {
  10659. var range = finder(cm, pos);
  10660. if (!range || range.to.line - range.from.line < minSize) return null;
  10661. var marks = cm.findMarksAt(range.from);
  10662. for (var i = 0; i < marks.length; ++i) {
  10663. if (marks[i].__isFold && force !== "fold") {
  10664. if (!allowFolded) return null;
  10665. range.cleared = true;
  10666. marks[i].clear();
  10667. }
  10668. }
  10669. return range;
  10670. }
  10671. var range = getRange(true);
  10672. if (getOption(cm, options, "scanUp")) while (!range && pos.line > cm.firstLine()) {
  10673. pos = CodeMirror.Pos(pos.line - 1, 0);
  10674. range = getRange(false);
  10675. }
  10676. if (!range || range.cleared || force === "unfold") return;
  10677. var myWidget = makeWidget(cm, options, range);
  10678. CodeMirror.on(myWidget, "mousedown", function(e) {
  10679. myRange.clear();
  10680. CodeMirror.e_preventDefault(e);
  10681. });
  10682. var myRange = cm.markText(range.from, range.to, {
  10683. replacedWith: myWidget,
  10684. clearOnEnter: getOption(cm, options, "clearOnEnter"),
  10685. __isFold: true
  10686. });
  10687. myRange.on("clear", function(from, to) {
  10688. CodeMirror.signal(cm, "unfold", cm, from, to);
  10689. });
  10690. CodeMirror.signal(cm, "fold", cm, range.from, range.to);
  10691. }
  10692. function makeWidget(cm, options, range) {
  10693. var widget = getOption(cm, options, "widget");
  10694. if (typeof widget == "function") {
  10695. widget = widget(range.from, range.to);
  10696. }
  10697. if (typeof widget == "string") {
  10698. var text = document.createTextNode(widget);
  10699. widget = document.createElement("span");
  10700. widget.appendChild(text);
  10701. widget.className = "CodeMirror-foldmarker";
  10702. } else if (widget) {
  10703. widget = widget.cloneNode(true)
  10704. }
  10705. return widget;
  10706. }
  10707. // Clumsy backwards-compatible interface
  10708. CodeMirror.newFoldFunction = function(rangeFinder, widget) {
  10709. return function(cm, pos) { doFold(cm, pos, {rangeFinder: rangeFinder, widget: widget}); };
  10710. };
  10711. // New-style interface
  10712. CodeMirror.defineExtension("foldCode", function(pos, options, force) {
  10713. doFold(this, pos, options, force);
  10714. });
  10715. CodeMirror.defineExtension("isFolded", function(pos) {
  10716. var marks = this.findMarksAt(pos);
  10717. for (var i = 0; i < marks.length; ++i)
  10718. if (marks[i].__isFold) return true;
  10719. });
  10720. CodeMirror.commands.toggleFold = function(cm) {
  10721. cm.foldCode(cm.getCursor());
  10722. };
  10723. CodeMirror.commands.fold = function(cm) {
  10724. cm.foldCode(cm.getCursor(), null, "fold");
  10725. };
  10726. CodeMirror.commands.unfold = function(cm) {
  10727. cm.foldCode(cm.getCursor(), null, "unfold");
  10728. };
  10729. CodeMirror.commands.foldAll = function(cm) {
  10730. cm.operation(function() {
  10731. for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
  10732. cm.foldCode(CodeMirror.Pos(i, 0), null, "fold");
  10733. });
  10734. };
  10735. CodeMirror.commands.unfoldAll = function(cm) {
  10736. cm.operation(function() {
  10737. for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
  10738. cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold");
  10739. });
  10740. };
  10741. CodeMirror.registerHelper("fold", "combine", function() {
  10742. var funcs = Array.prototype.slice.call(arguments, 0);
  10743. return function(cm, start) {
  10744. for (var i = 0; i < funcs.length; ++i) {
  10745. var found = funcs[i](cm, start);
  10746. if (found) return found;
  10747. }
  10748. };
  10749. });
  10750. CodeMirror.registerHelper("fold", "auto", function(cm, start) {
  10751. var helpers = cm.getHelpers(start, "fold");
  10752. for (var i = 0; i < helpers.length; i++) {
  10753. var cur = helpers[i](cm, start);
  10754. if (cur) return cur;
  10755. }
  10756. });
  10757. var defaultOptions = {
  10758. rangeFinder: CodeMirror.fold.auto,
  10759. widget: "\u2194",
  10760. minFoldSize: 0,
  10761. scanUp: false,
  10762. clearOnEnter: true
  10763. };
  10764. CodeMirror.defineOption("foldOptions", null);
  10765. function getOption(cm, options, name) {
  10766. if (options && options[name] !== undefined)
  10767. return options[name];
  10768. var editorOptions = cm.options.foldOptions;
  10769. if (editorOptions && editorOptions[name] !== undefined)
  10770. return editorOptions[name];
  10771. return defaultOptions[name];
  10772. }
  10773. CodeMirror.defineExtension("foldOption", function(options, name) {
  10774. return getOption(this, options, name);
  10775. });
  10776. });
  10777. /* ---- extension/fold/foldgutter.js ---- */
  10778. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  10779. // Distributed under an MIT license: https://codemirror.net/LICENSE
  10780. (function(mod) {
  10781. if (typeof exports == "object" && typeof module == "object") // CommonJS
  10782. mod(require("../../lib/codemirror"), require("./foldcode"));
  10783. else if (typeof define == "function" && define.amd) // AMD
  10784. define(["../../lib/codemirror", "./foldcode"], mod);
  10785. else // Plain browser env
  10786. mod(CodeMirror);
  10787. })(function(CodeMirror) {
  10788. "use strict";
  10789. CodeMirror.defineOption("foldGutter", false, function(cm, val, old) {
  10790. if (old && old != CodeMirror.Init) {
  10791. cm.clearGutter(cm.state.foldGutter.options.gutter);
  10792. cm.state.foldGutter = null;
  10793. cm.off("gutterClick", onGutterClick);
  10794. cm.off("changes", onChange);
  10795. cm.off("viewportChange", onViewportChange);
  10796. cm.off("fold", onFold);
  10797. cm.off("unfold", onFold);
  10798. cm.off("swapDoc", onChange);
  10799. }
  10800. if (val) {
  10801. cm.state.foldGutter = new State(parseOptions(val));
  10802. updateInViewport(cm);
  10803. cm.on("gutterClick", onGutterClick);
  10804. cm.on("changes", onChange);
  10805. cm.on("viewportChange", onViewportChange);
  10806. cm.on("fold", onFold);
  10807. cm.on("unfold", onFold);
  10808. cm.on("swapDoc", onChange);
  10809. }
  10810. });
  10811. var Pos = CodeMirror.Pos;
  10812. function State(options) {
  10813. this.options = options;
  10814. this.from = this.to = 0;
  10815. }
  10816. function parseOptions(opts) {
  10817. if (opts === true) opts = {};
  10818. if (opts.gutter == null) opts.gutter = "CodeMirror-foldgutter";
  10819. if (opts.indicatorOpen == null) opts.indicatorOpen = "CodeMirror-foldgutter-open";
  10820. if (opts.indicatorFolded == null) opts.indicatorFolded = "CodeMirror-foldgutter-folded";
  10821. return opts;
  10822. }
  10823. function isFolded(cm, line) {
  10824. var marks = cm.findMarks(Pos(line, 0), Pos(line + 1, 0));
  10825. for (var i = 0; i < marks.length; ++i) {
  10826. if (marks[i].__isFold) {
  10827. var fromPos = marks[i].find(-1);
  10828. if (fromPos && fromPos.line === line)
  10829. return marks[i];
  10830. }
  10831. }
  10832. }
  10833. function marker(spec) {
  10834. if (typeof spec == "string") {
  10835. var elt = document.createElement("div");
  10836. elt.className = spec + " CodeMirror-guttermarker-subtle";
  10837. return elt;
  10838. } else {
  10839. return spec.cloneNode(true);
  10840. }
  10841. }
  10842. function updateFoldInfo(cm, from, to) {
  10843. var opts = cm.state.foldGutter.options, cur = from - 1;
  10844. var minSize = cm.foldOption(opts, "minFoldSize");
  10845. var func = cm.foldOption(opts, "rangeFinder");
  10846. // we can reuse the built-in indicator element if its className matches the new state
  10847. var clsFolded = typeof opts.indicatorFolded == "string" && classTest(opts.indicatorFolded);
  10848. var clsOpen = typeof opts.indicatorOpen == "string" && classTest(opts.indicatorOpen);
  10849. cm.eachLine(from, to, function(line) {
  10850. ++cur;
  10851. var mark = null;
  10852. var old = line.gutterMarkers;
  10853. if (old) old = old[opts.gutter];
  10854. if (isFolded(cm, cur)) {
  10855. if (clsFolded && old && clsFolded.test(old.className)) return;
  10856. mark = marker(opts.indicatorFolded);
  10857. } else {
  10858. var pos = Pos(cur, 0);
  10859. var range = func && func(cm, pos);
  10860. if (range && range.to.line - range.from.line >= minSize) {
  10861. if (clsOpen && old && clsOpen.test(old.className)) return;
  10862. mark = marker(opts.indicatorOpen);
  10863. }
  10864. }
  10865. if (!mark && !old) return;
  10866. cm.setGutterMarker(line, opts.gutter, mark);
  10867. });
  10868. }
  10869. // copied from CodeMirror/src/util/dom.js
  10870. function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") }
  10871. function updateInViewport(cm) {
  10872. var vp = cm.getViewport(), state = cm.state.foldGutter;
  10873. if (!state) return;
  10874. cm.operation(function() {
  10875. updateFoldInfo(cm, vp.from, vp.to);
  10876. });
  10877. state.from = vp.from; state.to = vp.to;
  10878. }
  10879. function onGutterClick(cm, line, gutter) {
  10880. var state = cm.state.foldGutter;
  10881. if (!state) return;
  10882. var opts = state.options;
  10883. if (gutter != opts.gutter) return;
  10884. var folded = isFolded(cm, line);
  10885. if (folded) folded.clear();
  10886. else cm.foldCode(Pos(line, 0), opts);
  10887. }
  10888. function onChange(cm) {
  10889. var state = cm.state.foldGutter;
  10890. if (!state) return;
  10891. var opts = state.options;
  10892. state.from = state.to = 0;
  10893. clearTimeout(state.changeUpdate);
  10894. state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600);
  10895. }
  10896. function onViewportChange(cm) {
  10897. var state = cm.state.foldGutter;
  10898. if (!state) return;
  10899. var opts = state.options;
  10900. clearTimeout(state.changeUpdate);
  10901. state.changeUpdate = setTimeout(function() {
  10902. var vp = cm.getViewport();
  10903. if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
  10904. updateInViewport(cm);
  10905. } else {
  10906. cm.operation(function() {
  10907. if (vp.from < state.from) {
  10908. updateFoldInfo(cm, vp.from, state.from);
  10909. state.from = vp.from;
  10910. }
  10911. if (vp.to > state.to) {
  10912. updateFoldInfo(cm, state.to, vp.to);
  10913. state.to = vp.to;
  10914. }
  10915. });
  10916. }
  10917. }, opts.updateViewportTimeSpan || 400);
  10918. }
  10919. function onFold(cm, from) {
  10920. var state = cm.state.foldGutter;
  10921. if (!state) return;
  10922. var line = from.line;
  10923. if (line >= state.from && line < state.to)
  10924. updateFoldInfo(cm, line, line + 1);
  10925. }
  10926. });
  10927. /* ---- extension/fold/indent-fold.js ---- */
  10928. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  10929. // Distributed under an MIT license: https://codemirror.net/LICENSE
  10930. (function(mod) {
  10931. if (typeof exports == "object" && typeof module == "object") // CommonJS
  10932. mod(require("../../lib/codemirror"));
  10933. else if (typeof define == "function" && define.amd) // AMD
  10934. define(["../../lib/codemirror"], mod);
  10935. else // Plain browser env
  10936. mod(CodeMirror);
  10937. })(function(CodeMirror) {
  10938. "use strict";
  10939. function lineIndent(cm, lineNo) {
  10940. var text = cm.getLine(lineNo)
  10941. var spaceTo = text.search(/\S/)
  10942. if (spaceTo == -1 || /\bcomment\b/.test(cm.getTokenTypeAt(CodeMirror.Pos(lineNo, spaceTo + 1))))
  10943. return -1
  10944. return CodeMirror.countColumn(text, null, cm.getOption("tabSize"))
  10945. }
  10946. CodeMirror.registerHelper("fold", "indent", function(cm, start) {
  10947. var myIndent = lineIndent(cm, start.line)
  10948. if (myIndent < 0) return
  10949. var lastLineInFold = null
  10950. // Go through lines until we find a line that definitely doesn't belong in
  10951. // the block we're folding, or to the end.
  10952. for (var i = start.line + 1, end = cm.lastLine(); i <= end; ++i) {
  10953. var indent = lineIndent(cm, i)
  10954. if (indent == -1) {
  10955. } else if (indent > myIndent) {
  10956. // Lines with a greater indent are considered part of the block.
  10957. lastLineInFold = i;
  10958. } else {
  10959. // If this line has non-space, non-comment content, and is
  10960. // indented less or equal to the start line, it is the start of
  10961. // another block.
  10962. break;
  10963. }
  10964. }
  10965. if (lastLineInFold) return {
  10966. from: CodeMirror.Pos(start.line, cm.getLine(start.line).length),
  10967. to: CodeMirror.Pos(lastLineInFold, cm.getLine(lastLineInFold).length)
  10968. };
  10969. });
  10970. });
  10971. /* ---- extension/fold/markdown-fold.js ---- */
  10972. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  10973. // Distributed under an MIT license: https://codemirror.net/LICENSE
  10974. (function(mod) {
  10975. if (typeof exports == "object" && typeof module == "object") // CommonJS
  10976. mod(require("../../lib/codemirror"));
  10977. else if (typeof define == "function" && define.amd) // AMD
  10978. define(["../../lib/codemirror"], mod);
  10979. else // Plain browser env
  10980. mod(CodeMirror);
  10981. })(function(CodeMirror) {
  10982. "use strict";
  10983. CodeMirror.registerHelper("fold", "markdown", function(cm, start) {
  10984. var maxDepth = 100;
  10985. function isHeader(lineNo) {
  10986. var tokentype = cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0));
  10987. return tokentype && /\bheader\b/.test(tokentype);
  10988. }
  10989. function headerLevel(lineNo, line, nextLine) {
  10990. var match = line && line.match(/^#+/);
  10991. if (match && isHeader(lineNo)) return match[0].length;
  10992. match = nextLine && nextLine.match(/^[=\-]+\s*$/);
  10993. if (match && isHeader(lineNo + 1)) return nextLine[0] == "=" ? 1 : 2;
  10994. return maxDepth;
  10995. }
  10996. var firstLine = cm.getLine(start.line), nextLine = cm.getLine(start.line + 1);
  10997. var level = headerLevel(start.line, firstLine, nextLine);
  10998. if (level === maxDepth) return undefined;
  10999. var lastLineNo = cm.lastLine();
  11000. var end = start.line, nextNextLine = cm.getLine(end + 2);
  11001. while (end < lastLineNo) {
  11002. if (headerLevel(end + 1, nextLine, nextNextLine) <= level) break;
  11003. ++end;
  11004. nextLine = nextNextLine;
  11005. nextNextLine = cm.getLine(end + 2);
  11006. }
  11007. return {
  11008. from: CodeMirror.Pos(start.line, firstLine.length),
  11009. to: CodeMirror.Pos(end, cm.getLine(end).length)
  11010. };
  11011. });
  11012. });
  11013. /* ---- extension/fold/xml-fold.js ---- */
  11014. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  11015. // Distributed under an MIT license: https://codemirror.net/LICENSE
  11016. (function(mod) {
  11017. if (typeof exports == "object" && typeof module == "object") // CommonJS
  11018. mod(require("../../lib/codemirror"));
  11019. else if (typeof define == "function" && define.amd) // AMD
  11020. define(["../../lib/codemirror"], mod);
  11021. else // Plain browser env
  11022. mod(CodeMirror);
  11023. })(function(CodeMirror) {
  11024. "use strict";
  11025. var Pos = CodeMirror.Pos;
  11026. function cmp(a, b) { return a.line - b.line || a.ch - b.ch; }
  11027. var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
  11028. var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
  11029. var xmlTagStart = new RegExp("<(/?)([" + nameStartChar + "][" + nameChar + "]*)", "g");
  11030. function Iter(cm, line, ch, range) {
  11031. this.line = line; this.ch = ch;
  11032. this.cm = cm; this.text = cm.getLine(line);
  11033. this.min = range ? Math.max(range.from, cm.firstLine()) : cm.firstLine();
  11034. this.max = range ? Math.min(range.to - 1, cm.lastLine()) : cm.lastLine();
  11035. }
  11036. function tagAt(iter, ch) {
  11037. var type = iter.cm.getTokenTypeAt(Pos(iter.line, ch));
  11038. return type && /\btag\b/.test(type);
  11039. }
  11040. function nextLine(iter) {
  11041. if (iter.line >= iter.max) return;
  11042. iter.ch = 0;
  11043. iter.text = iter.cm.getLine(++iter.line);
  11044. return true;
  11045. }
  11046. function prevLine(iter) {
  11047. if (iter.line <= iter.min) return;
  11048. iter.text = iter.cm.getLine(--iter.line);
  11049. iter.ch = iter.text.length;
  11050. return true;
  11051. }
  11052. function toTagEnd(iter) {
  11053. for (;;) {
  11054. var gt = iter.text.indexOf(">", iter.ch);
  11055. if (gt == -1) { if (nextLine(iter)) continue; else return; }
  11056. if (!tagAt(iter, gt + 1)) { iter.ch = gt + 1; continue; }
  11057. var lastSlash = iter.text.lastIndexOf("/", gt);
  11058. var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt));
  11059. iter.ch = gt + 1;
  11060. return selfClose ? "selfClose" : "regular";
  11061. }
  11062. }
  11063. function toTagStart(iter) {
  11064. for (;;) {
  11065. var lt = iter.ch ? iter.text.lastIndexOf("<", iter.ch - 1) : -1;
  11066. if (lt == -1) { if (prevLine(iter)) continue; else return; }
  11067. if (!tagAt(iter, lt + 1)) { iter.ch = lt; continue; }
  11068. xmlTagStart.lastIndex = lt;
  11069. iter.ch = lt;
  11070. var match = xmlTagStart.exec(iter.text);
  11071. if (match && match.index == lt) return match;
  11072. }
  11073. }
  11074. function toNextTag(iter) {
  11075. for (;;) {
  11076. xmlTagStart.lastIndex = iter.ch;
  11077. var found = xmlTagStart.exec(iter.text);
  11078. if (!found) { if (nextLine(iter)) continue; else return; }
  11079. if (!tagAt(iter, found.index + 1)) { iter.ch = found.index + 1; continue; }
  11080. iter.ch = found.index + found[0].length;
  11081. return found;
  11082. }
  11083. }
  11084. function toPrevTag(iter) {
  11085. for (;;) {
  11086. var gt = iter.ch ? iter.text.lastIndexOf(">", iter.ch - 1) : -1;
  11087. if (gt == -1) { if (prevLine(iter)) continue; else return; }
  11088. if (!tagAt(iter, gt + 1)) { iter.ch = gt; continue; }
  11089. var lastSlash = iter.text.lastIndexOf("/", gt);
  11090. var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt));
  11091. iter.ch = gt + 1;
  11092. return selfClose ? "selfClose" : "regular";
  11093. }
  11094. }
  11095. function findMatchingClose(iter, tag) {
  11096. var stack = [];
  11097. for (;;) {
  11098. var next = toNextTag(iter), end, startLine = iter.line, startCh = iter.ch - (next ? next[0].length : 0);
  11099. if (!next || !(end = toTagEnd(iter))) return;
  11100. if (end == "selfClose") continue;
  11101. if (next[1]) { // closing tag
  11102. for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == next[2]) {
  11103. stack.length = i;
  11104. break;
  11105. }
  11106. if (i < 0 && (!tag || tag == next[2])) return {
  11107. tag: next[2],
  11108. from: Pos(startLine, startCh),
  11109. to: Pos(iter.line, iter.ch)
  11110. };
  11111. } else { // opening tag
  11112. stack.push(next[2]);
  11113. }
  11114. }
  11115. }
  11116. function findMatchingOpen(iter, tag) {
  11117. var stack = [];
  11118. for (;;) {
  11119. var prev = toPrevTag(iter);
  11120. if (!prev) return;
  11121. if (prev == "selfClose") { toTagStart(iter); continue; }
  11122. var endLine = iter.line, endCh = iter.ch;
  11123. var start = toTagStart(iter);
  11124. if (!start) return;
  11125. if (start[1]) { // closing tag
  11126. stack.push(start[2]);
  11127. } else { // opening tag
  11128. for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == start[2]) {
  11129. stack.length = i;
  11130. break;
  11131. }
  11132. if (i < 0 && (!tag || tag == start[2])) return {
  11133. tag: start[2],
  11134. from: Pos(iter.line, iter.ch),
  11135. to: Pos(endLine, endCh)
  11136. };
  11137. }
  11138. }
  11139. }
  11140. CodeMirror.registerHelper("fold", "xml", function(cm, start) {
  11141. var iter = new Iter(cm, start.line, 0);
  11142. for (;;) {
  11143. var openTag = toNextTag(iter)
  11144. if (!openTag || iter.line != start.line) return
  11145. var end = toTagEnd(iter)
  11146. if (!end) return
  11147. if (!openTag[1] && end != "selfClose") {
  11148. var startPos = Pos(iter.line, iter.ch);
  11149. var endPos = findMatchingClose(iter, openTag[2]);
  11150. return endPos && cmp(endPos.from, startPos) > 0 ? {from: startPos, to: endPos.from} : null
  11151. }
  11152. }
  11153. });
  11154. CodeMirror.findMatchingTag = function(cm, pos, range) {
  11155. var iter = new Iter(cm, pos.line, pos.ch, range);
  11156. if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return;
  11157. var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch);
  11158. var start = end && toTagStart(iter);
  11159. if (!end || !start || cmp(iter, pos) > 0) return;
  11160. var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]};
  11161. if (end == "selfClose") return {open: here, close: null, at: "open"};
  11162. if (start[1]) { // closing tag
  11163. return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"};
  11164. } else { // opening tag
  11165. iter = new Iter(cm, to.line, to.ch, range);
  11166. return {open: here, close: findMatchingClose(iter, start[2]), at: "open"};
  11167. }
  11168. };
  11169. CodeMirror.findEnclosingTag = function(cm, pos, range, tag) {
  11170. var iter = new Iter(cm, pos.line, pos.ch, range);
  11171. for (;;) {
  11172. var open = findMatchingOpen(iter, tag);
  11173. if (!open) break;
  11174. var forward = new Iter(cm, pos.line, pos.ch, range);
  11175. var close = findMatchingClose(forward, open.tag);
  11176. if (close) return {open: open, close: close};
  11177. }
  11178. };
  11179. // Used by addon/edit/closetag.js
  11180. CodeMirror.scanForClosingTag = function(cm, pos, name, end) {
  11181. var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null);
  11182. return findMatchingClose(iter, name);
  11183. };
  11184. });
  11185. /* ---- extension/hint/anyword-hint.js ---- */
  11186. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  11187. // Distributed under an MIT license: https://codemirror.net/LICENSE
  11188. (function(mod) {
  11189. if (typeof exports == "object" && typeof module == "object") // CommonJS
  11190. mod(require("../../lib/codemirror"));
  11191. else if (typeof define == "function" && define.amd) // AMD
  11192. define(["../../lib/codemirror"], mod);
  11193. else // Plain browser env
  11194. mod(CodeMirror);
  11195. })(function(CodeMirror) {
  11196. "use strict";
  11197. var WORD = /[\w$]+/, RANGE = 500;
  11198. CodeMirror.registerHelper("hint", "anyword", function(editor, options) {
  11199. var word = options && options.word || WORD;
  11200. var range = options && options.range || RANGE;
  11201. var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
  11202. var end = cur.ch, start = end;
  11203. while (start && word.test(curLine.charAt(start - 1))) --start;
  11204. var curWord = start != end && curLine.slice(start, end);
  11205. var list = options && options.list || [], seen = {};
  11206. var re = new RegExp(word.source, "g");
  11207. for (var dir = -1; dir <= 1; dir += 2) {
  11208. var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
  11209. for (; line != endLine; line += dir) {
  11210. var text = editor.getLine(line), m;
  11211. while (m = re.exec(text)) {
  11212. if (line == cur.line && m[0] === curWord) continue;
  11213. if ((!curWord || m[0].lastIndexOf(curWord, 0) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) {
  11214. seen[m[0]] = true;
  11215. list.push(m[0]);
  11216. }
  11217. }
  11218. }
  11219. }
  11220. return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
  11221. });
  11222. });
  11223. /* ---- extension/hint/html-hint.js ---- */
  11224. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  11225. // Distributed under an MIT license: https://codemirror.net/LICENSE
  11226. (function(mod) {
  11227. if (typeof exports == "object" && typeof module == "object") // CommonJS
  11228. mod(require("../../lib/codemirror"), require("./xml-hint"));
  11229. else if (typeof define == "function" && define.amd) // AMD
  11230. define(["../../lib/codemirror", "./xml-hint"], mod);
  11231. else // Plain browser env
  11232. mod(CodeMirror);
  11233. })(function(CodeMirror) {
  11234. "use strict";
  11235. var langs = "ab aa af ak sq am ar an hy as av ae ay az bm ba eu be bn bh bi bs br bg my ca ch ce ny zh cv kw co cr hr cs da dv nl dz en eo et ee fo fj fi fr ff gl ka de el gn gu ht ha he hz hi ho hu ia id ie ga ig ik io is it iu ja jv kl kn kr ks kk km ki rw ky kv kg ko ku kj la lb lg li ln lo lt lu lv gv mk mg ms ml mt mi mr mh mn na nv nb nd ne ng nn no ii nr oc oj cu om or os pa pi fa pl ps pt qu rm rn ro ru sa sc sd se sm sg sr gd sn si sk sl so st es su sw ss sv ta te tg th ti bo tk tl tn to tr ts tt tw ty ug uk ur uz ve vi vo wa cy wo fy xh yi yo za zu".split(" ");
  11236. var targets = ["_blank", "_self", "_top", "_parent"];
  11237. var charsets = ["ascii", "utf-8", "utf-16", "latin1", "latin1"];
  11238. var methods = ["get", "post", "put", "delete"];
  11239. var encs = ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"];
  11240. var media = ["all", "screen", "print", "embossed", "braille", "handheld", "print", "projection", "screen", "tty", "tv", "speech",
  11241. "3d-glasses", "resolution [>][<][=] [X]", "device-aspect-ratio: X/Y", "orientation:portrait",
  11242. "orientation:landscape", "device-height: [X]", "device-width: [X]"];
  11243. var s = { attrs: {} }; // Simple tag, reused for a whole lot of tags
  11244. var data = {
  11245. a: {
  11246. attrs: {
  11247. href: null, ping: null, type: null,
  11248. media: media,
  11249. target: targets,
  11250. hreflang: langs
  11251. }
  11252. },
  11253. abbr: s,
  11254. acronym: s,
  11255. address: s,
  11256. applet: s,
  11257. area: {
  11258. attrs: {
  11259. alt: null, coords: null, href: null, target: null, ping: null,
  11260. media: media, hreflang: langs, type: null,
  11261. shape: ["default", "rect", "circle", "poly"]
  11262. }
  11263. },
  11264. article: s,
  11265. aside: s,
  11266. audio: {
  11267. attrs: {
  11268. src: null, mediagroup: null,
  11269. crossorigin: ["anonymous", "use-credentials"],
  11270. preload: ["none", "metadata", "auto"],
  11271. autoplay: ["", "autoplay"],
  11272. loop: ["", "loop"],
  11273. controls: ["", "controls"]
  11274. }
  11275. },
  11276. b: s,
  11277. base: { attrs: { href: null, target: targets } },
  11278. basefont: s,
  11279. bdi: s,
  11280. bdo: s,
  11281. big: s,
  11282. blockquote: { attrs: { cite: null } },
  11283. body: s,
  11284. br: s,
  11285. button: {
  11286. attrs: {
  11287. form: null, formaction: null, name: null, value: null,
  11288. autofocus: ["", "autofocus"],
  11289. disabled: ["", "autofocus"],
  11290. formenctype: encs,
  11291. formmethod: methods,
  11292. formnovalidate: ["", "novalidate"],
  11293. formtarget: targets,
  11294. type: ["submit", "reset", "button"]
  11295. }
  11296. },
  11297. canvas: { attrs: { width: null, height: null } },
  11298. caption: s,
  11299. center: s,
  11300. cite: s,
  11301. code: s,
  11302. col: { attrs: { span: null } },
  11303. colgroup: { attrs: { span: null } },
  11304. command: {
  11305. attrs: {
  11306. type: ["command", "checkbox", "radio"],
  11307. label: null, icon: null, radiogroup: null, command: null, title: null,
  11308. disabled: ["", "disabled"],
  11309. checked: ["", "checked"]
  11310. }
  11311. },
  11312. data: { attrs: { value: null } },
  11313. datagrid: { attrs: { disabled: ["", "disabled"], multiple: ["", "multiple"] } },
  11314. datalist: { attrs: { data: null } },
  11315. dd: s,
  11316. del: { attrs: { cite: null, datetime: null } },
  11317. details: { attrs: { open: ["", "open"] } },
  11318. dfn: s,
  11319. dir: s,
  11320. div: s,
  11321. dl: s,
  11322. dt: s,
  11323. em: s,
  11324. embed: { attrs: { src: null, type: null, width: null, height: null } },
  11325. eventsource: { attrs: { src: null } },
  11326. fieldset: { attrs: { disabled: ["", "disabled"], form: null, name: null } },
  11327. figcaption: s,
  11328. figure: s,
  11329. font: s,
  11330. footer: s,
  11331. form: {
  11332. attrs: {
  11333. action: null, name: null,
  11334. "accept-charset": charsets,
  11335. autocomplete: ["on", "off"],
  11336. enctype: encs,
  11337. method: methods,
  11338. novalidate: ["", "novalidate"],
  11339. target: targets
  11340. }
  11341. },
  11342. frame: s,
  11343. frameset: s,
  11344. h1: s, h2: s, h3: s, h4: s, h5: s, h6: s,
  11345. head: {
  11346. attrs: {},
  11347. children: ["title", "base", "link", "style", "meta", "script", "noscript", "command"]
  11348. },
  11349. header: s,
  11350. hgroup: s,
  11351. hr: s,
  11352. html: {
  11353. attrs: { manifest: null },
  11354. children: ["head", "body"]
  11355. },
  11356. i: s,
  11357. iframe: {
  11358. attrs: {
  11359. src: null, srcdoc: null, name: null, width: null, height: null,
  11360. sandbox: ["allow-top-navigation", "allow-same-origin", "allow-forms", "allow-scripts"],
  11361. seamless: ["", "seamless"]
  11362. }
  11363. },
  11364. img: {
  11365. attrs: {
  11366. alt: null, src: null, ismap: null, usemap: null, width: null, height: null,
  11367. crossorigin: ["anonymous", "use-credentials"]
  11368. }
  11369. },
  11370. input: {
  11371. attrs: {
  11372. alt: null, dirname: null, form: null, formaction: null,
  11373. height: null, list: null, max: null, maxlength: null, min: null,
  11374. name: null, pattern: null, placeholder: null, size: null, src: null,
  11375. step: null, value: null, width: null,
  11376. accept: ["audio/*", "video/*", "image/*"],
  11377. autocomplete: ["on", "off"],
  11378. autofocus: ["", "autofocus"],
  11379. checked: ["", "checked"],
  11380. disabled: ["", "disabled"],
  11381. formenctype: encs,
  11382. formmethod: methods,
  11383. formnovalidate: ["", "novalidate"],
  11384. formtarget: targets,
  11385. multiple: ["", "multiple"],
  11386. readonly: ["", "readonly"],
  11387. required: ["", "required"],
  11388. type: ["hidden", "text", "search", "tel", "url", "email", "password", "datetime", "date", "month",
  11389. "week", "time", "datetime-local", "number", "range", "color", "checkbox", "radio",
  11390. "file", "submit", "image", "reset", "button"]
  11391. }
  11392. },
  11393. ins: { attrs: { cite: null, datetime: null } },
  11394. kbd: s,
  11395. keygen: {
  11396. attrs: {
  11397. challenge: null, form: null, name: null,
  11398. autofocus: ["", "autofocus"],
  11399. disabled: ["", "disabled"],
  11400. keytype: ["RSA"]
  11401. }
  11402. },
  11403. label: { attrs: { "for": null, form: null } },
  11404. legend: s,
  11405. li: { attrs: { value: null } },
  11406. link: {
  11407. attrs: {
  11408. href: null, type: null,
  11409. hreflang: langs,
  11410. media: media,
  11411. sizes: ["all", "16x16", "16x16 32x32", "16x16 32x32 64x64"]
  11412. }
  11413. },
  11414. map: { attrs: { name: null } },
  11415. mark: s,
  11416. menu: { attrs: { label: null, type: ["list", "context", "toolbar"] } },
  11417. meta: {
  11418. attrs: {
  11419. content: null,
  11420. charset: charsets,
  11421. name: ["viewport", "application-name", "author", "description", "generator", "keywords"],
  11422. "http-equiv": ["content-language", "content-type", "default-style", "refresh"]
  11423. }
  11424. },
  11425. meter: { attrs: { value: null, min: null, low: null, high: null, max: null, optimum: null } },
  11426. nav: s,
  11427. noframes: s,
  11428. noscript: s,
  11429. object: {
  11430. attrs: {
  11431. data: null, type: null, name: null, usemap: null, form: null, width: null, height: null,
  11432. typemustmatch: ["", "typemustmatch"]
  11433. }
  11434. },
  11435. ol: { attrs: { reversed: ["", "reversed"], start: null, type: ["1", "a", "A", "i", "I"] } },
  11436. optgroup: { attrs: { disabled: ["", "disabled"], label: null } },
  11437. option: { attrs: { disabled: ["", "disabled"], label: null, selected: ["", "selected"], value: null } },
  11438. output: { attrs: { "for": null, form: null, name: null } },
  11439. p: s,
  11440. param: { attrs: { name: null, value: null } },
  11441. pre: s,
  11442. progress: { attrs: { value: null, max: null } },
  11443. q: { attrs: { cite: null } },
  11444. rp: s,
  11445. rt: s,
  11446. ruby: s,
  11447. s: s,
  11448. samp: s,
  11449. script: {
  11450. attrs: {
  11451. type: ["text/javascript"],
  11452. src: null,
  11453. async: ["", "async"],
  11454. defer: ["", "defer"],
  11455. charset: charsets
  11456. }
  11457. },
  11458. section: s,
  11459. select: {
  11460. attrs: {
  11461. form: null, name: null, size: null,
  11462. autofocus: ["", "autofocus"],
  11463. disabled: ["", "disabled"],
  11464. multiple: ["", "multiple"]
  11465. }
  11466. },
  11467. small: s,
  11468. source: { attrs: { src: null, type: null, media: null } },
  11469. span: s,
  11470. strike: s,
  11471. strong: s,
  11472. style: {
  11473. attrs: {
  11474. type: ["text/css"],
  11475. media: media,
  11476. scoped: null
  11477. }
  11478. },
  11479. sub: s,
  11480. summary: s,
  11481. sup: s,
  11482. table: s,
  11483. tbody: s,
  11484. td: { attrs: { colspan: null, rowspan: null, headers: null } },
  11485. textarea: {
  11486. attrs: {
  11487. dirname: null, form: null, maxlength: null, name: null, placeholder: null,
  11488. rows: null, cols: null,
  11489. autofocus: ["", "autofocus"],
  11490. disabled: ["", "disabled"],
  11491. readonly: ["", "readonly"],
  11492. required: ["", "required"],
  11493. wrap: ["soft", "hard"]
  11494. }
  11495. },
  11496. tfoot: s,
  11497. th: { attrs: { colspan: null, rowspan: null, headers: null, scope: ["row", "col", "rowgroup", "colgroup"] } },
  11498. thead: s,
  11499. time: { attrs: { datetime: null } },
  11500. title: s,
  11501. tr: s,
  11502. track: {
  11503. attrs: {
  11504. src: null, label: null, "default": null,
  11505. kind: ["subtitles", "captions", "descriptions", "chapters", "metadata"],
  11506. srclang: langs
  11507. }
  11508. },
  11509. tt: s,
  11510. u: s,
  11511. ul: s,
  11512. "var": s,
  11513. video: {
  11514. attrs: {
  11515. src: null, poster: null, width: null, height: null,
  11516. crossorigin: ["anonymous", "use-credentials"],
  11517. preload: ["auto", "metadata", "none"],
  11518. autoplay: ["", "autoplay"],
  11519. mediagroup: ["movie"],
  11520. muted: ["", "muted"],
  11521. controls: ["", "controls"]
  11522. }
  11523. },
  11524. wbr: s
  11525. };
  11526. var globalAttrs = {
  11527. accesskey: ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
  11528. "class": null,
  11529. contenteditable: ["true", "false"],
  11530. contextmenu: null,
  11531. dir: ["ltr", "rtl", "auto"],
  11532. draggable: ["true", "false", "auto"],
  11533. dropzone: ["copy", "move", "link", "string:", "file:"],
  11534. hidden: ["hidden"],
  11535. id: null,
  11536. inert: ["inert"],
  11537. itemid: null,
  11538. itemprop: null,
  11539. itemref: null,
  11540. itemscope: ["itemscope"],
  11541. itemtype: null,
  11542. lang: ["en", "es"],
  11543. spellcheck: ["true", "false"],
  11544. autocorrect: ["true", "false"],
  11545. autocapitalize: ["true", "false"],
  11546. style: null,
  11547. tabindex: ["1", "2", "3", "4", "5", "6", "7", "8", "9"],
  11548. title: null,
  11549. translate: ["yes", "no"],
  11550. onclick: null,
  11551. rel: ["stylesheet", "alternate", "author", "bookmark", "help", "license", "next", "nofollow", "noreferrer", "prefetch", "prev", "search", "tag"]
  11552. };
  11553. function populate(obj) {
  11554. for (var attr in globalAttrs) if (globalAttrs.hasOwnProperty(attr))
  11555. obj.attrs[attr] = globalAttrs[attr];
  11556. }
  11557. populate(s);
  11558. for (var tag in data) if (data.hasOwnProperty(tag) && data[tag] != s)
  11559. populate(data[tag]);
  11560. CodeMirror.htmlSchema = data;
  11561. function htmlHint(cm, options) {
  11562. var local = {schemaInfo: data};
  11563. if (options) for (var opt in options) local[opt] = options[opt];
  11564. return CodeMirror.hint.xml(cm, local);
  11565. }
  11566. CodeMirror.registerHelper("hint", "html", htmlHint);
  11567. });
  11568. /* ---- extension/hint/show-hint.js ---- */
  11569. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  11570. // Distributed under an MIT license: https://codemirror.net/LICENSE
  11571. (function(mod) {
  11572. if (typeof exports == "object" && typeof module == "object") // CommonJS
  11573. mod(require("../../lib/codemirror"));
  11574. else if (typeof define == "function" && define.amd) // AMD
  11575. define(["../../lib/codemirror"], mod);
  11576. else // Plain browser env
  11577. mod(CodeMirror);
  11578. })(function(CodeMirror) {
  11579. "use strict";
  11580. var HINT_ELEMENT_CLASS = "CodeMirror-hint";
  11581. var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
  11582. // This is the old interface, kept around for now to stay
  11583. // backwards-compatible.
  11584. CodeMirror.showHint = function(cm, getHints, options) {
  11585. if (!getHints) return cm.showHint(options);
  11586. if (options && options.async) getHints.async = true;
  11587. var newOpts = {hint: getHints};
  11588. if (options) for (var prop in options) newOpts[prop] = options[prop];
  11589. return cm.showHint(newOpts);
  11590. };
  11591. CodeMirror.defineExtension("showHint", function(options) {
  11592. options = parseOptions(this, this.getCursor("start"), options);
  11593. var selections = this.listSelections()
  11594. if (selections.length > 1) return;
  11595. // By default, don't allow completion when something is selected.
  11596. // A hint function can have a `supportsSelection` property to
  11597. // indicate that it can handle selections.
  11598. if (this.somethingSelected()) {
  11599. if (!options.hint.supportsSelection) return;
  11600. // Don't try with cross-line selections
  11601. for (var i = 0; i < selections.length; i++)
  11602. if (selections[i].head.line != selections[i].anchor.line) return;
  11603. }
  11604. if (this.state.completionActive) this.state.completionActive.close();
  11605. var completion = this.state.completionActive = new Completion(this, options);
  11606. if (!completion.options.hint) return;
  11607. CodeMirror.signal(this, "startCompletion", this);
  11608. completion.update(true);
  11609. });
  11610. CodeMirror.defineExtension("closeHint", function() {
  11611. if (this.state.completionActive) this.state.completionActive.close()
  11612. })
  11613. function Completion(cm, options) {
  11614. this.cm = cm;
  11615. this.options = options;
  11616. this.widget = null;
  11617. this.debounce = 0;
  11618. this.tick = 0;
  11619. this.startPos = this.cm.getCursor("start");
  11620. this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
  11621. var self = this;
  11622. cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
  11623. }
  11624. var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
  11625. return setTimeout(fn, 1000/60);
  11626. };
  11627. var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
  11628. Completion.prototype = {
  11629. close: function() {
  11630. if (!this.active()) return;
  11631. this.cm.state.completionActive = null;
  11632. this.tick = null;
  11633. this.cm.off("cursorActivity", this.activityFunc);
  11634. if (this.widget && this.data) CodeMirror.signal(this.data, "close");
  11635. if (this.widget) this.widget.close();
  11636. CodeMirror.signal(this.cm, "endCompletion", this.cm);
  11637. },
  11638. active: function() {
  11639. return this.cm.state.completionActive == this;
  11640. },
  11641. pick: function(data, i) {
  11642. var completion = data.list[i], self = this;
  11643. this.cm.operation(function() {
  11644. if (completion.hint)
  11645. completion.hint(self.cm, data, completion);
  11646. else
  11647. self.cm.replaceRange(getText(completion), completion.from || data.from,
  11648. completion.to || data.to, "complete");
  11649. CodeMirror.signal(data, "pick", completion);
  11650. self.cm.scrollIntoView();
  11651. })
  11652. this.close();
  11653. },
  11654. cursorActivity: function() {
  11655. if (this.debounce) {
  11656. cancelAnimationFrame(this.debounce);
  11657. this.debounce = 0;
  11658. }
  11659. var identStart = this.startPos;
  11660. if(this.data) {
  11661. identStart = this.data.from;
  11662. }
  11663. var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
  11664. if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
  11665. pos.ch < identStart.ch || this.cm.somethingSelected() ||
  11666. (!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
  11667. this.close();
  11668. } else {
  11669. var self = this;
  11670. this.debounce = requestAnimationFrame(function() {self.update();});
  11671. if (this.widget) this.widget.disable();
  11672. }
  11673. },
  11674. update: function(first) {
  11675. if (this.tick == null) return
  11676. var self = this, myTick = ++this.tick
  11677. fetchHints(this.options.hint, this.cm, this.options, function(data) {
  11678. if (self.tick == myTick) self.finishUpdate(data, first)
  11679. })
  11680. },
  11681. finishUpdate: function(data, first) {
  11682. if (this.data) CodeMirror.signal(this.data, "update");
  11683. var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
  11684. if (this.widget) this.widget.close();
  11685. this.data = data;
  11686. if (data && data.list.length) {
  11687. if (picked && data.list.length == 1) {
  11688. this.pick(data, 0);
  11689. } else {
  11690. this.widget = new Widget(this, data);
  11691. CodeMirror.signal(data, "shown");
  11692. }
  11693. }
  11694. }
  11695. };
  11696. function parseOptions(cm, pos, options) {
  11697. var editor = cm.options.hintOptions;
  11698. var out = {};
  11699. for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
  11700. if (editor) for (var prop in editor)
  11701. if (editor[prop] !== undefined) out[prop] = editor[prop];
  11702. if (options) for (var prop in options)
  11703. if (options[prop] !== undefined) out[prop] = options[prop];
  11704. if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
  11705. return out;
  11706. }
  11707. function getText(completion) {
  11708. if (typeof completion == "string") return completion;
  11709. else return completion.text;
  11710. }
  11711. function buildKeyMap(completion, handle) {
  11712. var baseMap = {
  11713. Up: function() {handle.moveFocus(-1);},
  11714. Down: function() {handle.moveFocus(1);},
  11715. PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
  11716. PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
  11717. Home: function() {handle.setFocus(0);},
  11718. End: function() {handle.setFocus(handle.length - 1);},
  11719. Enter: handle.pick,
  11720. Tab: handle.pick,
  11721. Esc: handle.close
  11722. };
  11723. var mac = /Mac/.test(navigator.platform);
  11724. if (mac) {
  11725. baseMap["Ctrl-P"] = function() {handle.moveFocus(-1);};
  11726. baseMap["Ctrl-N"] = function() {handle.moveFocus(1);};
  11727. }
  11728. var custom = completion.options.customKeys;
  11729. var ourMap = custom ? {} : baseMap;
  11730. function addBinding(key, val) {
  11731. var bound;
  11732. if (typeof val != "string")
  11733. bound = function(cm) { return val(cm, handle); };
  11734. // This mechanism is deprecated
  11735. else if (baseMap.hasOwnProperty(val))
  11736. bound = baseMap[val];
  11737. else
  11738. bound = val;
  11739. ourMap[key] = bound;
  11740. }
  11741. if (custom)
  11742. for (var key in custom) if (custom.hasOwnProperty(key))
  11743. addBinding(key, custom[key]);
  11744. var extra = completion.options.extraKeys;
  11745. if (extra)
  11746. for (var key in extra) if (extra.hasOwnProperty(key))
  11747. addBinding(key, extra[key]);
  11748. return ourMap;
  11749. }
  11750. function getHintElement(hintsElement, el) {
  11751. while (el && el != hintsElement) {
  11752. if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
  11753. el = el.parentNode;
  11754. }
  11755. }
  11756. function Widget(completion, data) {
  11757. this.completion = completion;
  11758. this.data = data;
  11759. this.picked = false;
  11760. var widget = this, cm = completion.cm;
  11761. var ownerDocument = cm.getInputField().ownerDocument;
  11762. var parentWindow = ownerDocument.defaultView || ownerDocument.parentWindow;
  11763. var hints = this.hints = ownerDocument.createElement("ul");
  11764. var theme = completion.cm.options.theme;
  11765. hints.className = "CodeMirror-hints " + theme;
  11766. this.selectedHint = data.selectedHint || 0;
  11767. var completions = data.list;
  11768. for (var i = 0; i < completions.length; ++i) {
  11769. var elt = hints.appendChild(ownerDocument.createElement("li")), cur = completions[i];
  11770. var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
  11771. if (cur.className != null) className = cur.className + " " + className;
  11772. elt.className = className;
  11773. if (cur.render) cur.render(elt, data, cur);
  11774. else elt.appendChild(ownerDocument.createTextNode(cur.displayText || getText(cur)));
  11775. elt.hintId = i;
  11776. }
  11777. var container = completion.options.container || ownerDocument.body;
  11778. var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
  11779. var left = pos.left, top = pos.bottom, below = true;
  11780. var offsetLeft = 0, offsetTop = 0;
  11781. if (container !== ownerDocument.body) {
  11782. // We offset the cursor position because left and top are relative to the offsetParent's top left corner.
  11783. var isContainerPositioned = ['absolute', 'relative', 'fixed'].indexOf(parentWindow.getComputedStyle(container).position) !== -1;
  11784. var offsetParent = isContainerPositioned ? container : container.offsetParent;
  11785. var offsetParentPosition = offsetParent.getBoundingClientRect();
  11786. var bodyPosition = ownerDocument.body.getBoundingClientRect();
  11787. offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft);
  11788. offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop);
  11789. }
  11790. hints.style.left = (left - offsetLeft) + "px";
  11791. hints.style.top = (top - offsetTop) + "px";
  11792. // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
  11793. var winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth);
  11794. var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight);
  11795. container.appendChild(hints);
  11796. var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
  11797. var scrolls = hints.scrollHeight > hints.clientHeight + 1
  11798. var startScroll = cm.getScrollInfo();
  11799. if (overlapY > 0) {
  11800. var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
  11801. if (curTop - height > 0) { // Fits above cursor
  11802. hints.style.top = (top = pos.top - height - offsetTop) + "px";
  11803. below = false;
  11804. } else if (height > winH) {
  11805. hints.style.height = (winH - 5) + "px";
  11806. hints.style.top = (top = pos.bottom - box.top - offsetTop) + "px";
  11807. var cursor = cm.getCursor();
  11808. if (data.from.ch != cursor.ch) {
  11809. pos = cm.cursorCoords(cursor);
  11810. hints.style.left = (left = pos.left - offsetLeft) + "px";
  11811. box = hints.getBoundingClientRect();
  11812. }
  11813. }
  11814. }
  11815. var overlapX = box.right - winW;
  11816. if (overlapX > 0) {
  11817. if (box.right - box.left > winW) {
  11818. hints.style.width = (winW - 5) + "px";
  11819. overlapX -= (box.right - box.left) - winW;
  11820. }
  11821. hints.style.left = (left = pos.left - overlapX - offsetLeft) + "px";
  11822. }
  11823. if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling)
  11824. node.style.paddingRight = cm.display.nativeBarWidth + "px"
  11825. cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
  11826. moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
  11827. setFocus: function(n) { widget.changeActive(n); },
  11828. menuSize: function() { return widget.screenAmount(); },
  11829. length: completions.length,
  11830. close: function() { completion.close(); },
  11831. pick: function() { widget.pick(); },
  11832. data: data
  11833. }));
  11834. if (completion.options.closeOnUnfocus) {
  11835. var closingOnBlur;
  11836. cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
  11837. cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
  11838. }
  11839. cm.on("scroll", this.onScroll = function() {
  11840. var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
  11841. var newTop = top + startScroll.top - curScroll.top;
  11842. var point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop);
  11843. if (!below) point += hints.offsetHeight;
  11844. if (point <= editor.top || point >= editor.bottom) return completion.close();
  11845. hints.style.top = newTop + "px";
  11846. hints.style.left = (left + startScroll.left - curScroll.left) + "px";
  11847. });
  11848. CodeMirror.on(hints, "dblclick", function(e) {
  11849. var t = getHintElement(hints, e.target || e.srcElement);
  11850. if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
  11851. });
  11852. CodeMirror.on(hints, "click", function(e) {
  11853. var t = getHintElement(hints, e.target || e.srcElement);
  11854. if (t && t.hintId != null) {
  11855. widget.changeActive(t.hintId);
  11856. if (completion.options.completeOnSingleClick) widget.pick();
  11857. }
  11858. });
  11859. CodeMirror.on(hints, "mousedown", function() {
  11860. setTimeout(function(){cm.focus();}, 20);
  11861. });
  11862. this.scrollToActive()
  11863. CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]);
  11864. return true;
  11865. }
  11866. Widget.prototype = {
  11867. close: function() {
  11868. if (this.completion.widget != this) return;
  11869. this.completion.widget = null;
  11870. this.hints.parentNode.removeChild(this.hints);
  11871. this.completion.cm.removeKeyMap(this.keyMap);
  11872. var cm = this.completion.cm;
  11873. if (this.completion.options.closeOnUnfocus) {
  11874. cm.off("blur", this.onBlur);
  11875. cm.off("focus", this.onFocus);
  11876. }
  11877. cm.off("scroll", this.onScroll);
  11878. },
  11879. disable: function() {
  11880. this.completion.cm.removeKeyMap(this.keyMap);
  11881. var widget = this;
  11882. this.keyMap = {Enter: function() { widget.picked = true; }};
  11883. this.completion.cm.addKeyMap(this.keyMap);
  11884. },
  11885. pick: function() {
  11886. this.completion.pick(this.data, this.selectedHint);
  11887. },
  11888. changeActive: function(i, avoidWrap) {
  11889. if (i >= this.data.list.length)
  11890. i = avoidWrap ? this.data.list.length - 1 : 0;
  11891. else if (i < 0)
  11892. i = avoidWrap ? 0 : this.data.list.length - 1;
  11893. if (this.selectedHint == i) return;
  11894. var node = this.hints.childNodes[this.selectedHint];
  11895. if (node) node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
  11896. node = this.hints.childNodes[this.selectedHint = i];
  11897. node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
  11898. this.scrollToActive()
  11899. CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
  11900. },
  11901. scrollToActive: function() {
  11902. var margin = this.completion.options.scrollMargin || 0;
  11903. var node1 = this.hints.childNodes[Math.max(0, this.selectedHint - margin)];
  11904. var node2 = this.hints.childNodes[Math.min(this.data.list.length - 1, this.selectedHint + margin)];
  11905. var firstNode = this.hints.firstChild;
  11906. if (node1.offsetTop < this.hints.scrollTop)
  11907. this.hints.scrollTop = node1.offsetTop - firstNode.offsetTop;
  11908. else if (node2.offsetTop + node2.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
  11909. this.hints.scrollTop = node2.offsetTop + node2.offsetHeight - this.hints.clientHeight + firstNode.offsetTop;
  11910. },
  11911. screenAmount: function() {
  11912. return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
  11913. }
  11914. };
  11915. function applicableHelpers(cm, helpers) {
  11916. if (!cm.somethingSelected()) return helpers
  11917. var result = []
  11918. for (var i = 0; i < helpers.length; i++)
  11919. if (helpers[i].supportsSelection) result.push(helpers[i])
  11920. return result
  11921. }
  11922. function fetchHints(hint, cm, options, callback) {
  11923. if (hint.async) {
  11924. hint(cm, callback, options)
  11925. } else {
  11926. var result = hint(cm, options)
  11927. if (result && result.then) result.then(callback)
  11928. else callback(result)
  11929. }
  11930. }
  11931. function resolveAutoHints(cm, pos) {
  11932. var helpers = cm.getHelpers(pos, "hint"), words
  11933. if (helpers.length) {
  11934. var resolved = function(cm, callback, options) {
  11935. var app = applicableHelpers(cm, helpers);
  11936. function run(i) {
  11937. if (i == app.length) return callback(null)
  11938. fetchHints(app[i], cm, options, function(result) {
  11939. if (result && result.list.length > 0) callback(result)
  11940. else run(i + 1)
  11941. })
  11942. }
  11943. run(0)
  11944. }
  11945. resolved.async = true
  11946. resolved.supportsSelection = true
  11947. return resolved
  11948. } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
  11949. return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }
  11950. } else if (CodeMirror.hint.anyword) {
  11951. return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
  11952. } else {
  11953. return function() {}
  11954. }
  11955. }
  11956. CodeMirror.registerHelper("hint", "auto", {
  11957. resolve: resolveAutoHints
  11958. });
  11959. CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
  11960. var cur = cm.getCursor(), token = cm.getTokenAt(cur)
  11961. var term, from = CodeMirror.Pos(cur.line, token.start), to = cur
  11962. if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
  11963. term = token.string.substr(0, cur.ch - token.start)
  11964. } else {
  11965. term = ""
  11966. from = cur
  11967. }
  11968. var found = [];
  11969. for (var i = 0; i < options.words.length; i++) {
  11970. var word = options.words[i];
  11971. if (word.slice(0, term.length) == term)
  11972. found.push(word);
  11973. }
  11974. if (found.length) return {list: found, from: from, to: to};
  11975. });
  11976. CodeMirror.commands.autocomplete = CodeMirror.showHint;
  11977. var defaultOptions = {
  11978. hint: CodeMirror.hint.auto,
  11979. completeSingle: true,
  11980. alignWithWord: true,
  11981. closeCharacters: /[\s()\[\]{};:>,]/,
  11982. closeOnUnfocus: true,
  11983. completeOnSingleClick: true,
  11984. container: null,
  11985. customKeys: null,
  11986. extraKeys: null
  11987. };
  11988. CodeMirror.defineOption("hintOptions", null);
  11989. });
  11990. /* ---- extension/hint/sql-hint.js ---- */
  11991. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  11992. // Distributed under an MIT license: https://codemirror.net/LICENSE
  11993. (function(mod) {
  11994. if (typeof exports == "object" && typeof module == "object") // CommonJS
  11995. mod(require("../../lib/codemirror"), require("../../mode/sql/sql"));
  11996. else if (typeof define == "function" && define.amd) // AMD
  11997. define(["../../lib/codemirror", "../../mode/sql/sql"], mod);
  11998. else // Plain browser env
  11999. mod(CodeMirror);
  12000. })(function(CodeMirror) {
  12001. "use strict";
  12002. var tables;
  12003. var defaultTable;
  12004. var keywords;
  12005. var identifierQuote;
  12006. var CONS = {
  12007. QUERY_DIV: ";",
  12008. ALIAS_KEYWORD: "AS"
  12009. };
  12010. var Pos = CodeMirror.Pos, cmpPos = CodeMirror.cmpPos;
  12011. function isArray(val) { return Object.prototype.toString.call(val) == "[object Array]" }
  12012. function getKeywords(editor) {
  12013. var mode = editor.doc.modeOption;
  12014. if (mode === "sql") mode = "text/x-sql";
  12015. return CodeMirror.resolveMode(mode).keywords;
  12016. }
  12017. function getIdentifierQuote(editor) {
  12018. var mode = editor.doc.modeOption;
  12019. if (mode === "sql") mode = "text/x-sql";
  12020. return CodeMirror.resolveMode(mode).identifierQuote || "`";
  12021. }
  12022. function getText(item) {
  12023. return typeof item == "string" ? item : item.text;
  12024. }
  12025. function wrapTable(name, value) {
  12026. if (isArray(value)) value = {columns: value}
  12027. if (!value.text) value.text = name
  12028. return value
  12029. }
  12030. function parseTables(input) {
  12031. var result = {}
  12032. if (isArray(input)) {
  12033. for (var i = input.length - 1; i >= 0; i--) {
  12034. var item = input[i]
  12035. result[getText(item).toUpperCase()] = wrapTable(getText(item), item)
  12036. }
  12037. } else if (input) {
  12038. for (var name in input)
  12039. result[name.toUpperCase()] = wrapTable(name, input[name])
  12040. }
  12041. return result
  12042. }
  12043. function getTable(name) {
  12044. return tables[name.toUpperCase()]
  12045. }
  12046. function shallowClone(object) {
  12047. var result = {};
  12048. for (var key in object) if (object.hasOwnProperty(key))
  12049. result[key] = object[key];
  12050. return result;
  12051. }
  12052. function match(string, word) {
  12053. var len = string.length;
  12054. var sub = getText(word).substr(0, len);
  12055. return string.toUpperCase() === sub.toUpperCase();
  12056. }
  12057. function addMatches(result, search, wordlist, formatter) {
  12058. if (isArray(wordlist)) {
  12059. for (var i = 0; i < wordlist.length; i++)
  12060. if (match(search, wordlist[i])) result.push(formatter(wordlist[i]))
  12061. } else {
  12062. for (var word in wordlist) if (wordlist.hasOwnProperty(word)) {
  12063. var val = wordlist[word]
  12064. if (!val || val === true)
  12065. val = word
  12066. else
  12067. val = val.displayText ? {text: val.text, displayText: val.displayText} : val.text
  12068. if (match(search, val)) result.push(formatter(val))
  12069. }
  12070. }
  12071. }
  12072. function cleanName(name) {
  12073. // Get rid name from identifierQuote and preceding dot(.)
  12074. if (name.charAt(0) == ".") {
  12075. name = name.substr(1);
  12076. }
  12077. // replace doublicated identifierQuotes with single identifierQuotes
  12078. // and remove single identifierQuotes
  12079. var nameParts = name.split(identifierQuote+identifierQuote);
  12080. for (var i = 0; i < nameParts.length; i++)
  12081. nameParts[i] = nameParts[i].replace(new RegExp(identifierQuote,"g"), "");
  12082. return nameParts.join(identifierQuote);
  12083. }
  12084. function insertIdentifierQuotes(name) {
  12085. var nameParts = getText(name).split(".");
  12086. for (var i = 0; i < nameParts.length; i++)
  12087. nameParts[i] = identifierQuote +
  12088. // doublicate identifierQuotes
  12089. nameParts[i].replace(new RegExp(identifierQuote,"g"), identifierQuote+identifierQuote) +
  12090. identifierQuote;
  12091. var escaped = nameParts.join(".");
  12092. if (typeof name == "string") return escaped;
  12093. name = shallowClone(name);
  12094. name.text = escaped;
  12095. return name;
  12096. }
  12097. function nameCompletion(cur, token, result, editor) {
  12098. // Try to complete table, column names and return start position of completion
  12099. var useIdentifierQuotes = false;
  12100. var nameParts = [];
  12101. var start = token.start;
  12102. var cont = true;
  12103. while (cont) {
  12104. cont = (token.string.charAt(0) == ".");
  12105. useIdentifierQuotes = useIdentifierQuotes || (token.string.charAt(0) == identifierQuote);
  12106. start = token.start;
  12107. nameParts.unshift(cleanName(token.string));
  12108. token = editor.getTokenAt(Pos(cur.line, token.start));
  12109. if (token.string == ".") {
  12110. cont = true;
  12111. token = editor.getTokenAt(Pos(cur.line, token.start));
  12112. }
  12113. }
  12114. // Try to complete table names
  12115. var string = nameParts.join(".");
  12116. addMatches(result, string, tables, function(w) {
  12117. return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
  12118. });
  12119. // Try to complete columns from defaultTable
  12120. addMatches(result, string, defaultTable, function(w) {
  12121. return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
  12122. });
  12123. // Try to complete columns
  12124. string = nameParts.pop();
  12125. var table = nameParts.join(".");
  12126. var alias = false;
  12127. var aliasTable = table;
  12128. // Check if table is available. If not, find table by Alias
  12129. if (!getTable(table)) {
  12130. var oldTable = table;
  12131. table = findTableByAlias(table, editor);
  12132. if (table !== oldTable) alias = true;
  12133. }
  12134. var columns = getTable(table);
  12135. if (columns && columns.columns)
  12136. columns = columns.columns;
  12137. if (columns) {
  12138. addMatches(result, string, columns, function(w) {
  12139. var tableInsert = table;
  12140. if (alias == true) tableInsert = aliasTable;
  12141. if (typeof w == "string") {
  12142. w = tableInsert + "." + w;
  12143. } else {
  12144. w = shallowClone(w);
  12145. w.text = tableInsert + "." + w.text;
  12146. }
  12147. return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
  12148. });
  12149. }
  12150. return start;
  12151. }
  12152. function eachWord(lineText, f) {
  12153. var words = lineText.split(/\s+/)
  12154. for (var i = 0; i < words.length; i++)
  12155. if (words[i]) f(words[i].replace(/[,;]/g, ''))
  12156. }
  12157. function findTableByAlias(alias, editor) {
  12158. var doc = editor.doc;
  12159. var fullQuery = doc.getValue();
  12160. var aliasUpperCase = alias.toUpperCase();
  12161. var previousWord = "";
  12162. var table = "";
  12163. var separator = [];
  12164. var validRange = {
  12165. start: Pos(0, 0),
  12166. end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)
  12167. };
  12168. //add separator
  12169. var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);
  12170. while(indexOfSeparator != -1) {
  12171. separator.push(doc.posFromIndex(indexOfSeparator));
  12172. indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1);
  12173. }
  12174. separator.unshift(Pos(0, 0));
  12175. separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
  12176. //find valid range
  12177. var prevItem = null;
  12178. var current = editor.getCursor()
  12179. for (var i = 0; i < separator.length; i++) {
  12180. if ((prevItem == null || cmpPos(current, prevItem) > 0) && cmpPos(current, separator[i]) <= 0) {
  12181. validRange = {start: prevItem, end: separator[i]};
  12182. break;
  12183. }
  12184. prevItem = separator[i];
  12185. }
  12186. if (validRange.start) {
  12187. var query = doc.getRange(validRange.start, validRange.end, false);
  12188. for (var i = 0; i < query.length; i++) {
  12189. var lineText = query[i];
  12190. eachWord(lineText, function(word) {
  12191. var wordUpperCase = word.toUpperCase();
  12192. if (wordUpperCase === aliasUpperCase && getTable(previousWord))
  12193. table = previousWord;
  12194. if (wordUpperCase !== CONS.ALIAS_KEYWORD)
  12195. previousWord = word;
  12196. });
  12197. if (table) break;
  12198. }
  12199. }
  12200. return table;
  12201. }
  12202. CodeMirror.registerHelper("hint", "sql", function(editor, options) {
  12203. tables = parseTables(options && options.tables)
  12204. var defaultTableName = options && options.defaultTable;
  12205. var disableKeywords = options && options.disableKeywords;
  12206. defaultTable = defaultTableName && getTable(defaultTableName);
  12207. keywords = getKeywords(editor);
  12208. identifierQuote = getIdentifierQuote(editor);
  12209. if (defaultTableName && !defaultTable)
  12210. defaultTable = findTableByAlias(defaultTableName, editor);
  12211. defaultTable = defaultTable || [];
  12212. if (defaultTable.columns)
  12213. defaultTable = defaultTable.columns;
  12214. var cur = editor.getCursor();
  12215. var result = [];
  12216. var token = editor.getTokenAt(cur), start, end, search;
  12217. if (token.end > cur.ch) {
  12218. token.end = cur.ch;
  12219. token.string = token.string.slice(0, cur.ch - token.start);
  12220. }
  12221. if (token.string.match(/^[.`"'\w@][\w$#]*$/g)) {
  12222. search = token.string;
  12223. start = token.start;
  12224. end = token.end;
  12225. } else {
  12226. start = end = cur.ch;
  12227. search = "";
  12228. }
  12229. if (search.charAt(0) == "." || search.charAt(0) == identifierQuote) {
  12230. start = nameCompletion(cur, token, result, editor);
  12231. } else {
  12232. var objectOrClass = function(w, className) {
  12233. if (typeof w === "object") {
  12234. w.className = className;
  12235. } else {
  12236. w = { text: w, className: className };
  12237. }
  12238. return w;
  12239. };
  12240. addMatches(result, search, defaultTable, function(w) {
  12241. return objectOrClass(w, "CodeMirror-hint-table CodeMirror-hint-default-table");
  12242. });
  12243. addMatches(
  12244. result,
  12245. search,
  12246. tables, function(w) {
  12247. return objectOrClass(w, "CodeMirror-hint-table");
  12248. }
  12249. );
  12250. if (!disableKeywords)
  12251. addMatches(result, search, keywords, function(w) {
  12252. return objectOrClass(w.toUpperCase(), "CodeMirror-hint-keyword");
  12253. });
  12254. }
  12255. return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
  12256. });
  12257. });
  12258. /* ---- extension/hint/xml-hint.js ---- */
  12259. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  12260. // Distributed under an MIT license: https://codemirror.net/LICENSE
  12261. (function(mod) {
  12262. if (typeof exports == "object" && typeof module == "object") // CommonJS
  12263. mod(require("../../lib/codemirror"));
  12264. else if (typeof define == "function" && define.amd) // AMD
  12265. define(["../../lib/codemirror"], mod);
  12266. else // Plain browser env
  12267. mod(CodeMirror);
  12268. })(function(CodeMirror) {
  12269. "use strict";
  12270. var Pos = CodeMirror.Pos;
  12271. function matches(hint, typed, matchInMiddle) {
  12272. if (matchInMiddle) return hint.indexOf(typed) >= 0;
  12273. else return hint.lastIndexOf(typed, 0) == 0;
  12274. }
  12275. function getHints(cm, options) {
  12276. var tags = options && options.schemaInfo;
  12277. var quote = (options && options.quoteChar) || '"';
  12278. var matchInMiddle = options && options.matchInMiddle;
  12279. if (!tags) return;
  12280. var cur = cm.getCursor(), token = cm.getTokenAt(cur);
  12281. if (token.end > cur.ch) {
  12282. token.end = cur.ch;
  12283. token.string = token.string.slice(0, cur.ch - token.start);
  12284. }
  12285. var inner = CodeMirror.innerMode(cm.getMode(), token.state);
  12286. if (!inner.mode.xmlCurrentTag) return
  12287. var result = [], replaceToken = false, prefix;
  12288. var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
  12289. var tagName = tag && /^\w/.test(token.string), tagStart;
  12290. if (tagName) {
  12291. var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start);
  12292. var tagType = /<\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null;
  12293. if (tagType) tagStart = token.start - (tagType == "close" ? 2 : 1);
  12294. } else if (tag && token.string == "<") {
  12295. tagType = "open";
  12296. } else if (tag && token.string == "</") {
  12297. tagType = "close";
  12298. }
  12299. var tagInfo = inner.mode.xmlCurrentTag(inner.state)
  12300. if (!tag && !tagInfo || tagType) {
  12301. if (tagName)
  12302. prefix = token.string;
  12303. replaceToken = tagType;
  12304. var context = inner.mode.xmlCurrentContext ? inner.mode.xmlCurrentContext(inner.state) : []
  12305. var inner = context.length && context[context.length - 1]
  12306. var curTag = inner && tags[inner]
  12307. var childList = inner ? curTag && curTag.children : tags["!top"];
  12308. if (childList && tagType != "close") {
  12309. for (var i = 0; i < childList.length; ++i) if (!prefix || matches(childList[i], prefix, matchInMiddle))
  12310. result.push("<" + childList[i]);
  12311. } else if (tagType != "close") {
  12312. for (var name in tags)
  12313. if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || matches(name, prefix, matchInMiddle)))
  12314. result.push("<" + name);
  12315. }
  12316. if (inner && (!prefix || tagType == "close" && matches(inner, prefix, matchInMiddle)))
  12317. result.push("</" + inner + ">");
  12318. } else {
  12319. // Attribute completion
  12320. var curTag = tagInfo && tags[tagInfo.name], attrs = curTag && curTag.attrs;
  12321. var globalAttrs = tags["!attrs"];
  12322. if (!attrs && !globalAttrs) return;
  12323. if (!attrs) {
  12324. attrs = globalAttrs;
  12325. } else if (globalAttrs) { // Combine tag-local and global attributes
  12326. var set = {};
  12327. for (var nm in globalAttrs) if (globalAttrs.hasOwnProperty(nm)) set[nm] = globalAttrs[nm];
  12328. for (var nm in attrs) if (attrs.hasOwnProperty(nm)) set[nm] = attrs[nm];
  12329. attrs = set;
  12330. }
  12331. if (token.type == "string" || token.string == "=") { // A value
  12332. var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)),
  12333. Pos(cur.line, token.type == "string" ? token.start : token.end));
  12334. var atName = before.match(/([^\s\u00a0=<>\"\']+)=$/), atValues;
  12335. if (!atName || !attrs.hasOwnProperty(atName[1]) || !(atValues = attrs[atName[1]])) return;
  12336. if (typeof atValues == 'function') atValues = atValues.call(this, cm); // Functions can be used to supply values for autocomplete widget
  12337. if (token.type == "string") {
  12338. prefix = token.string;
  12339. var n = 0;
  12340. if (/['"]/.test(token.string.charAt(0))) {
  12341. quote = token.string.charAt(0);
  12342. prefix = token.string.slice(1);
  12343. n++;
  12344. }
  12345. var len = token.string.length;
  12346. if (/['"]/.test(token.string.charAt(len - 1))) {
  12347. quote = token.string.charAt(len - 1);
  12348. prefix = token.string.substr(n, len - 2);
  12349. }
  12350. if (n) { // an opening quote
  12351. var line = cm.getLine(cur.line);
  12352. if (line.length > token.end && line.charAt(token.end) == quote) token.end++; // include a closing quote
  12353. }
  12354. replaceToken = true;
  12355. }
  12356. for (var i = 0; i < atValues.length; ++i) if (!prefix || matches(atValues[i], prefix, matchInMiddle))
  12357. result.push(quote + atValues[i] + quote);
  12358. } else { // An attribute name
  12359. if (token.type == "attribute") {
  12360. prefix = token.string;
  12361. replaceToken = true;
  12362. }
  12363. for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || matches(attr, prefix, matchInMiddle)))
  12364. result.push(attr);
  12365. }
  12366. }
  12367. return {
  12368. list: result,
  12369. from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
  12370. to: replaceToken ? Pos(cur.line, token.end) : cur
  12371. };
  12372. }
  12373. CodeMirror.registerHelper("hint", "xml", getHints);
  12374. });
  12375. /* ---- extension/lint/json-lint.js ---- */
  12376. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  12377. // Distributed under an MIT license: https://codemirror.net/LICENSE
  12378. // Depends on jsonlint.js from https://github.com/zaach/jsonlint
  12379. // declare global: jsonlint
  12380. (function(mod) {
  12381. if (typeof exports == "object" && typeof module == "object") // CommonJS
  12382. mod(require("../../lib/codemirror"));
  12383. else if (typeof define == "function" && define.amd) // AMD
  12384. define(["../../lib/codemirror"], mod);
  12385. else // Plain browser env
  12386. mod(CodeMirror);
  12387. })(function(CodeMirror) {
  12388. "use strict";
  12389. CodeMirror.registerHelper("lint", "json", function(text) {
  12390. var found = [];
  12391. if (!window.jsonlint) {
  12392. if (window.console) {
  12393. window.console.error("Error: window.jsonlint not defined, CodeMirror JSON linting cannot run.");
  12394. }
  12395. return found;
  12396. }
  12397. // for jsonlint's web dist jsonlint is exported as an object with a single property parser, of which parseError
  12398. // is a subproperty
  12399. var jsonlint = window.jsonlint.parser || window.jsonlint
  12400. jsonlint.parseError = function(str, hash) {
  12401. var loc = hash.loc;
  12402. found.push({from: CodeMirror.Pos(loc.first_line - 1, loc.first_column),
  12403. to: CodeMirror.Pos(loc.last_line - 1, loc.last_column),
  12404. message: str});
  12405. };
  12406. try { jsonlint.parse(text); }
  12407. catch(e) {}
  12408. return found;
  12409. });
  12410. });
  12411. /* ---- extension/lint/jsonlint.js ---- */
  12412. var jsonlint=function(){var a=!0,b=!1,c={},d=function(){var a={trace:function(){},yy:{},symbols_:{error:2,JSONString:3,STRING:4,JSONNumber:5,NUMBER:6,JSONNullLiteral:7,NULL:8,JSONBooleanLiteral:9,TRUE:10,FALSE:11,JSONText:12,JSONValue:13,EOF:14,JSONObject:15,JSONArray:16,"{":17,"}":18,JSONMemberList:19,JSONMember:20,":":21,",":22,"[":23,"]":24,JSONElementList:25,$accept:0,$end:1},terminals_:{2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"},productions_:[0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]],performAction:function(b,c,d,e,f,g,h){var i=g.length-1;switch(f){case 1:this.$=b.replace(/\\(\\|")/g,"$1").replace(/\\n/g,"\n").replace(/\\r/g,"\r").replace(/\\t/g," ").replace(/\\v/g," ").replace(/\\f/g,"\f").replace(/\\b/g,"\b");break;case 2:this.$=Number(b);break;case 3:this.$=null;break;case 4:this.$=!0;break;case 5:this.$=!1;break;case 6:return this.$=g[i-1];case 13:this.$={};break;case 14:this.$=g[i-1];break;case 15:this.$=[g[i-2],g[i]];break;case 16:this.$={},this.$[g[i][0]]=g[i][1];break;case 17:this.$=g[i-2],g[i-2][g[i][0]]=g[i][1];break;case 18:this.$=[];break;case 19:this.$=g[i-1];break;case 20:this.$=[g[i]];break;case 21:this.$=g[i-2],g[i-2].push(g[i])}},table:[{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}],defaultActions:{16:[2,6]},parseError:function(b,c){throw new Error(b)},parse:function(b){function o(a){d.length=d.length-2*a,e.length=e.length-a,f.length=f.length-a}function p(){var a;return a=c.lexer.lex()||1,typeof a!="number"&&(a=c.symbols_[a]||a),a}var c=this,d=[0],e=[null],f=[],g=this.table,h="",i=0,j=0,k=0,l=2,m=1;this.lexer.setInput(b),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,typeof this.lexer.yylloc=="undefined"&&(this.lexer.yylloc={});var n=this.lexer.yylloc;f.push(n),typeof this.yy.parseError=="function"&&(this.parseError=this.yy.parseError);var q,r,s,t,u,v,w={},x,y,z,A;for(;;){s=d[d.length-1],this.defaultActions[s]?t=this.defaultActions[s]:(q==null&&(q=p()),t=g[s]&&g[s][q]);if(typeof t=="undefined"||!t.length||!t[0]){if(!k){A=[];for(x in g[s])this.terminals_[x]&&x>2&&A.push("'"+this.terminals_[x]+"'");var B="";this.lexer.showPosition?B="Parse error on line "+(i+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+A.join(", ")+", got '"+this.terminals_[q]+"'":B="Parse error on line "+(i+1)+": Unexpected "+(q==1?"end of input":"'"+(this.terminals_[q]||q)+"'"),this.parseError(B,{text:this.lexer.match,token:this.terminals_[q]||q,line:this.lexer.yylineno,loc:n,expected:A})}if(k==3){if(q==m)throw new Error(B||"Parsing halted.");j=this.lexer.yyleng,h=this.lexer.yytext,i=this.lexer.yylineno,n=this.lexer.yylloc,q=p()}for(;;){if(l.toString()in g[s])break;if(s==0)throw new Error(B||"Parsing halted.");o(1),s=d[d.length-1]}r=q,q=l,s=d[d.length-1],t=g[s]&&g[s][l],k=3}if(t[0]instanceof Array&&t.length>1)throw new Error("Parse Error: multiple actions possible at state: "+s+", token: "+q);switch(t[0]){case 1:d.push(q),e.push(this.lexer.yytext),f.push(this.lexer.yylloc),d.push(t[1]),q=null,r?(q=r,r=null):(j=this.lexer.yyleng,h=this.lexer.yytext,i=this.lexer.yylineno,n=this.lexer.yylloc,k>0&&k--);break;case 2:y=this.productions_[t[1]][1],w.$=e[e.length-y],w._$={first_line:f[f.length-(y||1)].first_line,last_line:f[f.length-1].last_line,first_column:f[f.length-(y||1)].first_column,last_column:f[f.length-1].last_column},v=this.performAction.call(w,h,j,i,this.yy,t[1],e,f);if(typeof v!="undefined")return v;y&&(d=d.slice(0,-1*y*2),e=e.slice(0,-1*y),f=f.slice(0,-1*y)),d.push(this.productions_[t[1]][0]),e.push(w.$),f.push(w._$),z=g[d[d.length-2]][d[d.length-1]],d.push(z);break;case 3:return!0}}return!0}},b=function(){var a={EOF:1,parseError:function(b,c){if(!this.yy.parseError)throw new Error(b);this.yy.parseError(b,c)},setInput:function(a){return this._input=a,this._more=this._less=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this},input:function(){var a=this._input[0];this.yytext+=a,this.yyleng++,this.match+=a,this.matched+=a;var b=a.match(/\n/);return b&&this.yylineno++,this._input=this._input.slice(1),a},unput:function(a){return this._input=a+this._input,this},more:function(){return this._more=!0,this},less:function(a){this._input=this.match.slice(a)+this._input},pastInput:function(){var a=this.matched.substr(0,this.matched.length-this.match.length);return(a.length>20?"...":"")+a.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var a=this.match;return a.length<20&&(a+=this._input.substr(0,20-a.length)),(a.substr(0,20)+(a.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var a=this.pastInput(),b=(new Array(a.length+1)).join("-");return a+this.upcomingInput()+"\n"+b+"^"},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var a,b,c,d,e,f;this._more||(this.yytext="",this.match="");var g=this._currentRules();for(var h=0;h<g.length;h++){c=this._input.match(this.rules[g[h]]);if(c&&(!b||c[0].length>b[0].length)){b=c,d=h;if(!this.options.flex)break}}if(b){f=b[0].match(/\n.*/g),f&&(this.yylineno+=f.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:f?f[f.length-1].length-1:this.yylloc.last_column+b[0].length},this.yytext+=b[0],this.match+=b[0],this.yyleng=this.yytext.length,this._more=!1,this._input=this._input.slice(b[0].length),this.matched+=b[0],a=this.performAction.call(this,this.yy,this,g[d],this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1);if(a)return a;return}if(this._input==="")return this.EOF;this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var b=this.next();return typeof b!="undefined"?b:this.lex()},begin:function(b){this.conditionStack.push(b)},popState:function(){return this.conditionStack.pop()},_currentRules:function(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function(b){this.begin(b)}};return a.options={},a.performAction=function(b,c,d,e){var f=e;switch(d){case 0:break;case 1:return 6;case 2:return c.yytext=c.yytext.substr(1,c.yyleng-2),4;case 3:return 17;case 4:return 18;case 5:return 23;case 6:return 24;case 7:return 22;case 8:return 21;case 9:return 10;case 10:return 11;case 11:return 8;case 12:return 14;case 13:return"INVALID"}},a.rules=[/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/],a.conditions={INITIAL:{rules:[0,1,2,3,4,5,6,7,8,9,10,11,12,13],inclusive:!0}},a}();return a.lexer=b,a}();return typeof a!="undefined"&&typeof c!="undefined"&&(c.parser=d,c.parse=function(){return d.parse.apply(d,arguments)},c.main=function(d){if(!d[1])throw new Error("Usage: "+d[0]+" FILE");if(typeof process!="undefined")var e=a("fs").readFileSync(a("path").join(process.cwd(),d[1]),"utf8");else var f=a("file").path(a("file").cwd()),e=f.join(d[1]).read({charset:"utf-8"});return c.parser.parse(e)},typeof b!="undefined"&&a.main===b&&c.main(typeof process!="undefined"?process.argv.slice(1):a("system").args)),c}();
  12413. /* ---- extension/lint/lint.js ---- */
  12414. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  12415. // Distributed under an MIT license: https://codemirror.net/LICENSE
  12416. (function(mod) {
  12417. if (typeof exports == "object" && typeof module == "object") // CommonJS
  12418. mod(require("../../lib/codemirror"));
  12419. else if (typeof define == "function" && define.amd) // AMD
  12420. define(["../../lib/codemirror"], mod);
  12421. else // Plain browser env
  12422. mod(CodeMirror);
  12423. })(function(CodeMirror) {
  12424. "use strict";
  12425. var GUTTER_ID = "CodeMirror-lint-markers";
  12426. function showTooltip(cm, e, content) {
  12427. var tt = document.createElement("div");
  12428. tt.className = "CodeMirror-lint-tooltip cm-s-" + cm.options.theme;
  12429. tt.appendChild(content.cloneNode(true));
  12430. if (cm.state.lint.options.selfContain)
  12431. cm.getWrapperElement().appendChild(tt);
  12432. else
  12433. document.body.appendChild(tt);
  12434. function position(e) {
  12435. if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position);
  12436. tt.style.top = Math.max(0, e.clientY - tt.offsetHeight - 5) + "px";
  12437. tt.style.left = (e.clientX + 5) + "px";
  12438. }
  12439. CodeMirror.on(document, "mousemove", position);
  12440. position(e);
  12441. if (tt.style.opacity != null) tt.style.opacity = 1;
  12442. return tt;
  12443. }
  12444. function rm(elt) {
  12445. if (elt.parentNode) elt.parentNode.removeChild(elt);
  12446. }
  12447. function hideTooltip(tt) {
  12448. if (!tt.parentNode) return;
  12449. if (tt.style.opacity == null) rm(tt);
  12450. tt.style.opacity = 0;
  12451. setTimeout(function() { rm(tt); }, 600);
  12452. }
  12453. function showTooltipFor(cm, e, content, node) {
  12454. var tooltip = showTooltip(cm, e, content);
  12455. function hide() {
  12456. CodeMirror.off(node, "mouseout", hide);
  12457. if (tooltip) { hideTooltip(tooltip); tooltip = null; }
  12458. }
  12459. var poll = setInterval(function() {
  12460. if (tooltip) for (var n = node;; n = n.parentNode) {
  12461. if (n && n.nodeType == 11) n = n.host;
  12462. if (n == document.body) return;
  12463. if (!n) { hide(); break; }
  12464. }
  12465. if (!tooltip) return clearInterval(poll);
  12466. }, 400);
  12467. CodeMirror.on(node, "mouseout", hide);
  12468. }
  12469. function LintState(cm, options, hasGutter) {
  12470. this.marked = [];
  12471. this.options = options;
  12472. this.timeout = null;
  12473. this.hasGutter = hasGutter;
  12474. this.onMouseOver = function(e) { onMouseOver(cm, e); };
  12475. this.waitingFor = 0
  12476. }
  12477. function parseOptions(_cm, options) {
  12478. if (options instanceof Function) return {getAnnotations: options};
  12479. if (!options || options === true) options = {};
  12480. return options;
  12481. }
  12482. function clearMarks(cm) {
  12483. var state = cm.state.lint;
  12484. if (state.hasGutter) cm.clearGutter(GUTTER_ID);
  12485. for (var i = 0; i < state.marked.length; ++i)
  12486. state.marked[i].clear();
  12487. state.marked.length = 0;
  12488. }
  12489. function makeMarker(cm, labels, severity, multiple, tooltips) {
  12490. var marker = document.createElement("div"), inner = marker;
  12491. marker.className = "CodeMirror-lint-marker-" + severity;
  12492. if (multiple) {
  12493. inner = marker.appendChild(document.createElement("div"));
  12494. inner.className = "CodeMirror-lint-marker-multiple";
  12495. }
  12496. if (tooltips != false) CodeMirror.on(inner, "mouseover", function(e) {
  12497. showTooltipFor(cm, e, labels, inner);
  12498. });
  12499. return marker;
  12500. }
  12501. function getMaxSeverity(a, b) {
  12502. if (a == "error") return a;
  12503. else return b;
  12504. }
  12505. function groupByLine(annotations) {
  12506. var lines = [];
  12507. for (var i = 0; i < annotations.length; ++i) {
  12508. var ann = annotations[i], line = ann.from.line;
  12509. (lines[line] || (lines[line] = [])).push(ann);
  12510. }
  12511. return lines;
  12512. }
  12513. function annotationTooltip(ann) {
  12514. var severity = ann.severity;
  12515. if (!severity) severity = "error";
  12516. var tip = document.createElement("div");
  12517. tip.className = "CodeMirror-lint-message-" + severity;
  12518. if (typeof ann.messageHTML != 'undefined') {
  12519. tip.innerHTML = ann.messageHTML;
  12520. } else {
  12521. tip.appendChild(document.createTextNode(ann.message));
  12522. }
  12523. return tip;
  12524. }
  12525. function lintAsync(cm, getAnnotations, passOptions) {
  12526. var state = cm.state.lint
  12527. var id = ++state.waitingFor
  12528. function abort() {
  12529. id = -1
  12530. cm.off("change", abort)
  12531. }
  12532. cm.on("change", abort)
  12533. getAnnotations(cm.getValue(), function(annotations, arg2) {
  12534. cm.off("change", abort)
  12535. if (state.waitingFor != id) return
  12536. if (arg2 && annotations instanceof CodeMirror) annotations = arg2
  12537. cm.operation(function() {updateLinting(cm, annotations)})
  12538. }, passOptions, cm);
  12539. }
  12540. function startLinting(cm) {
  12541. var state = cm.state.lint, options = state.options;
  12542. /*
  12543. * Passing rules in `options` property prevents JSHint (and other linters) from complaining
  12544. * about unrecognized rules like `onUpdateLinting`, `delay`, `lintOnChange`, etc.
  12545. */
  12546. var passOptions = options.options || options;
  12547. var getAnnotations = options.getAnnotations || cm.getHelper(CodeMirror.Pos(0, 0), "lint");
  12548. if (!getAnnotations) return;
  12549. if (options.async || getAnnotations.async) {
  12550. lintAsync(cm, getAnnotations, passOptions)
  12551. } else {
  12552. var annotations = getAnnotations(cm.getValue(), passOptions, cm);
  12553. if (!annotations) return;
  12554. if (annotations.then) annotations.then(function(issues) {
  12555. cm.operation(function() {updateLinting(cm, issues)})
  12556. });
  12557. else cm.operation(function() {updateLinting(cm, annotations)})
  12558. }
  12559. }
  12560. function updateLinting(cm, annotationsNotSorted) {
  12561. clearMarks(cm);
  12562. var state = cm.state.lint, options = state.options;
  12563. var annotations = groupByLine(annotationsNotSorted);
  12564. for (var line = 0; line < annotations.length; ++line) {
  12565. var anns = annotations[line];
  12566. if (!anns) continue;
  12567. var maxSeverity = null;
  12568. var tipLabel = state.hasGutter && document.createDocumentFragment();
  12569. for (var i = 0; i < anns.length; ++i) {
  12570. var ann = anns[i];
  12571. var severity = ann.severity;
  12572. if (!severity) severity = "error";
  12573. maxSeverity = getMaxSeverity(maxSeverity, severity);
  12574. if (options.formatAnnotation) ann = options.formatAnnotation(ann);
  12575. if (state.hasGutter) tipLabel.appendChild(annotationTooltip(ann));
  12576. if (ann.to) state.marked.push(cm.markText(ann.from, ann.to, {
  12577. className: "CodeMirror-lint-mark-" + severity,
  12578. __annotation: ann
  12579. }));
  12580. }
  12581. if (state.hasGutter)
  12582. cm.setGutterMarker(line, GUTTER_ID, makeMarker(cm, tipLabel, maxSeverity, anns.length > 1,
  12583. state.options.tooltips));
  12584. }
  12585. if (options.onUpdateLinting) options.onUpdateLinting(annotationsNotSorted, annotations, cm);
  12586. }
  12587. function onChange(cm) {
  12588. var state = cm.state.lint;
  12589. if (!state) return;
  12590. clearTimeout(state.timeout);
  12591. state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);
  12592. }
  12593. function popupTooltips(cm, annotations, e) {
  12594. var target = e.target || e.srcElement;
  12595. var tooltip = document.createDocumentFragment();
  12596. for (var i = 0; i < annotations.length; i++) {
  12597. var ann = annotations[i];
  12598. tooltip.appendChild(annotationTooltip(ann));
  12599. }
  12600. showTooltipFor(cm, e, tooltip, target);
  12601. }
  12602. function onMouseOver(cm, e) {
  12603. var target = e.target || e.srcElement;
  12604. if (!/\bCodeMirror-lint-mark-/.test(target.className)) return;
  12605. var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2;
  12606. var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client"));
  12607. var annotations = [];
  12608. for (var i = 0; i < spans.length; ++i) {
  12609. var ann = spans[i].__annotation;
  12610. if (ann) annotations.push(ann);
  12611. }
  12612. if (annotations.length) popupTooltips(cm, annotations, e);
  12613. }
  12614. CodeMirror.defineOption("lint", false, function(cm, val, old) {
  12615. if (old && old != CodeMirror.Init) {
  12616. clearMarks(cm);
  12617. if (cm.state.lint.options.lintOnChange !== false)
  12618. cm.off("change", onChange);
  12619. CodeMirror.off(cm.getWrapperElement(), "mouseover", cm.state.lint.onMouseOver);
  12620. clearTimeout(cm.state.lint.timeout);
  12621. delete cm.state.lint;
  12622. }
  12623. if (val) {
  12624. var gutters = cm.getOption("gutters"), hasLintGutter = false;
  12625. for (var i = 0; i < gutters.length; ++i) if (gutters[i] == GUTTER_ID) hasLintGutter = true;
  12626. var state = cm.state.lint = new LintState(cm, parseOptions(cm, val), hasLintGutter);
  12627. if (state.options.lintOnChange !== false)
  12628. cm.on("change", onChange);
  12629. if (state.options.tooltips != false && state.options.tooltips != "gutter")
  12630. CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver);
  12631. startLinting(cm);
  12632. }
  12633. });
  12634. CodeMirror.defineExtension("performLint", function() {
  12635. if (this.state.lint) startLinting(this);
  12636. });
  12637. });
  12638. /* ---- extension/scroll/annotatescrollbar.js ---- */
  12639. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  12640. // Distributed under an MIT license: https://codemirror.net/LICENSE
  12641. (function(mod) {
  12642. if (typeof exports == "object" && typeof module == "object") // CommonJS
  12643. mod(require("../../lib/codemirror"));
  12644. else if (typeof define == "function" && define.amd) // AMD
  12645. define(["../../lib/codemirror"], mod);
  12646. else // Plain browser env
  12647. mod(CodeMirror);
  12648. })(function(CodeMirror) {
  12649. "use strict";
  12650. CodeMirror.defineExtension("annotateScrollbar", function(options) {
  12651. if (typeof options == "string") options = {className: options};
  12652. return new Annotation(this, options);
  12653. });
  12654. CodeMirror.defineOption("scrollButtonHeight", 0);
  12655. function Annotation(cm, options) {
  12656. this.cm = cm;
  12657. this.options = options;
  12658. this.buttonHeight = options.scrollButtonHeight || cm.getOption("scrollButtonHeight");
  12659. this.annotations = [];
  12660. this.doRedraw = this.doUpdate = null;
  12661. this.div = cm.getWrapperElement().appendChild(document.createElement("div"));
  12662. this.div.style.cssText = "position: absolute; right: 0; top: 0; z-index: 7; pointer-events: none";
  12663. this.computeScale();
  12664. function scheduleRedraw(delay) {
  12665. clearTimeout(self.doRedraw);
  12666. self.doRedraw = setTimeout(function() { self.redraw(); }, delay);
  12667. }
  12668. var self = this;
  12669. cm.on("refresh", this.resizeHandler = function() {
  12670. clearTimeout(self.doUpdate);
  12671. self.doUpdate = setTimeout(function() {
  12672. if (self.computeScale()) scheduleRedraw(20);
  12673. }, 100);
  12674. });
  12675. cm.on("markerAdded", this.resizeHandler);
  12676. cm.on("markerCleared", this.resizeHandler);
  12677. if (options.listenForChanges !== false)
  12678. cm.on("changes", this.changeHandler = function() {
  12679. scheduleRedraw(250);
  12680. });
  12681. }
  12682. Annotation.prototype.computeScale = function() {
  12683. var cm = this.cm;
  12684. var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight - this.buttonHeight * 2) /
  12685. cm.getScrollerElement().scrollHeight
  12686. if (hScale != this.hScale) {
  12687. this.hScale = hScale;
  12688. return true;
  12689. }
  12690. };
  12691. Annotation.prototype.update = function(annotations) {
  12692. this.annotations = annotations;
  12693. this.redraw();
  12694. };
  12695. Annotation.prototype.redraw = function(compute) {
  12696. if (compute !== false) this.computeScale();
  12697. var cm = this.cm, hScale = this.hScale;
  12698. var frag = document.createDocumentFragment(), anns = this.annotations;
  12699. var wrapping = cm.getOption("lineWrapping");
  12700. var singleLineH = wrapping && cm.defaultTextHeight() * 1.5;
  12701. var curLine = null, curLineObj = null;
  12702. function getY(pos, top) {
  12703. if (curLine != pos.line) {
  12704. curLine = pos.line;
  12705. curLineObj = cm.getLineHandle(curLine);
  12706. }
  12707. if ((curLineObj.widgets && curLineObj.widgets.length) ||
  12708. (wrapping && curLineObj.height > singleLineH))
  12709. return cm.charCoords(pos, "local")[top ? "top" : "bottom"];
  12710. var topY = cm.heightAtLine(curLineObj, "local");
  12711. return topY + (top ? 0 : curLineObj.height);
  12712. }
  12713. var lastLine = cm.lastLine()
  12714. if (cm.display.barWidth) for (var i = 0, nextTop; i < anns.length; i++) {
  12715. var ann = anns[i];
  12716. if (ann.to.line > lastLine) continue;
  12717. var top = nextTop || getY(ann.from, true) * hScale;
  12718. var bottom = getY(ann.to, false) * hScale;
  12719. while (i < anns.length - 1) {
  12720. if (anns[i + 1].to.line > lastLine) break;
  12721. nextTop = getY(anns[i + 1].from, true) * hScale;
  12722. if (nextTop > bottom + .9) break;
  12723. ann = anns[++i];
  12724. bottom = getY(ann.to, false) * hScale;
  12725. }
  12726. if (bottom == top) continue;
  12727. var height = Math.max(bottom - top, 3);
  12728. var elt = frag.appendChild(document.createElement("div"));
  12729. elt.style.cssText = "position: absolute; right: 0px; width: " + Math.max(cm.display.barWidth - 1, 2) + "px; top: "
  12730. + (top + this.buttonHeight) + "px; height: " + height + "px";
  12731. elt.className = this.options.className;
  12732. if (ann.id) {
  12733. elt.setAttribute("annotation-id", ann.id);
  12734. }
  12735. }
  12736. this.div.textContent = "";
  12737. this.div.appendChild(frag);
  12738. };
  12739. Annotation.prototype.clear = function() {
  12740. this.cm.off("refresh", this.resizeHandler);
  12741. this.cm.off("markerAdded", this.resizeHandler);
  12742. this.cm.off("markerCleared", this.resizeHandler);
  12743. if (this.changeHandler) this.cm.off("changes", this.changeHandler);
  12744. this.div.parentNode.removeChild(this.div);
  12745. };
  12746. });
  12747. /* ---- extension/scroll/scrollpastend.js ---- */
  12748. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  12749. // Distributed under an MIT license: https://codemirror.net/LICENSE
  12750. (function(mod) {
  12751. if (typeof exports == "object" && typeof module == "object") // CommonJS
  12752. mod(require("../../lib/codemirror"));
  12753. else if (typeof define == "function" && define.amd) // AMD
  12754. define(["../../lib/codemirror"], mod);
  12755. else // Plain browser env
  12756. mod(CodeMirror);
  12757. })(function(CodeMirror) {
  12758. "use strict";
  12759. CodeMirror.defineOption("scrollPastEnd", false, function(cm, val, old) {
  12760. if (old && old != CodeMirror.Init) {
  12761. cm.off("change", onChange);
  12762. cm.off("refresh", updateBottomMargin);
  12763. cm.display.lineSpace.parentNode.style.paddingBottom = "";
  12764. cm.state.scrollPastEndPadding = null;
  12765. }
  12766. if (val) {
  12767. cm.on("change", onChange);
  12768. cm.on("refresh", updateBottomMargin);
  12769. updateBottomMargin(cm);
  12770. }
  12771. });
  12772. function onChange(cm, change) {
  12773. if (CodeMirror.changeEnd(change).line == cm.lastLine())
  12774. updateBottomMargin(cm);
  12775. }
  12776. function updateBottomMargin(cm) {
  12777. var padding = "";
  12778. if (cm.lineCount() > 1) {
  12779. var totalH = cm.display.scroller.clientHeight - 30,
  12780. lastLineH = cm.getLineHandle(cm.lastLine()).height;
  12781. padding = (totalH - lastLineH) + "px";
  12782. }
  12783. if (cm.state.scrollPastEndPadding != padding) {
  12784. cm.state.scrollPastEndPadding = padding;
  12785. cm.display.lineSpace.parentNode.style.paddingBottom = padding;
  12786. cm.off("refresh", updateBottomMargin);
  12787. cm.setSize();
  12788. cm.on("refresh", updateBottomMargin);
  12789. }
  12790. }
  12791. });
  12792. /* ---- extension/scroll/simplescrollbars.js ---- */
  12793. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  12794. // Distributed under an MIT license: https://codemirror.net/LICENSE
  12795. (function(mod) {
  12796. if (typeof exports == "object" && typeof module == "object") // CommonJS
  12797. mod(require("../../lib/codemirror"));
  12798. else if (typeof define == "function" && define.amd) // AMD
  12799. define(["../../lib/codemirror"], mod);
  12800. else // Plain browser env
  12801. mod(CodeMirror);
  12802. })(function(CodeMirror) {
  12803. "use strict";
  12804. function Bar(cls, orientation, scroll) {
  12805. this.orientation = orientation;
  12806. this.scroll = scroll;
  12807. this.screen = this.total = this.size = 1;
  12808. this.pos = 0;
  12809. this.node = document.createElement("div");
  12810. this.node.className = cls + "-" + orientation;
  12811. this.inner = this.node.appendChild(document.createElement("div"));
  12812. var self = this;
  12813. CodeMirror.on(this.inner, "mousedown", function(e) {
  12814. if (e.which != 1) return;
  12815. CodeMirror.e_preventDefault(e);
  12816. var axis = self.orientation == "horizontal" ? "pageX" : "pageY";
  12817. var start = e[axis], startpos = self.pos;
  12818. function done() {
  12819. CodeMirror.off(document, "mousemove", move);
  12820. CodeMirror.off(document, "mouseup", done);
  12821. }
  12822. function move(e) {
  12823. if (e.which != 1) return done();
  12824. self.moveTo(startpos + (e[axis] - start) * (self.total / self.size));
  12825. }
  12826. CodeMirror.on(document, "mousemove", move);
  12827. CodeMirror.on(document, "mouseup", done);
  12828. });
  12829. CodeMirror.on(this.node, "click", function(e) {
  12830. CodeMirror.e_preventDefault(e);
  12831. var innerBox = self.inner.getBoundingClientRect(), where;
  12832. if (self.orientation == "horizontal")
  12833. where = e.clientX < innerBox.left ? -1 : e.clientX > innerBox.right ? 1 : 0;
  12834. else
  12835. where = e.clientY < innerBox.top ? -1 : e.clientY > innerBox.bottom ? 1 : 0;
  12836. self.moveTo(self.pos + where * self.screen);
  12837. });
  12838. function onWheel(e) {
  12839. var moved = CodeMirror.wheelEventPixels(e)[self.orientation == "horizontal" ? "x" : "y"];
  12840. var oldPos = self.pos;
  12841. self.moveTo(self.pos + moved);
  12842. if (self.pos != oldPos) CodeMirror.e_preventDefault(e);
  12843. }
  12844. CodeMirror.on(this.node, "mousewheel", onWheel);
  12845. CodeMirror.on(this.node, "DOMMouseScroll", onWheel);
  12846. }
  12847. Bar.prototype.setPos = function(pos, force) {
  12848. if (pos < 0) pos = 0;
  12849. if (pos > this.total - this.screen) pos = this.total - this.screen;
  12850. if (!force && pos == this.pos) return false;
  12851. this.pos = pos;
  12852. this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
  12853. (pos * (this.size / this.total)) + "px";
  12854. return true
  12855. };
  12856. Bar.prototype.moveTo = function(pos) {
  12857. if (this.setPos(pos)) this.scroll(pos, this.orientation);
  12858. }
  12859. var minButtonSize = 10;
  12860. Bar.prototype.update = function(scrollSize, clientSize, barSize) {
  12861. var sizeChanged = this.screen != clientSize || this.total != scrollSize || this.size != barSize
  12862. if (sizeChanged) {
  12863. this.screen = clientSize;
  12864. this.total = scrollSize;
  12865. this.size = barSize;
  12866. }
  12867. var buttonSize = this.screen * (this.size / this.total);
  12868. if (buttonSize < minButtonSize) {
  12869. this.size -= minButtonSize - buttonSize;
  12870. buttonSize = minButtonSize;
  12871. }
  12872. this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =
  12873. buttonSize + "px";
  12874. this.setPos(this.pos, sizeChanged);
  12875. };
  12876. function SimpleScrollbars(cls, place, scroll) {
  12877. this.addClass = cls;
  12878. this.horiz = new Bar(cls, "horizontal", scroll);
  12879. place(this.horiz.node);
  12880. this.vert = new Bar(cls, "vertical", scroll);
  12881. place(this.vert.node);
  12882. this.width = null;
  12883. }
  12884. SimpleScrollbars.prototype.update = function(measure) {
  12885. if (this.width == null) {
  12886. var style = window.getComputedStyle ? window.getComputedStyle(this.horiz.node) : this.horiz.node.currentStyle;
  12887. if (style) this.width = parseInt(style.height);
  12888. }
  12889. var width = this.width || 0;
  12890. var needsH = measure.scrollWidth > measure.clientWidth + 1;
  12891. var needsV = measure.scrollHeight > measure.clientHeight + 1;
  12892. this.vert.node.style.display = needsV ? "block" : "none";
  12893. this.horiz.node.style.display = needsH ? "block" : "none";
  12894. if (needsV) {
  12895. this.vert.update(measure.scrollHeight, measure.clientHeight,
  12896. measure.viewHeight - (needsH ? width : 0));
  12897. this.vert.node.style.bottom = needsH ? width + "px" : "0";
  12898. }
  12899. if (needsH) {
  12900. this.horiz.update(measure.scrollWidth, measure.clientWidth,
  12901. measure.viewWidth - (needsV ? width : 0) - measure.barLeft);
  12902. this.horiz.node.style.right = needsV ? width + "px" : "0";
  12903. this.horiz.node.style.left = measure.barLeft + "px";
  12904. }
  12905. return {right: needsV ? width : 0, bottom: needsH ? width : 0};
  12906. };
  12907. SimpleScrollbars.prototype.setScrollTop = function(pos) {
  12908. this.vert.setPos(pos);
  12909. };
  12910. SimpleScrollbars.prototype.setScrollLeft = function(pos) {
  12911. this.horiz.setPos(pos);
  12912. };
  12913. SimpleScrollbars.prototype.clear = function() {
  12914. var parent = this.horiz.node.parentNode;
  12915. parent.removeChild(this.horiz.node);
  12916. parent.removeChild(this.vert.node);
  12917. };
  12918. CodeMirror.scrollbarModel.simple = function(place, scroll) {
  12919. return new SimpleScrollbars("CodeMirror-simplescroll", place, scroll);
  12920. };
  12921. CodeMirror.scrollbarModel.overlay = function(place, scroll) {
  12922. return new SimpleScrollbars("CodeMirror-overlayscroll", place, scroll);
  12923. };
  12924. });
  12925. /* ---- extension/search/jump-to-line.js ---- */
  12926. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  12927. // Distributed under an MIT license: https://codemirror.net/LICENSE
  12928. // Defines jumpToLine command. Uses dialog.js if present.
  12929. (function(mod) {
  12930. if (typeof exports == "object" && typeof module == "object") // CommonJS
  12931. mod(require("../../lib/codemirror"), require("../dialog/dialog"));
  12932. else if (typeof define == "function" && define.amd) // AMD
  12933. define(["../../lib/codemirror", "../dialog/dialog"], mod);
  12934. else // Plain browser env
  12935. mod(CodeMirror);
  12936. })(function(CodeMirror) {
  12937. "use strict";
  12938. function dialog(cm, text, shortText, deflt, f) {
  12939. if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true});
  12940. else f(prompt(shortText, deflt));
  12941. }
  12942. function getJumpDialog(cm) {
  12943. return cm.phrase("Jump to line:") + ' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">' + cm.phrase("(Use line:column or scroll% syntax)") + '</span>';
  12944. }
  12945. function interpretLine(cm, string) {
  12946. var num = Number(string)
  12947. if (/^[-+]/.test(string)) return cm.getCursor().line + num
  12948. else return num - 1
  12949. }
  12950. CodeMirror.commands.jumpToLine = function(cm) {
  12951. var cur = cm.getCursor();
  12952. dialog(cm, getJumpDialog(cm), cm.phrase("Jump to line:"), (cur.line + 1) + ":" + cur.ch, function(posStr) {
  12953. if (!posStr) return;
  12954. var match;
  12955. if (match = /^\s*([\+\-]?\d+)\s*\:\s*(\d+)\s*$/.exec(posStr)) {
  12956. cm.setCursor(interpretLine(cm, match[1]), Number(match[2]))
  12957. } else if (match = /^\s*([\+\-]?\d+(\.\d+)?)\%\s*/.exec(posStr)) {
  12958. var line = Math.round(cm.lineCount() * Number(match[1]) / 100);
  12959. if (/^[-+]/.test(match[1])) line = cur.line + line + 1;
  12960. cm.setCursor(line - 1, cur.ch);
  12961. } else if (match = /^\s*\:?\s*([\+\-]?\d+)\s*/.exec(posStr)) {
  12962. cm.setCursor(interpretLine(cm, match[1]), cur.ch);
  12963. }
  12964. });
  12965. };
  12966. CodeMirror.keyMap["default"]["Alt-G"] = "jumpToLine";
  12967. });
  12968. /* ---- extension/search/match-highlighter.js ---- */
  12969. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  12970. // Distributed under an MIT license: https://codemirror.net/LICENSE
  12971. // Highlighting text that matches the selection
  12972. //
  12973. // Defines an option highlightSelectionMatches, which, when enabled,
  12974. // will style strings that match the selection throughout the
  12975. // document.
  12976. //
  12977. // The option can be set to true to simply enable it, or to a
  12978. // {minChars, style, wordsOnly, showToken, delay} object to explicitly
  12979. // configure it. minChars is the minimum amount of characters that should be
  12980. // selected for the behavior to occur, and style is the token style to
  12981. // apply to the matches. This will be prefixed by "cm-" to create an
  12982. // actual CSS class name. If wordsOnly is enabled, the matches will be
  12983. // highlighted only if the selected text is a word. showToken, when enabled,
  12984. // will cause the current token to be highlighted when nothing is selected.
  12985. // delay is used to specify how much time to wait, in milliseconds, before
  12986. // highlighting the matches. If annotateScrollbar is enabled, the occurences
  12987. // will be highlighted on the scrollbar via the matchesonscrollbar addon.
  12988. (function(mod) {
  12989. if (typeof exports == "object" && typeof module == "object") // CommonJS
  12990. mod(require("../../lib/codemirror"), require("./matchesonscrollbar"));
  12991. else if (typeof define == "function" && define.amd) // AMD
  12992. define(["../../lib/codemirror", "./matchesonscrollbar"], mod);
  12993. else // Plain browser env
  12994. mod(CodeMirror);
  12995. })(function(CodeMirror) {
  12996. "use strict";
  12997. var defaults = {
  12998. style: "matchhighlight",
  12999. minChars: 2,
  13000. delay: 100,
  13001. wordsOnly: false,
  13002. annotateScrollbar: false,
  13003. showToken: false,
  13004. trim: true
  13005. }
  13006. function State(options) {
  13007. this.options = {}
  13008. for (var name in defaults)
  13009. this.options[name] = (options && options.hasOwnProperty(name) ? options : defaults)[name]
  13010. this.overlay = this.timeout = null;
  13011. this.matchesonscroll = null;
  13012. this.active = false;
  13013. }
  13014. CodeMirror.defineOption("highlightSelectionMatches", false, function(cm, val, old) {
  13015. if (old && old != CodeMirror.Init) {
  13016. removeOverlay(cm);
  13017. clearTimeout(cm.state.matchHighlighter.timeout);
  13018. cm.state.matchHighlighter = null;
  13019. cm.off("cursorActivity", cursorActivity);
  13020. cm.off("focus", onFocus)
  13021. }
  13022. if (val) {
  13023. var state = cm.state.matchHighlighter = new State(val);
  13024. if (cm.hasFocus()) {
  13025. state.active = true
  13026. highlightMatches(cm)
  13027. } else {
  13028. cm.on("focus", onFocus)
  13029. }
  13030. cm.on("cursorActivity", cursorActivity);
  13031. }
  13032. });
  13033. function cursorActivity(cm) {
  13034. var state = cm.state.matchHighlighter;
  13035. if (state.active || cm.hasFocus()) scheduleHighlight(cm, state)
  13036. }
  13037. function onFocus(cm) {
  13038. var state = cm.state.matchHighlighter
  13039. if (!state.active) {
  13040. state.active = true
  13041. scheduleHighlight(cm, state)
  13042. }
  13043. }
  13044. function scheduleHighlight(cm, state) {
  13045. clearTimeout(state.timeout);
  13046. state.timeout = setTimeout(function() {highlightMatches(cm);}, state.options.delay);
  13047. }
  13048. function addOverlay(cm, query, hasBoundary, style) {
  13049. var state = cm.state.matchHighlighter;
  13050. cm.addOverlay(state.overlay = makeOverlay(query, hasBoundary, style));
  13051. if (state.options.annotateScrollbar && cm.showMatchesOnScrollbar) {
  13052. var searchFor = hasBoundary ? new RegExp((/\w/.test(query.charAt(0)) ? "\\b" : "") +
  13053. query.replace(/[\\\[.+*?(){|^$]/g, "\\$&") +
  13054. (/\w/.test(query.charAt(query.length - 1)) ? "\\b" : "")) : query;
  13055. state.matchesonscroll = cm.showMatchesOnScrollbar(searchFor, false,
  13056. {className: "CodeMirror-selection-highlight-scrollbar"});
  13057. }
  13058. }
  13059. function removeOverlay(cm) {
  13060. var state = cm.state.matchHighlighter;
  13061. if (state.overlay) {
  13062. cm.removeOverlay(state.overlay);
  13063. state.overlay = null;
  13064. if (state.matchesonscroll) {
  13065. state.matchesonscroll.clear();
  13066. state.matchesonscroll = null;
  13067. }
  13068. }
  13069. }
  13070. function highlightMatches(cm) {
  13071. cm.operation(function() {
  13072. var state = cm.state.matchHighlighter;
  13073. removeOverlay(cm);
  13074. if (!cm.somethingSelected() && state.options.showToken) {
  13075. var re = state.options.showToken === true ? /[\w$]/ : state.options.showToken;
  13076. var cur = cm.getCursor(), line = cm.getLine(cur.line), start = cur.ch, end = start;
  13077. while (start && re.test(line.charAt(start - 1))) --start;
  13078. while (end < line.length && re.test(line.charAt(end))) ++end;
  13079. if (start < end)
  13080. addOverlay(cm, line.slice(start, end), re, state.options.style);
  13081. return;
  13082. }
  13083. var from = cm.getCursor("from"), to = cm.getCursor("to");
  13084. if (from.line != to.line) return;
  13085. if (state.options.wordsOnly && !isWord(cm, from, to)) return;
  13086. var selection = cm.getRange(from, to)
  13087. if (state.options.trim) selection = selection.replace(/^\s+|\s+$/g, "")
  13088. if (selection.length >= state.options.minChars)
  13089. addOverlay(cm, selection, false, state.options.style);
  13090. });
  13091. }
  13092. function isWord(cm, from, to) {
  13093. var str = cm.getRange(from, to);
  13094. if (str.match(/^\w+$/) !== null) {
  13095. if (from.ch > 0) {
  13096. var pos = {line: from.line, ch: from.ch - 1};
  13097. var chr = cm.getRange(pos, from);
  13098. if (chr.match(/\W/) === null) return false;
  13099. }
  13100. if (to.ch < cm.getLine(from.line).length) {
  13101. var pos = {line: to.line, ch: to.ch + 1};
  13102. var chr = cm.getRange(to, pos);
  13103. if (chr.match(/\W/) === null) return false;
  13104. }
  13105. return true;
  13106. } else return false;
  13107. }
  13108. function boundariesAround(stream, re) {
  13109. return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) &&
  13110. (stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos)));
  13111. }
  13112. function makeOverlay(query, hasBoundary, style) {
  13113. return {token: function(stream) {
  13114. if (stream.match(query) &&
  13115. (!hasBoundary || boundariesAround(stream, hasBoundary)))
  13116. return style;
  13117. stream.next();
  13118. stream.skipTo(query.charAt(0)) || stream.skipToEnd();
  13119. }};
  13120. }
  13121. });
  13122. /* ---- extension/search/matchesonscrollbar.js ---- */
  13123. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  13124. // Distributed under an MIT license: https://codemirror.net/LICENSE
  13125. (function(mod) {
  13126. if (typeof exports == "object" && typeof module == "object") // CommonJS
  13127. mod(require("../../lib/codemirror"), require("./searchcursor"), require("../scroll/annotatescrollbar"));
  13128. else if (typeof define == "function" && define.amd) // AMD
  13129. define(["../../lib/codemirror", "./searchcursor", "../scroll/annotatescrollbar"], mod);
  13130. else // Plain browser env
  13131. mod(CodeMirror);
  13132. })(function(CodeMirror) {
  13133. "use strict";
  13134. CodeMirror.defineExtension("showMatchesOnScrollbar", function(query, caseFold, options) {
  13135. if (typeof options == "string") options = {className: options};
  13136. if (!options) options = {};
  13137. return new SearchAnnotation(this, query, caseFold, options);
  13138. });
  13139. function SearchAnnotation(cm, query, caseFold, options) {
  13140. this.cm = cm;
  13141. this.options = options;
  13142. var annotateOptions = {listenForChanges: false};
  13143. for (var prop in options) annotateOptions[prop] = options[prop];
  13144. if (!annotateOptions.className) annotateOptions.className = "CodeMirror-search-match";
  13145. this.annotation = cm.annotateScrollbar(annotateOptions);
  13146. this.query = query;
  13147. this.caseFold = caseFold;
  13148. this.gap = {from: cm.firstLine(), to: cm.lastLine() + 1};
  13149. this.matches = [];
  13150. this.update = null;
  13151. this.findMatches();
  13152. this.annotation.update(this.matches);
  13153. var self = this;
  13154. cm.on("change", this.changeHandler = function(_cm, change) { self.onChange(change); });
  13155. }
  13156. var MAX_MATCHES = 1000;
  13157. SearchAnnotation.prototype.findMatches = function() {
  13158. if (!this.gap) return;
  13159. for (var i = 0; i < this.matches.length; i++) {
  13160. var match = this.matches[i];
  13161. if (match.from.line >= this.gap.to) break;
  13162. if (match.to.line >= this.gap.from) this.matches.splice(i--, 1);
  13163. }
  13164. var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), {caseFold: this.caseFold, multiline: this.options.multiline});
  13165. var maxMatches = this.options && this.options.maxMatches || MAX_MATCHES;
  13166. while (cursor.findNext()) {
  13167. var match = {from: cursor.from(), to: cursor.to()};
  13168. if (match.from.line >= this.gap.to) break;
  13169. this.matches.splice(i++, 0, match);
  13170. if (this.matches.length > maxMatches) break;
  13171. }
  13172. this.gap = null;
  13173. };
  13174. function offsetLine(line, changeStart, sizeChange) {
  13175. if (line <= changeStart) return line;
  13176. return Math.max(changeStart, line + sizeChange);
  13177. }
  13178. SearchAnnotation.prototype.onChange = function(change) {
  13179. var startLine = change.from.line;
  13180. var endLine = CodeMirror.changeEnd(change).line;
  13181. var sizeChange = endLine - change.to.line;
  13182. if (this.gap) {
  13183. this.gap.from = Math.min(offsetLine(this.gap.from, startLine, sizeChange), change.from.line);
  13184. this.gap.to = Math.max(offsetLine(this.gap.to, startLine, sizeChange), change.from.line);
  13185. } else {
  13186. this.gap = {from: change.from.line, to: endLine + 1};
  13187. }
  13188. if (sizeChange) for (var i = 0; i < this.matches.length; i++) {
  13189. var match = this.matches[i];
  13190. var newFrom = offsetLine(match.from.line, startLine, sizeChange);
  13191. if (newFrom != match.from.line) match.from = CodeMirror.Pos(newFrom, match.from.ch);
  13192. var newTo = offsetLine(match.to.line, startLine, sizeChange);
  13193. if (newTo != match.to.line) match.to = CodeMirror.Pos(newTo, match.to.ch);
  13194. }
  13195. clearTimeout(this.update);
  13196. var self = this;
  13197. this.update = setTimeout(function() { self.updateAfterChange(); }, 250);
  13198. };
  13199. SearchAnnotation.prototype.updateAfterChange = function() {
  13200. this.findMatches();
  13201. this.annotation.update(this.matches);
  13202. };
  13203. SearchAnnotation.prototype.clear = function() {
  13204. this.cm.off("change", this.changeHandler);
  13205. this.annotation.clear();
  13206. };
  13207. });
  13208. /* ---- extension/search/search.js ---- */
  13209. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  13210. // Distributed under an MIT license: https://codemirror.net/LICENSE
  13211. // Define search commands. Depends on dialog.js or another
  13212. // implementation of the openDialog method.
  13213. // Replace works a little oddly -- it will do the replace on the next
  13214. // Ctrl-G (or whatever is bound to findNext) press. You prevent a
  13215. // replace by making sure the match is no longer selected when hitting
  13216. // Ctrl-G.
  13217. (function(mod) {
  13218. if (typeof exports == "object" && typeof module == "object") // CommonJS
  13219. mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog"));
  13220. else if (typeof define == "function" && define.amd) // AMD
  13221. define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod);
  13222. else // Plain browser env
  13223. mod(CodeMirror);
  13224. })(function(CodeMirror) {
  13225. "use strict";
  13226. function searchOverlay(query, caseInsensitive) {
  13227. if (typeof query == "string")
  13228. query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g");
  13229. else if (!query.global)
  13230. query = new RegExp(query.source, query.ignoreCase ? "gi" : "g");
  13231. return {token: function(stream) {
  13232. query.lastIndex = stream.pos;
  13233. var match = query.exec(stream.string);
  13234. if (match && match.index == stream.pos) {
  13235. stream.pos += match[0].length || 1;
  13236. return "searching";
  13237. } else if (match) {
  13238. stream.pos = match.index;
  13239. } else {
  13240. stream.skipToEnd();
  13241. }
  13242. }};
  13243. }
  13244. function SearchState() {
  13245. this.posFrom = this.posTo = this.lastQuery = this.query = null;
  13246. this.overlay = null;
  13247. }
  13248. function getSearchState(cm) {
  13249. return cm.state.search || (cm.state.search = new SearchState());
  13250. }
  13251. function queryCaseInsensitive(query) {
  13252. return typeof query == "string" && query == query.toLowerCase();
  13253. }
  13254. function getSearchCursor(cm, query, pos) {
  13255. // Heuristic: if the query string is all lowercase, do a case insensitive search.
  13256. return cm.getSearchCursor(query, pos, {caseFold: queryCaseInsensitive(query), multiline: true});
  13257. }
  13258. function persistentDialog(cm, text, deflt, onEnter, onKeyDown) {
  13259. cm.openDialog(text, onEnter, {
  13260. value: deflt,
  13261. selectValueOnOpen: true,
  13262. closeOnEnter: false,
  13263. onClose: function() { clearSearch(cm); },
  13264. onKeyDown: onKeyDown
  13265. });
  13266. }
  13267. function dialog(cm, text, shortText, deflt, f) {
  13268. if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true});
  13269. else f(prompt(shortText, deflt));
  13270. }
  13271. function confirmDialog(cm, text, shortText, fs) {
  13272. if (cm.openConfirm) cm.openConfirm(text, fs);
  13273. else if (confirm(shortText)) fs[0]();
  13274. }
  13275. function parseString(string) {
  13276. return string.replace(/\\([nrt\\])/g, function(match, ch) {
  13277. if (ch == "n") return "\n"
  13278. if (ch == "r") return "\r"
  13279. if (ch == "t") return "\t"
  13280. if (ch == "\\") return "\\"
  13281. return match
  13282. })
  13283. }
  13284. function parseQuery(query) {
  13285. var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
  13286. if (isRE) {
  13287. try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
  13288. catch(e) {} // Not a regular expression after all, do a string search
  13289. } else {
  13290. query = parseString(query)
  13291. }
  13292. if (typeof query == "string" ? query == "" : query.test(""))
  13293. query = /x^/;
  13294. return query;
  13295. }
  13296. function startSearch(cm, state, query) {
  13297. state.queryText = query;
  13298. state.query = parseQuery(query);
  13299. cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
  13300. state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
  13301. cm.addOverlay(state.overlay);
  13302. if (cm.showMatchesOnScrollbar) {
  13303. if (state.annotate) { state.annotate.clear(); state.annotate = null; }
  13304. state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
  13305. }
  13306. }
  13307. function doSearch(cm, rev, persistent, immediate) {
  13308. var state = getSearchState(cm);
  13309. if (state.query) return findNext(cm, rev);
  13310. var q = cm.getSelection() || state.lastQuery;
  13311. if (q instanceof RegExp && q.source == "x^") q = null
  13312. if (persistent && cm.openDialog) {
  13313. var hiding = null
  13314. var searchNext = function(query, event) {
  13315. CodeMirror.e_stop(event);
  13316. if (!query) return;
  13317. if (query != state.queryText) {
  13318. startSearch(cm, state, query);
  13319. state.posFrom = state.posTo = cm.getCursor();
  13320. }
  13321. if (hiding) hiding.style.opacity = 1
  13322. findNext(cm, event.shiftKey, function(_, to) {
  13323. var dialog
  13324. if (to.line < 3 && document.querySelector &&
  13325. (dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) &&
  13326. dialog.getBoundingClientRect().bottom - 4 > cm.cursorCoords(to, "window").top)
  13327. (hiding = dialog).style.opacity = .4
  13328. })
  13329. };
  13330. persistentDialog(cm, getQueryDialog(cm), q, searchNext, function(event, query) {
  13331. var keyName = CodeMirror.keyName(event)
  13332. var extra = cm.getOption('extraKeys'), cmd = (extra && extra[keyName]) || CodeMirror.keyMap[cm.getOption("keyMap")][keyName]
  13333. if (cmd == "findNext" || cmd == "findPrev" ||
  13334. cmd == "findPersistentNext" || cmd == "findPersistentPrev") {
  13335. CodeMirror.e_stop(event);
  13336. startSearch(cm, getSearchState(cm), query);
  13337. cm.execCommand(cmd);
  13338. } else if (cmd == "find" || cmd == "findPersistent") {
  13339. CodeMirror.e_stop(event);
  13340. searchNext(query, event);
  13341. }
  13342. });
  13343. if (immediate && q) {
  13344. startSearch(cm, state, q);
  13345. findNext(cm, rev);
  13346. }
  13347. } else {
  13348. dialog(cm, getQueryDialog(cm), "Search for:", q, function(query) {
  13349. if (query && !state.query) cm.operation(function() {
  13350. startSearch(cm, state, query);
  13351. state.posFrom = state.posTo = cm.getCursor();
  13352. findNext(cm, rev);
  13353. });
  13354. });
  13355. }
  13356. }
  13357. function findNext(cm, rev, callback) {cm.operation(function() {
  13358. var state = getSearchState(cm);
  13359. var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
  13360. if (!cursor.find(rev)) {
  13361. cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0));
  13362. if (!cursor.find(rev)) return;
  13363. }
  13364. cm.setSelection(cursor.from(), cursor.to());
  13365. cm.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20);
  13366. state.posFrom = cursor.from(); state.posTo = cursor.to();
  13367. if (callback) callback(cursor.from(), cursor.to())
  13368. });}
  13369. function clearSearch(cm) {cm.operation(function() {
  13370. var state = getSearchState(cm);
  13371. state.lastQuery = state.query;
  13372. if (!state.query) return;
  13373. state.query = state.queryText = null;
  13374. cm.removeOverlay(state.overlay);
  13375. if (state.annotate) { state.annotate.clear(); state.annotate = null; }
  13376. });}
  13377. function getQueryDialog(cm) {
  13378. return '<span class="CodeMirror-search-label">' + cm.phrase("Search:") + '</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">' + cm.phrase("(Use /re/ syntax for regexp search)") + '</span>';
  13379. }
  13380. function getReplaceQueryDialog(cm) {
  13381. return ' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">' + cm.phrase("(Use /re/ syntax for regexp search)") + '</span>';
  13382. }
  13383. function getReplacementQueryDialog(cm) {
  13384. return '<span class="CodeMirror-search-label">' + cm.phrase("With:") + '</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
  13385. }
  13386. function getDoReplaceConfirm(cm) {
  13387. return '<span class="CodeMirror-search-label">' + cm.phrase("Replace?") + '</span> <button>' + cm.phrase("Yes") + '</button> <button>' + cm.phrase("No") + '</button> <button>' + cm.phrase("All") + '</button> <button>' + cm.phrase("Stop") + '</button> ';
  13388. }
  13389. function replaceAll(cm, query, text) {
  13390. cm.operation(function() {
  13391. for (var cursor = getSearchCursor(cm, query); cursor.findNext();) {
  13392. if (typeof query != "string") {
  13393. var match = cm.getRange(cursor.from(), cursor.to()).match(query);
  13394. cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
  13395. } else cursor.replace(text);
  13396. }
  13397. });
  13398. }
  13399. function replace(cm, all) {
  13400. if (cm.getOption("readOnly")) return;
  13401. var query = cm.getSelection() || getSearchState(cm).lastQuery;
  13402. var dialogText = '<span class="CodeMirror-search-label">' + (all ? cm.phrase("Replace all:") : cm.phrase("Replace:")) + '</span>';
  13403. dialog(cm, dialogText + getReplaceQueryDialog(cm), dialogText, query, function(query) {
  13404. if (!query) return;
  13405. query = parseQuery(query);
  13406. dialog(cm, getReplacementQueryDialog(cm), cm.phrase("Replace with:"), "", function(text) {
  13407. text = parseString(text)
  13408. if (all) {
  13409. replaceAll(cm, query, text)
  13410. } else {
  13411. clearSearch(cm);
  13412. var cursor = getSearchCursor(cm, query, cm.getCursor("from"));
  13413. var advance = function() {
  13414. var start = cursor.from(), match;
  13415. if (!(match = cursor.findNext())) {
  13416. cursor = getSearchCursor(cm, query);
  13417. if (!(match = cursor.findNext()) ||
  13418. (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return;
  13419. }
  13420. cm.setSelection(cursor.from(), cursor.to());
  13421. cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
  13422. confirmDialog(cm, getDoReplaceConfirm(cm), cm.phrase("Replace?"),
  13423. [function() {doReplace(match);}, advance,
  13424. function() {replaceAll(cm, query, text)}]);
  13425. };
  13426. var doReplace = function(match) {
  13427. cursor.replace(typeof query == "string" ? text :
  13428. text.replace(/\$(\d)/g, function(_, i) {return match[i];}));
  13429. advance();
  13430. };
  13431. advance();
  13432. }
  13433. });
  13434. });
  13435. }
  13436. CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
  13437. CodeMirror.commands.findPersistent = function(cm) {clearSearch(cm); doSearch(cm, false, true);};
  13438. CodeMirror.commands.findPersistentNext = function(cm) {doSearch(cm, false, true, true);};
  13439. CodeMirror.commands.findPersistentPrev = function(cm) {doSearch(cm, true, true, true);};
  13440. CodeMirror.commands.findNext = doSearch;
  13441. CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
  13442. CodeMirror.commands.clearSearch = clearSearch;
  13443. CodeMirror.commands.replace = replace;
  13444. CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);};
  13445. });
  13446. /* ---- extension/search/searchcursor.js ---- */
  13447. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  13448. // Distributed under an MIT license: https://codemirror.net/LICENSE
  13449. (function(mod) {
  13450. if (typeof exports == "object" && typeof module == "object") // CommonJS
  13451. mod(require("../../lib/codemirror"))
  13452. else if (typeof define == "function" && define.amd) // AMD
  13453. define(["../../lib/codemirror"], mod)
  13454. else // Plain browser env
  13455. mod(CodeMirror)
  13456. })(function(CodeMirror) {
  13457. "use strict"
  13458. var Pos = CodeMirror.Pos
  13459. function regexpFlags(regexp) {
  13460. var flags = regexp.flags
  13461. return flags != null ? flags : (regexp.ignoreCase ? "i" : "")
  13462. + (regexp.global ? "g" : "")
  13463. + (regexp.multiline ? "m" : "")
  13464. }
  13465. function ensureFlags(regexp, flags) {
  13466. var current = regexpFlags(regexp), target = current
  13467. for (var i = 0; i < flags.length; i++) if (target.indexOf(flags.charAt(i)) == -1)
  13468. target += flags.charAt(i)
  13469. return current == target ? regexp : new RegExp(regexp.source, target)
  13470. }
  13471. function maybeMultiline(regexp) {
  13472. return /\\s|\\n|\n|\\W|\\D|\[\^/.test(regexp.source)
  13473. }
  13474. function searchRegexpForward(doc, regexp, start) {
  13475. regexp = ensureFlags(regexp, "g")
  13476. for (var line = start.line, ch = start.ch, last = doc.lastLine(); line <= last; line++, ch = 0) {
  13477. regexp.lastIndex = ch
  13478. var string = doc.getLine(line), match = regexp.exec(string)
  13479. if (match)
  13480. return {from: Pos(line, match.index),
  13481. to: Pos(line, match.index + match[0].length),
  13482. match: match}
  13483. }
  13484. }
  13485. function searchRegexpForwardMultiline(doc, regexp, start) {
  13486. if (!maybeMultiline(regexp)) return searchRegexpForward(doc, regexp, start)
  13487. regexp = ensureFlags(regexp, "gm")
  13488. var string, chunk = 1
  13489. for (var line = start.line, last = doc.lastLine(); line <= last;) {
  13490. // This grows the search buffer in exponentially-sized chunks
  13491. // between matches, so that nearby matches are fast and don't
  13492. // require concatenating the whole document (in case we're
  13493. // searching for something that has tons of matches), but at the
  13494. // same time, the amount of retries is limited.
  13495. for (var i = 0; i < chunk; i++) {
  13496. if (line > last) break
  13497. var curLine = doc.getLine(line++)
  13498. string = string == null ? curLine : string + "\n" + curLine
  13499. }
  13500. chunk = chunk * 2
  13501. regexp.lastIndex = start.ch
  13502. var match = regexp.exec(string)
  13503. if (match) {
  13504. var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n")
  13505. var startLine = start.line + before.length - 1, startCh = before[before.length - 1].length
  13506. return {from: Pos(startLine, startCh),
  13507. to: Pos(startLine + inside.length - 1,
  13508. inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length),
  13509. match: match}
  13510. }
  13511. }
  13512. }
  13513. function lastMatchIn(string, regexp, endMargin) {
  13514. var match, from = 0
  13515. while (from <= string.length) {
  13516. regexp.lastIndex = from
  13517. var newMatch = regexp.exec(string)
  13518. if (!newMatch) break
  13519. var end = newMatch.index + newMatch[0].length
  13520. if (end > string.length - endMargin) break
  13521. if (!match || end > match.index + match[0].length)
  13522. match = newMatch
  13523. from = newMatch.index + 1
  13524. }
  13525. return match
  13526. }
  13527. function searchRegexpBackward(doc, regexp, start) {
  13528. regexp = ensureFlags(regexp, "g")
  13529. for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) {
  13530. var string = doc.getLine(line)
  13531. var match = lastMatchIn(string, regexp, ch < 0 ? 0 : string.length - ch)
  13532. if (match)
  13533. return {from: Pos(line, match.index),
  13534. to: Pos(line, match.index + match[0].length),
  13535. match: match}
  13536. }
  13537. }
  13538. function searchRegexpBackwardMultiline(doc, regexp, start) {
  13539. if (!maybeMultiline(regexp)) return searchRegexpBackward(doc, regexp, start)
  13540. regexp = ensureFlags(regexp, "gm")
  13541. var string, chunkSize = 1, endMargin = doc.getLine(start.line).length - start.ch
  13542. for (var line = start.line, first = doc.firstLine(); line >= first;) {
  13543. for (var i = 0; i < chunkSize && line >= first; i++) {
  13544. var curLine = doc.getLine(line--)
  13545. string = string == null ? curLine : curLine + "\n" + string
  13546. }
  13547. chunkSize *= 2
  13548. var match = lastMatchIn(string, regexp, endMargin)
  13549. if (match) {
  13550. var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n")
  13551. var startLine = line + before.length, startCh = before[before.length - 1].length
  13552. return {from: Pos(startLine, startCh),
  13553. to: Pos(startLine + inside.length - 1,
  13554. inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length),
  13555. match: match}
  13556. }
  13557. }
  13558. }
  13559. var doFold, noFold
  13560. if (String.prototype.normalize) {
  13561. doFold = function(str) { return str.normalize("NFD").toLowerCase() }
  13562. noFold = function(str) { return str.normalize("NFD") }
  13563. } else {
  13564. doFold = function(str) { return str.toLowerCase() }
  13565. noFold = function(str) { return str }
  13566. }
  13567. // Maps a position in a case-folded line back to a position in the original line
  13568. // (compensating for codepoints increasing in number during folding)
  13569. function adjustPos(orig, folded, pos, foldFunc) {
  13570. if (orig.length == folded.length) return pos
  13571. for (var min = 0, max = pos + Math.max(0, orig.length - folded.length);;) {
  13572. if (min == max) return min
  13573. var mid = (min + max) >> 1
  13574. var len = foldFunc(orig.slice(0, mid)).length
  13575. if (len == pos) return mid
  13576. else if (len > pos) max = mid
  13577. else min = mid + 1
  13578. }
  13579. }
  13580. function searchStringForward(doc, query, start, caseFold) {
  13581. // Empty string would match anything and never progress, so we
  13582. // define it to match nothing instead.
  13583. if (!query.length) return null
  13584. var fold = caseFold ? doFold : noFold
  13585. var lines = fold(query).split(/\r|\n\r?/)
  13586. search: for (var line = start.line, ch = start.ch, last = doc.lastLine() + 1 - lines.length; line <= last; line++, ch = 0) {
  13587. var orig = doc.getLine(line).slice(ch), string = fold(orig)
  13588. if (lines.length == 1) {
  13589. var found = string.indexOf(lines[0])
  13590. if (found == -1) continue search
  13591. var start = adjustPos(orig, string, found, fold) + ch
  13592. return {from: Pos(line, adjustPos(orig, string, found, fold) + ch),
  13593. to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold) + ch)}
  13594. } else {
  13595. var cutFrom = string.length - lines[0].length
  13596. if (string.slice(cutFrom) != lines[0]) continue search
  13597. for (var i = 1; i < lines.length - 1; i++)
  13598. if (fold(doc.getLine(line + i)) != lines[i]) continue search
  13599. var end = doc.getLine(line + lines.length - 1), endString = fold(end), lastLine = lines[lines.length - 1]
  13600. if (endString.slice(0, lastLine.length) != lastLine) continue search
  13601. return {from: Pos(line, adjustPos(orig, string, cutFrom, fold) + ch),
  13602. to: Pos(line + lines.length - 1, adjustPos(end, endString, lastLine.length, fold))}
  13603. }
  13604. }
  13605. }
  13606. function searchStringBackward(doc, query, start, caseFold) {
  13607. if (!query.length) return null
  13608. var fold = caseFold ? doFold : noFold
  13609. var lines = fold(query).split(/\r|\n\r?/)
  13610. search: for (var line = start.line, ch = start.ch, first = doc.firstLine() - 1 + lines.length; line >= first; line--, ch = -1) {
  13611. var orig = doc.getLine(line)
  13612. if (ch > -1) orig = orig.slice(0, ch)
  13613. var string = fold(orig)
  13614. if (lines.length == 1) {
  13615. var found = string.lastIndexOf(lines[0])
  13616. if (found == -1) continue search
  13617. return {from: Pos(line, adjustPos(orig, string, found, fold)),
  13618. to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold))}
  13619. } else {
  13620. var lastLine = lines[lines.length - 1]
  13621. if (string.slice(0, lastLine.length) != lastLine) continue search
  13622. for (var i = 1, start = line - lines.length + 1; i < lines.length - 1; i++)
  13623. if (fold(doc.getLine(start + i)) != lines[i]) continue search
  13624. var top = doc.getLine(line + 1 - lines.length), topString = fold(top)
  13625. if (topString.slice(topString.length - lines[0].length) != lines[0]) continue search
  13626. return {from: Pos(line + 1 - lines.length, adjustPos(top, topString, top.length - lines[0].length, fold)),
  13627. to: Pos(line, adjustPos(orig, string, lastLine.length, fold))}
  13628. }
  13629. }
  13630. }
  13631. function SearchCursor(doc, query, pos, options) {
  13632. this.atOccurrence = false
  13633. this.doc = doc
  13634. pos = pos ? doc.clipPos(pos) : Pos(0, 0)
  13635. this.pos = {from: pos, to: pos}
  13636. var caseFold
  13637. if (typeof options == "object") {
  13638. caseFold = options.caseFold
  13639. } else { // Backwards compat for when caseFold was the 4th argument
  13640. caseFold = options
  13641. options = null
  13642. }
  13643. if (typeof query == "string") {
  13644. if (caseFold == null) caseFold = false
  13645. this.matches = function(reverse, pos) {
  13646. return (reverse ? searchStringBackward : searchStringForward)(doc, query, pos, caseFold)
  13647. }
  13648. } else {
  13649. query = ensureFlags(query, "gm")
  13650. if (!options || options.multiline !== false)
  13651. this.matches = function(reverse, pos) {
  13652. return (reverse ? searchRegexpBackwardMultiline : searchRegexpForwardMultiline)(doc, query, pos)
  13653. }
  13654. else
  13655. this.matches = function(reverse, pos) {
  13656. return (reverse ? searchRegexpBackward : searchRegexpForward)(doc, query, pos)
  13657. }
  13658. }
  13659. }
  13660. SearchCursor.prototype = {
  13661. findNext: function() {return this.find(false)},
  13662. findPrevious: function() {return this.find(true)},
  13663. find: function(reverse) {
  13664. var result = this.matches(reverse, this.doc.clipPos(reverse ? this.pos.from : this.pos.to))
  13665. // Implements weird auto-growing behavior on null-matches for
  13666. // backwards-compatibility with the vim code (unfortunately)
  13667. while (result && CodeMirror.cmpPos(result.from, result.to) == 0) {
  13668. if (reverse) {
  13669. if (result.from.ch) result.from = Pos(result.from.line, result.from.ch - 1)
  13670. else if (result.from.line == this.doc.firstLine()) result = null
  13671. else result = this.matches(reverse, this.doc.clipPos(Pos(result.from.line - 1)))
  13672. } else {
  13673. if (result.to.ch < this.doc.getLine(result.to.line).length) result.to = Pos(result.to.line, result.to.ch + 1)
  13674. else if (result.to.line == this.doc.lastLine()) result = null
  13675. else result = this.matches(reverse, Pos(result.to.line + 1, 0))
  13676. }
  13677. }
  13678. if (result) {
  13679. this.pos = result
  13680. this.atOccurrence = true
  13681. return this.pos.match || true
  13682. } else {
  13683. var end = Pos(reverse ? this.doc.firstLine() : this.doc.lastLine() + 1, 0)
  13684. this.pos = {from: end, to: end}
  13685. return this.atOccurrence = false
  13686. }
  13687. },
  13688. from: function() {if (this.atOccurrence) return this.pos.from},
  13689. to: function() {if (this.atOccurrence) return this.pos.to},
  13690. replace: function(newText, origin) {
  13691. if (!this.atOccurrence) return
  13692. var lines = CodeMirror.splitLines(newText)
  13693. this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin)
  13694. this.pos.to = Pos(this.pos.from.line + lines.length - 1,
  13695. lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0))
  13696. }
  13697. }
  13698. CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
  13699. return new SearchCursor(this.doc, query, pos, caseFold)
  13700. })
  13701. CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
  13702. return new SearchCursor(this, query, pos, caseFold)
  13703. })
  13704. CodeMirror.defineExtension("selectMatches", function(query, caseFold) {
  13705. var ranges = []
  13706. var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold)
  13707. while (cur.findNext()) {
  13708. if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break
  13709. ranges.push({anchor: cur.from(), head: cur.to()})
  13710. }
  13711. if (ranges.length)
  13712. this.setSelections(ranges, 0)
  13713. })
  13714. });
  13715. /* ---- extension/selection/active-line.js ---- */
  13716. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  13717. // Distributed under an MIT license: https://codemirror.net/LICENSE
  13718. (function(mod) {
  13719. if (typeof exports == "object" && typeof module == "object") // CommonJS
  13720. mod(require("../../lib/codemirror"));
  13721. else if (typeof define == "function" && define.amd) // AMD
  13722. define(["../../lib/codemirror"], mod);
  13723. else // Plain browser env
  13724. mod(CodeMirror);
  13725. })(function(CodeMirror) {
  13726. "use strict";
  13727. var WRAP_CLASS = "CodeMirror-activeline";
  13728. var BACK_CLASS = "CodeMirror-activeline-background";
  13729. var GUTT_CLASS = "CodeMirror-activeline-gutter";
  13730. CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
  13731. var prev = old == CodeMirror.Init ? false : old;
  13732. if (val == prev) return
  13733. if (prev) {
  13734. cm.off("beforeSelectionChange", selectionChange);
  13735. clearActiveLines(cm);
  13736. delete cm.state.activeLines;
  13737. }
  13738. if (val) {
  13739. cm.state.activeLines = [];
  13740. updateActiveLines(cm, cm.listSelections());
  13741. cm.on("beforeSelectionChange", selectionChange);
  13742. }
  13743. });
  13744. function clearActiveLines(cm) {
  13745. for (var i = 0; i < cm.state.activeLines.length; i++) {
  13746. cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS);
  13747. cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS);
  13748. cm.removeLineClass(cm.state.activeLines[i], "gutter", GUTT_CLASS);
  13749. }
  13750. }
  13751. function sameArray(a, b) {
  13752. if (a.length != b.length) return false;
  13753. for (var i = 0; i < a.length; i++)
  13754. if (a[i] != b[i]) return false;
  13755. return true;
  13756. }
  13757. function updateActiveLines(cm, ranges) {
  13758. var active = [];
  13759. for (var i = 0; i < ranges.length; i++) {
  13760. var range = ranges[i];
  13761. var option = cm.getOption("styleActiveLine");
  13762. if (typeof option == "object" && option.nonEmpty ? range.anchor.line != range.head.line : !range.empty())
  13763. continue
  13764. var line = cm.getLineHandleVisualStart(range.head.line);
  13765. if (active[active.length - 1] != line) active.push(line);
  13766. }
  13767. if (sameArray(cm.state.activeLines, active)) return;
  13768. cm.operation(function() {
  13769. clearActiveLines(cm);
  13770. for (var i = 0; i < active.length; i++) {
  13771. cm.addLineClass(active[i], "wrap", WRAP_CLASS);
  13772. cm.addLineClass(active[i], "background", BACK_CLASS);
  13773. cm.addLineClass(active[i], "gutter", GUTT_CLASS);
  13774. }
  13775. cm.state.activeLines = active;
  13776. });
  13777. }
  13778. function selectionChange(cm, sel) {
  13779. updateActiveLines(cm, sel.ranges);
  13780. }
  13781. });
  13782. /* ---- extension/selection/mark-selection.js ---- */
  13783. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  13784. // Distributed under an MIT license: https://codemirror.net/LICENSE
  13785. // Because sometimes you need to mark the selected *text*.
  13786. //
  13787. // Adds an option 'styleSelectedText' which, when enabled, gives
  13788. // selected text the CSS class given as option value, or
  13789. // "CodeMirror-selectedtext" when the value is not a string.
  13790. (function(mod) {
  13791. if (typeof exports == "object" && typeof module == "object") // CommonJS
  13792. mod(require("../../lib/codemirror"));
  13793. else if (typeof define == "function" && define.amd) // AMD
  13794. define(["../../lib/codemirror"], mod);
  13795. else // Plain browser env
  13796. mod(CodeMirror);
  13797. })(function(CodeMirror) {
  13798. "use strict";
  13799. CodeMirror.defineOption("styleSelectedText", false, function(cm, val, old) {
  13800. var prev = old && old != CodeMirror.Init;
  13801. if (val && !prev) {
  13802. cm.state.markedSelection = [];
  13803. cm.state.markedSelectionStyle = typeof val == "string" ? val : "CodeMirror-selectedtext";
  13804. reset(cm);
  13805. cm.on("cursorActivity", onCursorActivity);
  13806. cm.on("change", onChange);
  13807. } else if (!val && prev) {
  13808. cm.off("cursorActivity", onCursorActivity);
  13809. cm.off("change", onChange);
  13810. clear(cm);
  13811. cm.state.markedSelection = cm.state.markedSelectionStyle = null;
  13812. }
  13813. });
  13814. function onCursorActivity(cm) {
  13815. if (cm.state.markedSelection)
  13816. cm.operation(function() { update(cm); });
  13817. }
  13818. function onChange(cm) {
  13819. if (cm.state.markedSelection && cm.state.markedSelection.length)
  13820. cm.operation(function() { clear(cm); });
  13821. }
  13822. var CHUNK_SIZE = 8;
  13823. var Pos = CodeMirror.Pos;
  13824. var cmp = CodeMirror.cmpPos;
  13825. function coverRange(cm, from, to, addAt) {
  13826. if (cmp(from, to) == 0) return;
  13827. var array = cm.state.markedSelection;
  13828. var cls = cm.state.markedSelectionStyle;
  13829. for (var line = from.line;;) {
  13830. var start = line == from.line ? from : Pos(line, 0);
  13831. var endLine = line + CHUNK_SIZE, atEnd = endLine >= to.line;
  13832. var end = atEnd ? to : Pos(endLine, 0);
  13833. var mark = cm.markText(start, end, {className: cls});
  13834. if (addAt == null) array.push(mark);
  13835. else array.splice(addAt++, 0, mark);
  13836. if (atEnd) break;
  13837. line = endLine;
  13838. }
  13839. }
  13840. function clear(cm) {
  13841. var array = cm.state.markedSelection;
  13842. for (var i = 0; i < array.length; ++i) array[i].clear();
  13843. array.length = 0;
  13844. }
  13845. function reset(cm) {
  13846. clear(cm);
  13847. var ranges = cm.listSelections();
  13848. for (var i = 0; i < ranges.length; i++)
  13849. coverRange(cm, ranges[i].from(), ranges[i].to());
  13850. }
  13851. function update(cm) {
  13852. if (!cm.somethingSelected()) return clear(cm);
  13853. if (cm.listSelections().length > 1) return reset(cm);
  13854. var from = cm.getCursor("start"), to = cm.getCursor("end");
  13855. var array = cm.state.markedSelection;
  13856. if (!array.length) return coverRange(cm, from, to);
  13857. var coverStart = array[0].find(), coverEnd = array[array.length - 1].find();
  13858. if (!coverStart || !coverEnd || to.line - from.line <= CHUNK_SIZE ||
  13859. cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0)
  13860. return reset(cm);
  13861. while (cmp(from, coverStart.from) > 0) {
  13862. array.shift().clear();
  13863. coverStart = array[0].find();
  13864. }
  13865. if (cmp(from, coverStart.from) < 0) {
  13866. if (coverStart.to.line - from.line < CHUNK_SIZE) {
  13867. array.shift().clear();
  13868. coverRange(cm, from, coverStart.to, 0);
  13869. } else {
  13870. coverRange(cm, from, coverStart.from, 0);
  13871. }
  13872. }
  13873. while (cmp(to, coverEnd.to) < 0) {
  13874. array.pop().clear();
  13875. coverEnd = array[array.length - 1].find();
  13876. }
  13877. if (cmp(to, coverEnd.to) > 0) {
  13878. if (to.line - coverEnd.from.line < CHUNK_SIZE) {
  13879. array.pop().clear();
  13880. coverRange(cm, coverEnd.from, to);
  13881. } else {
  13882. coverRange(cm, coverEnd.to, to);
  13883. }
  13884. }
  13885. }
  13886. });
  13887. /* ---- extension/selection/selection-pointer.js ---- */
  13888. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  13889. // Distributed under an MIT license: https://codemirror.net/LICENSE
  13890. (function(mod) {
  13891. if (typeof exports == "object" && typeof module == "object") // CommonJS
  13892. mod(require("../../lib/codemirror"));
  13893. else if (typeof define == "function" && define.amd) // AMD
  13894. define(["../../lib/codemirror"], mod);
  13895. else // Plain browser env
  13896. mod(CodeMirror);
  13897. })(function(CodeMirror) {
  13898. "use strict";
  13899. CodeMirror.defineOption("selectionPointer", false, function(cm, val) {
  13900. var data = cm.state.selectionPointer;
  13901. if (data) {
  13902. CodeMirror.off(cm.getWrapperElement(), "mousemove", data.mousemove);
  13903. CodeMirror.off(cm.getWrapperElement(), "mouseout", data.mouseout);
  13904. CodeMirror.off(window, "scroll", data.windowScroll);
  13905. cm.off("cursorActivity", reset);
  13906. cm.off("scroll", reset);
  13907. cm.state.selectionPointer = null;
  13908. cm.display.lineDiv.style.cursor = "";
  13909. }
  13910. if (val) {
  13911. data = cm.state.selectionPointer = {
  13912. value: typeof val == "string" ? val : "default",
  13913. mousemove: function(event) { mousemove(cm, event); },
  13914. mouseout: function(event) { mouseout(cm, event); },
  13915. windowScroll: function() { reset(cm); },
  13916. rects: null,
  13917. mouseX: null, mouseY: null,
  13918. willUpdate: false
  13919. };
  13920. CodeMirror.on(cm.getWrapperElement(), "mousemove", data.mousemove);
  13921. CodeMirror.on(cm.getWrapperElement(), "mouseout", data.mouseout);
  13922. CodeMirror.on(window, "scroll", data.windowScroll);
  13923. cm.on("cursorActivity", reset);
  13924. cm.on("scroll", reset);
  13925. }
  13926. });
  13927. function mousemove(cm, event) {
  13928. var data = cm.state.selectionPointer;
  13929. if (event.buttons == null ? event.which : event.buttons) {
  13930. data.mouseX = data.mouseY = null;
  13931. } else {
  13932. data.mouseX = event.clientX;
  13933. data.mouseY = event.clientY;
  13934. }
  13935. scheduleUpdate(cm);
  13936. }
  13937. function mouseout(cm, event) {
  13938. if (!cm.getWrapperElement().contains(event.relatedTarget)) {
  13939. var data = cm.state.selectionPointer;
  13940. data.mouseX = data.mouseY = null;
  13941. scheduleUpdate(cm);
  13942. }
  13943. }
  13944. function reset(cm) {
  13945. cm.state.selectionPointer.rects = null;
  13946. scheduleUpdate(cm);
  13947. }
  13948. function scheduleUpdate(cm) {
  13949. if (!cm.state.selectionPointer.willUpdate) {
  13950. cm.state.selectionPointer.willUpdate = true;
  13951. setTimeout(function() {
  13952. update(cm);
  13953. cm.state.selectionPointer.willUpdate = false;
  13954. }, 50);
  13955. }
  13956. }
  13957. function update(cm) {
  13958. var data = cm.state.selectionPointer;
  13959. if (!data) return;
  13960. if (data.rects == null && data.mouseX != null) {
  13961. data.rects = [];
  13962. if (cm.somethingSelected()) {
  13963. for (var sel = cm.display.selectionDiv.firstChild; sel; sel = sel.nextSibling)
  13964. data.rects.push(sel.getBoundingClientRect());
  13965. }
  13966. }
  13967. var inside = false;
  13968. if (data.mouseX != null) for (var i = 0; i < data.rects.length; i++) {
  13969. var rect = data.rects[i];
  13970. if (rect.left <= data.mouseX && rect.right >= data.mouseX &&
  13971. rect.top <= data.mouseY && rect.bottom >= data.mouseY)
  13972. inside = true;
  13973. }
  13974. var cursor = inside ? data.value : "";
  13975. if (cm.display.lineDiv.style.cursor != cursor)
  13976. cm.display.lineDiv.style.cursor = cursor;
  13977. }
  13978. });
  13979. /* ---- mode/coffeescript.js ---- */
  13980. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  13981. // Distributed under an MIT license: https://codemirror.net/LICENSE
  13982. /**
  13983. * Link to the project's GitHub page:
  13984. * https://github.com/pickhardt/coffeescript-codemirror-mode
  13985. */
  13986. (function(mod) {
  13987. if (typeof exports == "object" && typeof module == "object") // CommonJS
  13988. mod(require("../../lib/codemirror"));
  13989. else if (typeof define == "function" && define.amd) // AMD
  13990. define(["../../lib/codemirror"], mod);
  13991. else // Plain browser env
  13992. mod(CodeMirror);
  13993. })(function(CodeMirror) {
  13994. "use strict";
  13995. CodeMirror.defineMode("coffeescript", function(conf, parserConf) {
  13996. var ERRORCLASS = "error";
  13997. function wordRegexp(words) {
  13998. return new RegExp("^((" + words.join(")|(") + "))\\b");
  13999. }
  14000. var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/;
  14001. var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/;
  14002. var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/;
  14003. var atProp = /^@[_A-Za-z$][_A-Za-z$0-9]*/;
  14004. var wordOperators = wordRegexp(["and", "or", "not",
  14005. "is", "isnt", "in",
  14006. "instanceof", "typeof"]);
  14007. var indentKeywords = ["for", "while", "loop", "if", "unless", "else",
  14008. "switch", "try", "catch", "finally", "class"];
  14009. var commonKeywords = ["break", "by", "continue", "debugger", "delete",
  14010. "do", "in", "of", "new", "return", "then",
  14011. "this", "@", "throw", "when", "until", "extends"];
  14012. var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
  14013. indentKeywords = wordRegexp(indentKeywords);
  14014. var stringPrefixes = /^('{3}|\"{3}|['\"])/;
  14015. var regexPrefixes = /^(\/{3}|\/)/;
  14016. var commonConstants = ["Infinity", "NaN", "undefined", "null", "true", "false", "on", "off", "yes", "no"];
  14017. var constants = wordRegexp(commonConstants);
  14018. // Tokenizers
  14019. function tokenBase(stream, state) {
  14020. // Handle scope changes
  14021. if (stream.sol()) {
  14022. if (state.scope.align === null) state.scope.align = false;
  14023. var scopeOffset = state.scope.offset;
  14024. if (stream.eatSpace()) {
  14025. var lineOffset = stream.indentation();
  14026. if (lineOffset > scopeOffset && state.scope.type == "coffee") {
  14027. return "indent";
  14028. } else if (lineOffset < scopeOffset) {
  14029. return "dedent";
  14030. }
  14031. return null;
  14032. } else {
  14033. if (scopeOffset > 0) {
  14034. dedent(stream, state);
  14035. }
  14036. }
  14037. }
  14038. if (stream.eatSpace()) {
  14039. return null;
  14040. }
  14041. var ch = stream.peek();
  14042. // Handle docco title comment (single line)
  14043. if (stream.match("####")) {
  14044. stream.skipToEnd();
  14045. return "comment";
  14046. }
  14047. // Handle multi line comments
  14048. if (stream.match("###")) {
  14049. state.tokenize = longComment;
  14050. return state.tokenize(stream, state);
  14051. }
  14052. // Single line comment
  14053. if (ch === "#") {
  14054. stream.skipToEnd();
  14055. return "comment";
  14056. }
  14057. // Handle number literals
  14058. if (stream.match(/^-?[0-9\.]/, false)) {
  14059. var floatLiteral = false;
  14060. // Floats
  14061. if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
  14062. floatLiteral = true;
  14063. }
  14064. if (stream.match(/^-?\d+\.\d*/)) {
  14065. floatLiteral = true;
  14066. }
  14067. if (stream.match(/^-?\.\d+/)) {
  14068. floatLiteral = true;
  14069. }
  14070. if (floatLiteral) {
  14071. // prevent from getting extra . on 1..
  14072. if (stream.peek() == "."){
  14073. stream.backUp(1);
  14074. }
  14075. return "number";
  14076. }
  14077. // Integers
  14078. var intLiteral = false;
  14079. // Hex
  14080. if (stream.match(/^-?0x[0-9a-f]+/i)) {
  14081. intLiteral = true;
  14082. }
  14083. // Decimal
  14084. if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
  14085. intLiteral = true;
  14086. }
  14087. // Zero by itself with no other piece of number.
  14088. if (stream.match(/^-?0(?![\dx])/i)) {
  14089. intLiteral = true;
  14090. }
  14091. if (intLiteral) {
  14092. return "number";
  14093. }
  14094. }
  14095. // Handle strings
  14096. if (stream.match(stringPrefixes)) {
  14097. state.tokenize = tokenFactory(stream.current(), false, "string");
  14098. return state.tokenize(stream, state);
  14099. }
  14100. // Handle regex literals
  14101. if (stream.match(regexPrefixes)) {
  14102. if (stream.current() != "/" || stream.match(/^.*\//, false)) { // prevent highlight of division
  14103. state.tokenize = tokenFactory(stream.current(), true, "string-2");
  14104. return state.tokenize(stream, state);
  14105. } else {
  14106. stream.backUp(1);
  14107. }
  14108. }
  14109. // Handle operators and delimiters
  14110. if (stream.match(operators) || stream.match(wordOperators)) {
  14111. return "operator";
  14112. }
  14113. if (stream.match(delimiters)) {
  14114. return "punctuation";
  14115. }
  14116. if (stream.match(constants)) {
  14117. return "atom";
  14118. }
  14119. if (stream.match(atProp) || state.prop && stream.match(identifiers)) {
  14120. return "property";
  14121. }
  14122. if (stream.match(keywords)) {
  14123. return "keyword";
  14124. }
  14125. if (stream.match(identifiers)) {
  14126. return "variable";
  14127. }
  14128. // Handle non-detected items
  14129. stream.next();
  14130. return ERRORCLASS;
  14131. }
  14132. function tokenFactory(delimiter, singleline, outclass) {
  14133. return function(stream, state) {
  14134. while (!stream.eol()) {
  14135. stream.eatWhile(/[^'"\/\\]/);
  14136. if (stream.eat("\\")) {
  14137. stream.next();
  14138. if (singleline && stream.eol()) {
  14139. return outclass;
  14140. }
  14141. } else if (stream.match(delimiter)) {
  14142. state.tokenize = tokenBase;
  14143. return outclass;
  14144. } else {
  14145. stream.eat(/['"\/]/);
  14146. }
  14147. }
  14148. if (singleline) {
  14149. if (parserConf.singleLineStringErrors) {
  14150. outclass = ERRORCLASS;
  14151. } else {
  14152. state.tokenize = tokenBase;
  14153. }
  14154. }
  14155. return outclass;
  14156. };
  14157. }
  14158. function longComment(stream, state) {
  14159. while (!stream.eol()) {
  14160. stream.eatWhile(/[^#]/);
  14161. if (stream.match("###")) {
  14162. state.tokenize = tokenBase;
  14163. break;
  14164. }
  14165. stream.eatWhile("#");
  14166. }
  14167. return "comment";
  14168. }
  14169. function indent(stream, state, type) {
  14170. type = type || "coffee";
  14171. var offset = 0, align = false, alignOffset = null;
  14172. for (var scope = state.scope; scope; scope = scope.prev) {
  14173. if (scope.type === "coffee" || scope.type == "}") {
  14174. offset = scope.offset + conf.indentUnit;
  14175. break;
  14176. }
  14177. }
  14178. if (type !== "coffee") {
  14179. align = null;
  14180. alignOffset = stream.column() + stream.current().length;
  14181. } else if (state.scope.align) {
  14182. state.scope.align = false;
  14183. }
  14184. state.scope = {
  14185. offset: offset,
  14186. type: type,
  14187. prev: state.scope,
  14188. align: align,
  14189. alignOffset: alignOffset
  14190. };
  14191. }
  14192. function dedent(stream, state) {
  14193. if (!state.scope.prev) return;
  14194. if (state.scope.type === "coffee") {
  14195. var _indent = stream.indentation();
  14196. var matched = false;
  14197. for (var scope = state.scope; scope; scope = scope.prev) {
  14198. if (_indent === scope.offset) {
  14199. matched = true;
  14200. break;
  14201. }
  14202. }
  14203. if (!matched) {
  14204. return true;
  14205. }
  14206. while (state.scope.prev && state.scope.offset !== _indent) {
  14207. state.scope = state.scope.prev;
  14208. }
  14209. return false;
  14210. } else {
  14211. state.scope = state.scope.prev;
  14212. return false;
  14213. }
  14214. }
  14215. function tokenLexer(stream, state) {
  14216. var style = state.tokenize(stream, state);
  14217. var current = stream.current();
  14218. // Handle scope changes.
  14219. if (current === "return") {
  14220. state.dedent = true;
  14221. }
  14222. if (((current === "->" || current === "=>") && stream.eol())
  14223. || style === "indent") {
  14224. indent(stream, state);
  14225. }
  14226. var delimiter_index = "[({".indexOf(current);
  14227. if (delimiter_index !== -1) {
  14228. indent(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
  14229. }
  14230. if (indentKeywords.exec(current)){
  14231. indent(stream, state);
  14232. }
  14233. if (current == "then"){
  14234. dedent(stream, state);
  14235. }
  14236. if (style === "dedent") {
  14237. if (dedent(stream, state)) {
  14238. return ERRORCLASS;
  14239. }
  14240. }
  14241. delimiter_index = "])}".indexOf(current);
  14242. if (delimiter_index !== -1) {
  14243. while (state.scope.type == "coffee" && state.scope.prev)
  14244. state.scope = state.scope.prev;
  14245. if (state.scope.type == current)
  14246. state.scope = state.scope.prev;
  14247. }
  14248. if (state.dedent && stream.eol()) {
  14249. if (state.scope.type == "coffee" && state.scope.prev)
  14250. state.scope = state.scope.prev;
  14251. state.dedent = false;
  14252. }
  14253. return style;
  14254. }
  14255. var external = {
  14256. startState: function(basecolumn) {
  14257. return {
  14258. tokenize: tokenBase,
  14259. scope: {offset:basecolumn || 0, type:"coffee", prev: null, align: false},
  14260. prop: false,
  14261. dedent: 0
  14262. };
  14263. },
  14264. token: function(stream, state) {
  14265. var fillAlign = state.scope.align === null && state.scope;
  14266. if (fillAlign && stream.sol()) fillAlign.align = false;
  14267. var style = tokenLexer(stream, state);
  14268. if (style && style != "comment") {
  14269. if (fillAlign) fillAlign.align = true;
  14270. state.prop = style == "punctuation" && stream.current() == "."
  14271. }
  14272. return style;
  14273. },
  14274. indent: function(state, text) {
  14275. if (state.tokenize != tokenBase) return 0;
  14276. var scope = state.scope;
  14277. var closer = text && "])}".indexOf(text.charAt(0)) > -1;
  14278. if (closer) while (scope.type == "coffee" && scope.prev) scope = scope.prev;
  14279. var closes = closer && scope.type === text.charAt(0);
  14280. if (scope.align)
  14281. return scope.alignOffset - (closes ? 1 : 0);
  14282. else
  14283. return (closes ? scope.prev : scope).offset;
  14284. },
  14285. lineComment: "#",
  14286. fold: "indent"
  14287. };
  14288. return external;
  14289. });
  14290. // IANA registered media type
  14291. // https://www.iana.org/assignments/media-types/
  14292. CodeMirror.defineMIME("application/vnd.coffeescript", "coffeescript");
  14293. CodeMirror.defineMIME("text/x-coffeescript", "coffeescript");
  14294. CodeMirror.defineMIME("text/coffeescript", "coffeescript");
  14295. });
  14296. /* ---- mode/css.js ---- */
  14297. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  14298. // Distributed under an MIT license: https://codemirror.net/LICENSE
  14299. (function(mod) {
  14300. if (typeof exports == "object" && typeof module == "object") // CommonJS
  14301. mod(require("../../lib/codemirror"));
  14302. else if (typeof define == "function" && define.amd) // AMD
  14303. define(["../../lib/codemirror"], mod);
  14304. else // Plain browser env
  14305. mod(CodeMirror);
  14306. })(function(CodeMirror) {
  14307. "use strict";
  14308. CodeMirror.defineMode("css", function(config, parserConfig) {
  14309. var inline = parserConfig.inline
  14310. if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
  14311. var indentUnit = config.indentUnit,
  14312. tokenHooks = parserConfig.tokenHooks,
  14313. documentTypes = parserConfig.documentTypes || {},
  14314. mediaTypes = parserConfig.mediaTypes || {},
  14315. mediaFeatures = parserConfig.mediaFeatures || {},
  14316. mediaValueKeywords = parserConfig.mediaValueKeywords || {},
  14317. propertyKeywords = parserConfig.propertyKeywords || {},
  14318. nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
  14319. fontProperties = parserConfig.fontProperties || {},
  14320. counterDescriptors = parserConfig.counterDescriptors || {},
  14321. colorKeywords = parserConfig.colorKeywords || {},
  14322. valueKeywords = parserConfig.valueKeywords || {},
  14323. allowNested = parserConfig.allowNested,
  14324. lineComment = parserConfig.lineComment,
  14325. supportsAtComponent = parserConfig.supportsAtComponent === true;
  14326. var type, override;
  14327. function ret(style, tp) { type = tp; return style; }
  14328. // Tokenizers
  14329. function tokenBase(stream, state) {
  14330. var ch = stream.next();
  14331. if (tokenHooks[ch]) {
  14332. var result = tokenHooks[ch](stream, state);
  14333. if (result !== false) return result;
  14334. }
  14335. if (ch == "@") {
  14336. stream.eatWhile(/[\w\\\-]/);
  14337. return ret("def", stream.current());
  14338. } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
  14339. return ret(null, "compare");
  14340. } else if (ch == "\"" || ch == "'") {
  14341. state.tokenize = tokenString(ch);
  14342. return state.tokenize(stream, state);
  14343. } else if (ch == "#") {
  14344. stream.eatWhile(/[\w\\\-]/);
  14345. return ret("atom", "hash");
  14346. } else if (ch == "!") {
  14347. stream.match(/^\s*\w*/);
  14348. return ret("keyword", "important");
  14349. } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
  14350. stream.eatWhile(/[\w.%]/);
  14351. return ret("number", "unit");
  14352. } else if (ch === "-") {
  14353. if (/[\d.]/.test(stream.peek())) {
  14354. stream.eatWhile(/[\w.%]/);
  14355. return ret("number", "unit");
  14356. } else if (stream.match(/^-[\w\\\-]*/)) {
  14357. stream.eatWhile(/[\w\\\-]/);
  14358. if (stream.match(/^\s*:/, false))
  14359. return ret("variable-2", "variable-definition");
  14360. return ret("variable-2", "variable");
  14361. } else if (stream.match(/^\w+-/)) {
  14362. return ret("meta", "meta");
  14363. }
  14364. } else if (/[,+>*\/]/.test(ch)) {
  14365. return ret(null, "select-op");
  14366. } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
  14367. return ret("qualifier", "qualifier");
  14368. } else if (/[:;{}\[\]\(\)]/.test(ch)) {
  14369. return ret(null, ch);
  14370. } else if (stream.match(/[\w-.]+(?=\()/)) {
  14371. if (/^(url(-prefix)?|domain|regexp)$/.test(stream.current().toLowerCase())) {
  14372. state.tokenize = tokenParenthesized;
  14373. }
  14374. return ret("variable callee", "variable");
  14375. } else if (/[\w\\\-]/.test(ch)) {
  14376. stream.eatWhile(/[\w\\\-]/);
  14377. return ret("property", "word");
  14378. } else {
  14379. return ret(null, null);
  14380. }
  14381. }
  14382. function tokenString(quote) {
  14383. return function(stream, state) {
  14384. var escaped = false, ch;
  14385. while ((ch = stream.next()) != null) {
  14386. if (ch == quote && !escaped) {
  14387. if (quote == ")") stream.backUp(1);
  14388. break;
  14389. }
  14390. escaped = !escaped && ch == "\\";
  14391. }
  14392. if (ch == quote || !escaped && quote != ")") state.tokenize = null;
  14393. return ret("string", "string");
  14394. };
  14395. }
  14396. function tokenParenthesized(stream, state) {
  14397. stream.next(); // Must be '('
  14398. if (!stream.match(/\s*[\"\')]/, false))
  14399. state.tokenize = tokenString(")");
  14400. else
  14401. state.tokenize = null;
  14402. return ret(null, "(");
  14403. }
  14404. // Context management
  14405. function Context(type, indent, prev) {
  14406. this.type = type;
  14407. this.indent = indent;
  14408. this.prev = prev;
  14409. }
  14410. function pushContext(state, stream, type, indent) {
  14411. state.context = new Context(type, stream.indentation() + (indent === false ? 0 : indentUnit), state.context);
  14412. return type;
  14413. }
  14414. function popContext(state) {
  14415. if (state.context.prev)
  14416. state.context = state.context.prev;
  14417. return state.context.type;
  14418. }
  14419. function pass(type, stream, state) {
  14420. return states[state.context.type](type, stream, state);
  14421. }
  14422. function popAndPass(type, stream, state, n) {
  14423. for (var i = n || 1; i > 0; i--)
  14424. state.context = state.context.prev;
  14425. return pass(type, stream, state);
  14426. }
  14427. // Parser
  14428. function wordAsValue(stream) {
  14429. var word = stream.current().toLowerCase();
  14430. if (valueKeywords.hasOwnProperty(word))
  14431. override = "atom";
  14432. else if (colorKeywords.hasOwnProperty(word))
  14433. override = "keyword";
  14434. else
  14435. override = "variable";
  14436. }
  14437. var states = {};
  14438. states.top = function(type, stream, state) {
  14439. if (type == "{") {
  14440. return pushContext(state, stream, "block");
  14441. } else if (type == "}" && state.context.prev) {
  14442. return popContext(state);
  14443. } else if (supportsAtComponent && /@component/i.test(type)) {
  14444. return pushContext(state, stream, "atComponentBlock");
  14445. } else if (/^@(-moz-)?document$/i.test(type)) {
  14446. return pushContext(state, stream, "documentTypes");
  14447. } else if (/^@(media|supports|(-moz-)?document|import)$/i.test(type)) {
  14448. return pushContext(state, stream, "atBlock");
  14449. } else if (/^@(font-face|counter-style)/i.test(type)) {
  14450. state.stateArg = type;
  14451. return "restricted_atBlock_before";
  14452. } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/i.test(type)) {
  14453. return "keyframes";
  14454. } else if (type && type.charAt(0) == "@") {
  14455. return pushContext(state, stream, "at");
  14456. } else if (type == "hash") {
  14457. override = "builtin";
  14458. } else if (type == "word") {
  14459. override = "tag";
  14460. } else if (type == "variable-definition") {
  14461. return "maybeprop";
  14462. } else if (type == "interpolation") {
  14463. return pushContext(state, stream, "interpolation");
  14464. } else if (type == ":") {
  14465. return "pseudo";
  14466. } else if (allowNested && type == "(") {
  14467. return pushContext(state, stream, "parens");
  14468. }
  14469. return state.context.type;
  14470. };
  14471. states.block = function(type, stream, state) {
  14472. if (type == "word") {
  14473. var word = stream.current().toLowerCase();
  14474. if (propertyKeywords.hasOwnProperty(word)) {
  14475. override = "property";
  14476. return "maybeprop";
  14477. } else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
  14478. override = "string-2";
  14479. return "maybeprop";
  14480. } else if (allowNested) {
  14481. override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
  14482. return "block";
  14483. } else {
  14484. override += " error";
  14485. return "maybeprop";
  14486. }
  14487. } else if (type == "meta") {
  14488. return "block";
  14489. } else if (!allowNested && (type == "hash" || type == "qualifier")) {
  14490. override = "error";
  14491. return "block";
  14492. } else {
  14493. return states.top(type, stream, state);
  14494. }
  14495. };
  14496. states.maybeprop = function(type, stream, state) {
  14497. if (type == ":") return pushContext(state, stream, "prop");
  14498. return pass(type, stream, state);
  14499. };
  14500. states.prop = function(type, stream, state) {
  14501. if (type == ";") return popContext(state);
  14502. if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
  14503. if (type == "}" || type == "{") return popAndPass(type, stream, state);
  14504. if (type == "(") return pushContext(state, stream, "parens");
  14505. if (type == "hash" && !/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(stream.current())) {
  14506. override += " error";
  14507. } else if (type == "word") {
  14508. wordAsValue(stream);
  14509. } else if (type == "interpolation") {
  14510. return pushContext(state, stream, "interpolation");
  14511. }
  14512. return "prop";
  14513. };
  14514. states.propBlock = function(type, _stream, state) {
  14515. if (type == "}") return popContext(state);
  14516. if (type == "word") { override = "property"; return "maybeprop"; }
  14517. return state.context.type;
  14518. };
  14519. states.parens = function(type, stream, state) {
  14520. if (type == "{" || type == "}") return popAndPass(type, stream, state);
  14521. if (type == ")") return popContext(state);
  14522. if (type == "(") return pushContext(state, stream, "parens");
  14523. if (type == "interpolation") return pushContext(state, stream, "interpolation");
  14524. if (type == "word") wordAsValue(stream);
  14525. return "parens";
  14526. };
  14527. states.pseudo = function(type, stream, state) {
  14528. if (type == "meta") return "pseudo";
  14529. if (type == "word") {
  14530. override = "variable-3";
  14531. return state.context.type;
  14532. }
  14533. return pass(type, stream, state);
  14534. };
  14535. states.documentTypes = function(type, stream, state) {
  14536. if (type == "word" && documentTypes.hasOwnProperty(stream.current())) {
  14537. override = "tag";
  14538. return state.context.type;
  14539. } else {
  14540. return states.atBlock(type, stream, state);
  14541. }
  14542. };
  14543. states.atBlock = function(type, stream, state) {
  14544. if (type == "(") return pushContext(state, stream, "atBlock_parens");
  14545. if (type == "}" || type == ";") return popAndPass(type, stream, state);
  14546. if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
  14547. if (type == "interpolation") return pushContext(state, stream, "interpolation");
  14548. if (type == "word") {
  14549. var word = stream.current().toLowerCase();
  14550. if (word == "only" || word == "not" || word == "and" || word == "or")
  14551. override = "keyword";
  14552. else if (mediaTypes.hasOwnProperty(word))
  14553. override = "attribute";
  14554. else if (mediaFeatures.hasOwnProperty(word))
  14555. override = "property";
  14556. else if (mediaValueKeywords.hasOwnProperty(word))
  14557. override = "keyword";
  14558. else if (propertyKeywords.hasOwnProperty(word))
  14559. override = "property";
  14560. else if (nonStandardPropertyKeywords.hasOwnProperty(word))
  14561. override = "string-2";
  14562. else if (valueKeywords.hasOwnProperty(word))
  14563. override = "atom";
  14564. else if (colorKeywords.hasOwnProperty(word))
  14565. override = "keyword";
  14566. else
  14567. override = "error";
  14568. }
  14569. return state.context.type;
  14570. };
  14571. states.atComponentBlock = function(type, stream, state) {
  14572. if (type == "}")
  14573. return popAndPass(type, stream, state);
  14574. if (type == "{")
  14575. return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top", false);
  14576. if (type == "word")
  14577. override = "error";
  14578. return state.context.type;
  14579. };
  14580. states.atBlock_parens = function(type, stream, state) {
  14581. if (type == ")") return popContext(state);
  14582. if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
  14583. return states.atBlock(type, stream, state);
  14584. };
  14585. states.restricted_atBlock_before = function(type, stream, state) {
  14586. if (type == "{")
  14587. return pushContext(state, stream, "restricted_atBlock");
  14588. if (type == "word" && state.stateArg == "@counter-style") {
  14589. override = "variable";
  14590. return "restricted_atBlock_before";
  14591. }
  14592. return pass(type, stream, state);
  14593. };
  14594. states.restricted_atBlock = function(type, stream, state) {
  14595. if (type == "}") {
  14596. state.stateArg = null;
  14597. return popContext(state);
  14598. }
  14599. if (type == "word") {
  14600. if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) ||
  14601. (state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase())))
  14602. override = "error";
  14603. else
  14604. override = "property";
  14605. return "maybeprop";
  14606. }
  14607. return "restricted_atBlock";
  14608. };
  14609. states.keyframes = function(type, stream, state) {
  14610. if (type == "word") { override = "variable"; return "keyframes"; }
  14611. if (type == "{") return pushContext(state, stream, "top");
  14612. return pass(type, stream, state);
  14613. };
  14614. states.at = function(type, stream, state) {
  14615. if (type == ";") return popContext(state);
  14616. if (type == "{" || type == "}") return popAndPass(type, stream, state);
  14617. if (type == "word") override = "tag";
  14618. else if (type == "hash") override = "builtin";
  14619. return "at";
  14620. };
  14621. states.interpolation = function(type, stream, state) {
  14622. if (type == "}") return popContext(state);
  14623. if (type == "{" || type == ";") return popAndPass(type, stream, state);
  14624. if (type == "word") override = "variable";
  14625. else if (type != "variable" && type != "(" && type != ")") override = "error";
  14626. return "interpolation";
  14627. };
  14628. return {
  14629. startState: function(base) {
  14630. return {tokenize: null,
  14631. state: inline ? "block" : "top",
  14632. stateArg: null,
  14633. context: new Context(inline ? "block" : "top", base || 0, null)};
  14634. },
  14635. token: function(stream, state) {
  14636. if (!state.tokenize && stream.eatSpace()) return null;
  14637. var style = (state.tokenize || tokenBase)(stream, state);
  14638. if (style && typeof style == "object") {
  14639. type = style[1];
  14640. style = style[0];
  14641. }
  14642. override = style;
  14643. if (type != "comment")
  14644. state.state = states[state.state](type, stream, state);
  14645. return override;
  14646. },
  14647. indent: function(state, textAfter) {
  14648. var cx = state.context, ch = textAfter && textAfter.charAt(0);
  14649. var indent = cx.indent;
  14650. if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
  14651. if (cx.prev) {
  14652. if (ch == "}" && (cx.type == "block" || cx.type == "top" ||
  14653. cx.type == "interpolation" || cx.type == "restricted_atBlock")) {
  14654. // Resume indentation from parent context.
  14655. cx = cx.prev;
  14656. indent = cx.indent;
  14657. } else if (ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
  14658. ch == "{" && (cx.type == "at" || cx.type == "atBlock")) {
  14659. // Dedent relative to current context.
  14660. indent = Math.max(0, cx.indent - indentUnit);
  14661. }
  14662. }
  14663. return indent;
  14664. },
  14665. electricChars: "}",
  14666. blockCommentStart: "/*",
  14667. blockCommentEnd: "*/",
  14668. blockCommentContinue: " * ",
  14669. lineComment: lineComment,
  14670. fold: "brace"
  14671. };
  14672. });
  14673. function keySet(array) {
  14674. var keys = {};
  14675. for (var i = 0; i < array.length; ++i) {
  14676. keys[array[i].toLowerCase()] = true;
  14677. }
  14678. return keys;
  14679. }
  14680. var documentTypes_ = [
  14681. "domain", "regexp", "url", "url-prefix"
  14682. ], documentTypes = keySet(documentTypes_);
  14683. var mediaTypes_ = [
  14684. "all", "aural", "braille", "handheld", "print", "projection", "screen",
  14685. "tty", "tv", "embossed"
  14686. ], mediaTypes = keySet(mediaTypes_);
  14687. var mediaFeatures_ = [
  14688. "width", "min-width", "max-width", "height", "min-height", "max-height",
  14689. "device-width", "min-device-width", "max-device-width", "device-height",
  14690. "min-device-height", "max-device-height", "aspect-ratio",
  14691. "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
  14692. "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
  14693. "max-color", "color-index", "min-color-index", "max-color-index",
  14694. "monochrome", "min-monochrome", "max-monochrome", "resolution",
  14695. "min-resolution", "max-resolution", "scan", "grid", "orientation",
  14696. "device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio",
  14697. "pointer", "any-pointer", "hover", "any-hover"
  14698. ], mediaFeatures = keySet(mediaFeatures_);
  14699. var mediaValueKeywords_ = [
  14700. "landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
  14701. "interlace", "progressive"
  14702. ], mediaValueKeywords = keySet(mediaValueKeywords_);
  14703. var propertyKeywords_ = [
  14704. "align-content", "align-items", "align-self", "alignment-adjust",
  14705. "alignment-baseline", "anchor-point", "animation", "animation-delay",
  14706. "animation-direction", "animation-duration", "animation-fill-mode",
  14707. "animation-iteration-count", "animation-name", "animation-play-state",
  14708. "animation-timing-function", "appearance", "azimuth", "backdrop-filter",
  14709. "backface-visibility", "background", "background-attachment",
  14710. "background-blend-mode", "background-clip", "background-color",
  14711. "background-image", "background-origin", "background-position",
  14712. "background-position-x", "background-position-y", "background-repeat",
  14713. "background-size", "baseline-shift", "binding", "bleed", "block-size",
  14714. "bookmark-label", "bookmark-level", "bookmark-state", "bookmark-target",
  14715. "border", "border-bottom", "border-bottom-color", "border-bottom-left-radius",
  14716. "border-bottom-right-radius", "border-bottom-style", "border-bottom-width",
  14717. "border-collapse", "border-color", "border-image", "border-image-outset",
  14718. "border-image-repeat", "border-image-slice", "border-image-source",
  14719. "border-image-width", "border-left", "border-left-color", "border-left-style",
  14720. "border-left-width", "border-radius", "border-right", "border-right-color",
  14721. "border-right-style", "border-right-width", "border-spacing", "border-style",
  14722. "border-top", "border-top-color", "border-top-left-radius",
  14723. "border-top-right-radius", "border-top-style", "border-top-width",
  14724. "border-width", "bottom", "box-decoration-break", "box-shadow", "box-sizing",
  14725. "break-after", "break-before", "break-inside", "caption-side", "caret-color",
  14726. "clear", "clip", "color", "color-profile", "column-count", "column-fill",
  14727. "column-gap", "column-rule", "column-rule-color", "column-rule-style",
  14728. "column-rule-width", "column-span", "column-width", "columns", "contain",
  14729. "content", "counter-increment", "counter-reset", "crop", "cue", "cue-after",
  14730. "cue-before", "cursor", "direction", "display", "dominant-baseline",
  14731. "drop-initial-after-adjust", "drop-initial-after-align",
  14732. "drop-initial-before-adjust", "drop-initial-before-align", "drop-initial-size",
  14733. "drop-initial-value", "elevation", "empty-cells", "fit", "fit-position",
  14734. "flex", "flex-basis", "flex-direction", "flex-flow", "flex-grow",
  14735. "flex-shrink", "flex-wrap", "float", "float-offset", "flow-from", "flow-into",
  14736. "font", "font-family", "font-feature-settings", "font-kerning",
  14737. "font-language-override", "font-optical-sizing", "font-size",
  14738. "font-size-adjust", "font-stretch", "font-style", "font-synthesis",
  14739. "font-variant", "font-variant-alternates", "font-variant-caps",
  14740. "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric",
  14741. "font-variant-position", "font-variation-settings", "font-weight", "gap",
  14742. "grid", "grid-area", "grid-auto-columns", "grid-auto-flow", "grid-auto-rows",
  14743. "grid-column", "grid-column-end", "grid-column-gap", "grid-column-start",
  14744. "grid-gap", "grid-row", "grid-row-end", "grid-row-gap", "grid-row-start",
  14745. "grid-template", "grid-template-areas", "grid-template-columns",
  14746. "grid-template-rows", "hanging-punctuation", "height", "hyphens", "icon",
  14747. "image-orientation", "image-rendering", "image-resolution", "inline-box-align",
  14748. "inset", "inset-block", "inset-block-end", "inset-block-start", "inset-inline",
  14749. "inset-inline-end", "inset-inline-start", "isolation", "justify-content",
  14750. "justify-items", "justify-self", "left", "letter-spacing", "line-break",
  14751. "line-height", "line-height-step", "line-stacking", "line-stacking-ruby",
  14752. "line-stacking-shift", "line-stacking-strategy", "list-style",
  14753. "list-style-image", "list-style-position", "list-style-type", "margin",
  14754. "margin-bottom", "margin-left", "margin-right", "margin-top", "marks",
  14755. "marquee-direction", "marquee-loop", "marquee-play-count", "marquee-speed",
  14756. "marquee-style", "max-block-size", "max-height", "max-inline-size",
  14757. "max-width", "min-block-size", "min-height", "min-inline-size", "min-width",
  14758. "mix-blend-mode", "move-to", "nav-down", "nav-index", "nav-left", "nav-right",
  14759. "nav-up", "object-fit", "object-position", "offset", "offset-anchor",
  14760. "offset-distance", "offset-path", "offset-position", "offset-rotate",
  14761. "opacity", "order", "orphans", "outline", "outline-color", "outline-offset",
  14762. "outline-style", "outline-width", "overflow", "overflow-style",
  14763. "overflow-wrap", "overflow-x", "overflow-y", "padding", "padding-bottom",
  14764. "padding-left", "padding-right", "padding-top", "page", "page-break-after",
  14765. "page-break-before", "page-break-inside", "page-policy", "pause",
  14766. "pause-after", "pause-before", "perspective", "perspective-origin", "pitch",
  14767. "pitch-range", "place-content", "place-items", "place-self", "play-during",
  14768. "position", "presentation-level", "punctuation-trim", "quotes",
  14769. "region-break-after", "region-break-before", "region-break-inside",
  14770. "region-fragment", "rendering-intent", "resize", "rest", "rest-after",
  14771. "rest-before", "richness", "right", "rotate", "rotation", "rotation-point",
  14772. "row-gap", "ruby-align", "ruby-overhang", "ruby-position", "ruby-span",
  14773. "scale", "scroll-behavior", "scroll-margin", "scroll-margin-block",
  14774. "scroll-margin-block-end", "scroll-margin-block-start", "scroll-margin-bottom",
  14775. "scroll-margin-inline", "scroll-margin-inline-end",
  14776. "scroll-margin-inline-start", "scroll-margin-left", "scroll-margin-right",
  14777. "scroll-margin-top", "scroll-padding", "scroll-padding-block",
  14778. "scroll-padding-block-end", "scroll-padding-block-start",
  14779. "scroll-padding-bottom", "scroll-padding-inline", "scroll-padding-inline-end",
  14780. "scroll-padding-inline-start", "scroll-padding-left", "scroll-padding-right",
  14781. "scroll-padding-top", "scroll-snap-align", "scroll-snap-type",
  14782. "shape-image-threshold", "shape-inside", "shape-margin", "shape-outside",
  14783. "size", "speak", "speak-as", "speak-header", "speak-numeral",
  14784. "speak-punctuation", "speech-rate", "stress", "string-set", "tab-size",
  14785. "table-layout", "target", "target-name", "target-new", "target-position",
  14786. "text-align", "text-align-last", "text-combine-upright", "text-decoration",
  14787. "text-decoration-color", "text-decoration-line", "text-decoration-skip",
  14788. "text-decoration-skip-ink", "text-decoration-style", "text-emphasis",
  14789. "text-emphasis-color", "text-emphasis-position", "text-emphasis-style",
  14790. "text-height", "text-indent", "text-justify", "text-orientation",
  14791. "text-outline", "text-overflow", "text-rendering", "text-shadow",
  14792. "text-size-adjust", "text-space-collapse", "text-transform",
  14793. "text-underline-position", "text-wrap", "top", "transform", "transform-origin",
  14794. "transform-style", "transition", "transition-delay", "transition-duration",
  14795. "transition-property", "transition-timing-function", "translate",
  14796. "unicode-bidi", "user-select", "vertical-align", "visibility", "voice-balance",
  14797. "voice-duration", "voice-family", "voice-pitch", "voice-range", "voice-rate",
  14798. "voice-stress", "voice-volume", "volume", "white-space", "widows", "width",
  14799. "will-change", "word-break", "word-spacing", "word-wrap", "writing-mode", "z-index",
  14800. // SVG-specific
  14801. "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
  14802. "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
  14803. "color-interpolation", "color-interpolation-filters",
  14804. "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
  14805. "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
  14806. "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
  14807. "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
  14808. "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
  14809. "glyph-orientation-vertical", "text-anchor", "writing-mode"
  14810. ], propertyKeywords = keySet(propertyKeywords_);
  14811. var nonStandardPropertyKeywords_ = [
  14812. "border-block", "border-block-color", "border-block-end",
  14813. "border-block-end-color", "border-block-end-style", "border-block-end-width",
  14814. "border-block-start", "border-block-start-color", "border-block-start-style",
  14815. "border-block-start-width", "border-block-style", "border-block-width",
  14816. "border-inline", "border-inline-color", "border-inline-end",
  14817. "border-inline-end-color", "border-inline-end-style",
  14818. "border-inline-end-width", "border-inline-start", "border-inline-start-color",
  14819. "border-inline-start-style", "border-inline-start-width",
  14820. "border-inline-style", "border-inline-width", "margin-block",
  14821. "margin-block-end", "margin-block-start", "margin-inline", "margin-inline-end",
  14822. "margin-inline-start", "padding-block", "padding-block-end",
  14823. "padding-block-start", "padding-inline", "padding-inline-end",
  14824. "padding-inline-start", "scroll-snap-stop", "scrollbar-3d-light-color",
  14825. "scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
  14826. "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
  14827. "scrollbar-track-color", "searchfield-cancel-button", "searchfield-decoration",
  14828. "searchfield-results-button", "searchfield-results-decoration", "shape-inside", "zoom"
  14829. ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
  14830. var fontProperties_ = [
  14831. "font-display", "font-family", "src", "unicode-range", "font-variant",
  14832. "font-feature-settings", "font-stretch", "font-weight", "font-style"
  14833. ], fontProperties = keySet(fontProperties_);
  14834. var counterDescriptors_ = [
  14835. "additive-symbols", "fallback", "negative", "pad", "prefix", "range",
  14836. "speak-as", "suffix", "symbols", "system"
  14837. ], counterDescriptors = keySet(counterDescriptors_);
  14838. var colorKeywords_ = [
  14839. "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
  14840. "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
  14841. "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
  14842. "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
  14843. "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
  14844. "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
  14845. "darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
  14846. "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
  14847. "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
  14848. "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
  14849. "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
  14850. "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
  14851. "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
  14852. "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
  14853. "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
  14854. "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
  14855. "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
  14856. "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
  14857. "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
  14858. "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
  14859. "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
  14860. "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
  14861. "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
  14862. "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
  14863. "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
  14864. "whitesmoke", "yellow", "yellowgreen"
  14865. ], colorKeywords = keySet(colorKeywords_);
  14866. var valueKeywords_ = [
  14867. "above", "absolute", "activeborder", "additive", "activecaption", "afar",
  14868. "after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
  14869. "always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
  14870. "arabic-indic", "armenian", "asterisks", "attr", "auto", "auto-flow", "avoid", "avoid-column", "avoid-page",
  14871. "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
  14872. "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
  14873. "both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel",
  14874. "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
  14875. "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
  14876. "cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
  14877. "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
  14878. "col-resize", "collapse", "color", "color-burn", "color-dodge", "column", "column-reverse",
  14879. "compact", "condensed", "contain", "content", "contents",
  14880. "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
  14881. "cross", "crosshair", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal",
  14882. "decimal-leading-zero", "default", "default-button", "dense", "destination-atop",
  14883. "destination-in", "destination-out", "destination-over", "devanagari", "difference",
  14884. "disc", "discard", "disclosure-closed", "disclosure-open", "document",
  14885. "dot-dash", "dot-dot-dash",
  14886. "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
  14887. "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
  14888. "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
  14889. "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
  14890. "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
  14891. "ethiopic-halehame-gez", "ethiopic-halehame-om-et",
  14892. "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
  14893. "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
  14894. "ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed",
  14895. "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
  14896. "forwards", "from", "geometricPrecision", "georgian", "graytext", "grid", "groove",
  14897. "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew",
  14898. "help", "hidden", "hide", "higher", "highlight", "highlighttext",
  14899. "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "icon", "ignore",
  14900. "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
  14901. "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
  14902. "inline-block", "inline-flex", "inline-grid", "inline-table", "inset", "inside", "intrinsic", "invert",
  14903. "italic", "japanese-formal", "japanese-informal", "justify", "kannada",
  14904. "katakana", "katakana-iroha", "keep-all", "khmer",
  14905. "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
  14906. "landscape", "lao", "large", "larger", "left", "level", "lighter", "lighten",
  14907. "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
  14908. "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
  14909. "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
  14910. "lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "match", "matrix", "matrix3d",
  14911. "media-controls-background", "media-current-time-display",
  14912. "media-fullscreen-button", "media-mute-button", "media-play-button",
  14913. "media-return-to-realtime-button", "media-rewind-button",
  14914. "media-seek-back-button", "media-seek-forward-button", "media-slider",
  14915. "media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
  14916. "media-volume-slider-container", "media-volume-sliderthumb", "medium",
  14917. "menu", "menulist", "menulist-button", "menulist-text",
  14918. "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
  14919. "mix", "mongolian", "monospace", "move", "multiple", "multiply", "myanmar", "n-resize",
  14920. "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
  14921. "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
  14922. "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "opacity", "open-quote",
  14923. "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
  14924. "outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
  14925. "painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter",
  14926. "pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
  14927. "progress", "push-button", "radial-gradient", "radio", "read-only",
  14928. "read-write", "read-write-plaintext-only", "rectangle", "region",
  14929. "relative", "repeat", "repeating-linear-gradient",
  14930. "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse",
  14931. "rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
  14932. "rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running",
  14933. "s-resize", "sans-serif", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen",
  14934. "scroll", "scrollbar", "scroll-position", "se-resize", "searchfield",
  14935. "searchfield-cancel-button", "searchfield-decoration",
  14936. "searchfield-results-button", "searchfield-results-decoration", "self-start", "self-end",
  14937. "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
  14938. "simp-chinese-formal", "simp-chinese-informal", "single",
  14939. "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
  14940. "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
  14941. "small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali",
  14942. "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "space-evenly", "spell-out", "square",
  14943. "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
  14944. "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "system-ui", "table",
  14945. "table-caption", "table-cell", "table-column", "table-column-group",
  14946. "table-footer-group", "table-header-group", "table-row", "table-row-group",
  14947. "tamil",
  14948. "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
  14949. "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
  14950. "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
  14951. "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
  14952. "trad-chinese-formal", "trad-chinese-informal", "transform",
  14953. "translate", "translate3d", "translateX", "translateY", "translateZ",
  14954. "transparent", "ultra-condensed", "ultra-expanded", "underline", "unset", "up",
  14955. "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
  14956. "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
  14957. "var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
  14958. "visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
  14959. "window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor",
  14960. "xx-large", "xx-small"
  14961. ], valueKeywords = keySet(valueKeywords_);
  14962. var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(mediaValueKeywords_)
  14963. .concat(propertyKeywords_).concat(nonStandardPropertyKeywords_).concat(colorKeywords_)
  14964. .concat(valueKeywords_);
  14965. CodeMirror.registerHelper("hintWords", "css", allWords);
  14966. function tokenCComment(stream, state) {
  14967. var maybeEnd = false, ch;
  14968. while ((ch = stream.next()) != null) {
  14969. if (maybeEnd && ch == "/") {
  14970. state.tokenize = null;
  14971. break;
  14972. }
  14973. maybeEnd = (ch == "*");
  14974. }
  14975. return ["comment", "comment"];
  14976. }
  14977. CodeMirror.defineMIME("text/css", {
  14978. documentTypes: documentTypes,
  14979. mediaTypes: mediaTypes,
  14980. mediaFeatures: mediaFeatures,
  14981. mediaValueKeywords: mediaValueKeywords,
  14982. propertyKeywords: propertyKeywords,
  14983. nonStandardPropertyKeywords: nonStandardPropertyKeywords,
  14984. fontProperties: fontProperties,
  14985. counterDescriptors: counterDescriptors,
  14986. colorKeywords: colorKeywords,
  14987. valueKeywords: valueKeywords,
  14988. tokenHooks: {
  14989. "/": function(stream, state) {
  14990. if (!stream.eat("*")) return false;
  14991. state.tokenize = tokenCComment;
  14992. return tokenCComment(stream, state);
  14993. }
  14994. },
  14995. name: "css"
  14996. });
  14997. CodeMirror.defineMIME("text/x-scss", {
  14998. mediaTypes: mediaTypes,
  14999. mediaFeatures: mediaFeatures,
  15000. mediaValueKeywords: mediaValueKeywords,
  15001. propertyKeywords: propertyKeywords,
  15002. nonStandardPropertyKeywords: nonStandardPropertyKeywords,
  15003. colorKeywords: colorKeywords,
  15004. valueKeywords: valueKeywords,
  15005. fontProperties: fontProperties,
  15006. allowNested: true,
  15007. lineComment: "//",
  15008. tokenHooks: {
  15009. "/": function(stream, state) {
  15010. if (stream.eat("/")) {
  15011. stream.skipToEnd();
  15012. return ["comment", "comment"];
  15013. } else if (stream.eat("*")) {
  15014. state.tokenize = tokenCComment;
  15015. return tokenCComment(stream, state);
  15016. } else {
  15017. return ["operator", "operator"];
  15018. }
  15019. },
  15020. ":": function(stream) {
  15021. if (stream.match(/\s*\{/, false))
  15022. return [null, null]
  15023. return false;
  15024. },
  15025. "$": function(stream) {
  15026. stream.match(/^[\w-]+/);
  15027. if (stream.match(/^\s*:/, false))
  15028. return ["variable-2", "variable-definition"];
  15029. return ["variable-2", "variable"];
  15030. },
  15031. "#": function(stream) {
  15032. if (!stream.eat("{")) return false;
  15033. return [null, "interpolation"];
  15034. }
  15035. },
  15036. name: "css",
  15037. helperType: "scss"
  15038. });
  15039. CodeMirror.defineMIME("text/x-less", {
  15040. mediaTypes: mediaTypes,
  15041. mediaFeatures: mediaFeatures,
  15042. mediaValueKeywords: mediaValueKeywords,
  15043. propertyKeywords: propertyKeywords,
  15044. nonStandardPropertyKeywords: nonStandardPropertyKeywords,
  15045. colorKeywords: colorKeywords,
  15046. valueKeywords: valueKeywords,
  15047. fontProperties: fontProperties,
  15048. allowNested: true,
  15049. lineComment: "//",
  15050. tokenHooks: {
  15051. "/": function(stream, state) {
  15052. if (stream.eat("/")) {
  15053. stream.skipToEnd();
  15054. return ["comment", "comment"];
  15055. } else if (stream.eat("*")) {
  15056. state.tokenize = tokenCComment;
  15057. return tokenCComment(stream, state);
  15058. } else {
  15059. return ["operator", "operator"];
  15060. }
  15061. },
  15062. "@": function(stream) {
  15063. if (stream.eat("{")) return [null, "interpolation"];
  15064. if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/i, false)) return false;
  15065. stream.eatWhile(/[\w\\\-]/);
  15066. if (stream.match(/^\s*:/, false))
  15067. return ["variable-2", "variable-definition"];
  15068. return ["variable-2", "variable"];
  15069. },
  15070. "&": function() {
  15071. return ["atom", "atom"];
  15072. }
  15073. },
  15074. name: "css",
  15075. helperType: "less"
  15076. });
  15077. CodeMirror.defineMIME("text/x-gss", {
  15078. documentTypes: documentTypes,
  15079. mediaTypes: mediaTypes,
  15080. mediaFeatures: mediaFeatures,
  15081. propertyKeywords: propertyKeywords,
  15082. nonStandardPropertyKeywords: nonStandardPropertyKeywords,
  15083. fontProperties: fontProperties,
  15084. counterDescriptors: counterDescriptors,
  15085. colorKeywords: colorKeywords,
  15086. valueKeywords: valueKeywords,
  15087. supportsAtComponent: true,
  15088. tokenHooks: {
  15089. "/": function(stream, state) {
  15090. if (!stream.eat("*")) return false;
  15091. state.tokenize = tokenCComment;
  15092. return tokenCComment(stream, state);
  15093. }
  15094. },
  15095. name: "css",
  15096. helperType: "gss"
  15097. });
  15098. });
  15099. /* ---- mode/go.js ---- */
  15100. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  15101. // Distributed under an MIT license: https://codemirror.net/LICENSE
  15102. (function(mod) {
  15103. if (typeof exports == "object" && typeof module == "object") // CommonJS
  15104. mod(require("../../lib/codemirror"));
  15105. else if (typeof define == "function" && define.amd) // AMD
  15106. define(["../../lib/codemirror"], mod);
  15107. else // Plain browser env
  15108. mod(CodeMirror);
  15109. })(function(CodeMirror) {
  15110. "use strict";
  15111. CodeMirror.defineMode("go", function(config) {
  15112. var indentUnit = config.indentUnit;
  15113. var keywords = {
  15114. "break":true, "case":true, "chan":true, "const":true, "continue":true,
  15115. "default":true, "defer":true, "else":true, "fallthrough":true, "for":true,
  15116. "func":true, "go":true, "goto":true, "if":true, "import":true,
  15117. "interface":true, "map":true, "package":true, "range":true, "return":true,
  15118. "select":true, "struct":true, "switch":true, "type":true, "var":true,
  15119. "bool":true, "byte":true, "complex64":true, "complex128":true,
  15120. "float32":true, "float64":true, "int8":true, "int16":true, "int32":true,
  15121. "int64":true, "string":true, "uint8":true, "uint16":true, "uint32":true,
  15122. "uint64":true, "int":true, "uint":true, "uintptr":true, "error": true,
  15123. "rune":true
  15124. };
  15125. var atoms = {
  15126. "true":true, "false":true, "iota":true, "nil":true, "append":true,
  15127. "cap":true, "close":true, "complex":true, "copy":true, "delete":true, "imag":true,
  15128. "len":true, "make":true, "new":true, "panic":true, "print":true,
  15129. "println":true, "real":true, "recover":true
  15130. };
  15131. var isOperatorChar = /[+\-*&^%:=<>!|\/]/;
  15132. var curPunc;
  15133. function tokenBase(stream, state) {
  15134. var ch = stream.next();
  15135. if (ch == '"' || ch == "'" || ch == "`") {
  15136. state.tokenize = tokenString(ch);
  15137. return state.tokenize(stream, state);
  15138. }
  15139. if (/[\d\.]/.test(ch)) {
  15140. if (ch == ".") {
  15141. stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/);
  15142. } else if (ch == "0") {
  15143. stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/);
  15144. } else {
  15145. stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/);
  15146. }
  15147. return "number";
  15148. }
  15149. if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
  15150. curPunc = ch;
  15151. return null;
  15152. }
  15153. if (ch == "/") {
  15154. if (stream.eat("*")) {
  15155. state.tokenize = tokenComment;
  15156. return tokenComment(stream, state);
  15157. }
  15158. if (stream.eat("/")) {
  15159. stream.skipToEnd();
  15160. return "comment";
  15161. }
  15162. }
  15163. if (isOperatorChar.test(ch)) {
  15164. stream.eatWhile(isOperatorChar);
  15165. return "operator";
  15166. }
  15167. stream.eatWhile(/[\w\$_\xa1-\uffff]/);
  15168. var cur = stream.current();
  15169. if (keywords.propertyIsEnumerable(cur)) {
  15170. if (cur == "case" || cur == "default") curPunc = "case";
  15171. return "keyword";
  15172. }
  15173. if (atoms.propertyIsEnumerable(cur)) return "atom";
  15174. return "variable";
  15175. }
  15176. function tokenString(quote) {
  15177. return function(stream, state) {
  15178. var escaped = false, next, end = false;
  15179. while ((next = stream.next()) != null) {
  15180. if (next == quote && !escaped) {end = true; break;}
  15181. escaped = !escaped && quote != "`" && next == "\\";
  15182. }
  15183. if (end || !(escaped || quote == "`"))
  15184. state.tokenize = tokenBase;
  15185. return "string";
  15186. };
  15187. }
  15188. function tokenComment(stream, state) {
  15189. var maybeEnd = false, ch;
  15190. while (ch = stream.next()) {
  15191. if (ch == "/" && maybeEnd) {
  15192. state.tokenize = tokenBase;
  15193. break;
  15194. }
  15195. maybeEnd = (ch == "*");
  15196. }
  15197. return "comment";
  15198. }
  15199. function Context(indented, column, type, align, prev) {
  15200. this.indented = indented;
  15201. this.column = column;
  15202. this.type = type;
  15203. this.align = align;
  15204. this.prev = prev;
  15205. }
  15206. function pushContext(state, col, type) {
  15207. return state.context = new Context(state.indented, col, type, null, state.context);
  15208. }
  15209. function popContext(state) {
  15210. if (!state.context.prev) return;
  15211. var t = state.context.type;
  15212. if (t == ")" || t == "]" || t == "}")
  15213. state.indented = state.context.indented;
  15214. return state.context = state.context.prev;
  15215. }
  15216. // Interface
  15217. return {
  15218. startState: function(basecolumn) {
  15219. return {
  15220. tokenize: null,
  15221. context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
  15222. indented: 0,
  15223. startOfLine: true
  15224. };
  15225. },
  15226. token: function(stream, state) {
  15227. var ctx = state.context;
  15228. if (stream.sol()) {
  15229. if (ctx.align == null) ctx.align = false;
  15230. state.indented = stream.indentation();
  15231. state.startOfLine = true;
  15232. if (ctx.type == "case") ctx.type = "}";
  15233. }
  15234. if (stream.eatSpace()) return null;
  15235. curPunc = null;
  15236. var style = (state.tokenize || tokenBase)(stream, state);
  15237. if (style == "comment") return style;
  15238. if (ctx.align == null) ctx.align = true;
  15239. if (curPunc == "{") pushContext(state, stream.column(), "}");
  15240. else if (curPunc == "[") pushContext(state, stream.column(), "]");
  15241. else if (curPunc == "(") pushContext(state, stream.column(), ")");
  15242. else if (curPunc == "case") ctx.type = "case";
  15243. else if (curPunc == "}" && ctx.type == "}") popContext(state);
  15244. else if (curPunc == ctx.type) popContext(state);
  15245. state.startOfLine = false;
  15246. return style;
  15247. },
  15248. indent: function(state, textAfter) {
  15249. if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
  15250. var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
  15251. if (ctx.type == "case" && /^(?:case|default)\b/.test(textAfter)) {
  15252. state.context.type = "}";
  15253. return ctx.indented;
  15254. }
  15255. var closing = firstChar == ctx.type;
  15256. if (ctx.align) return ctx.column + (closing ? 0 : 1);
  15257. else return ctx.indented + (closing ? 0 : indentUnit);
  15258. },
  15259. electricChars: "{}):",
  15260. closeBrackets: "()[]{}''\"\"``",
  15261. fold: "brace",
  15262. blockCommentStart: "/*",
  15263. blockCommentEnd: "*/",
  15264. lineComment: "//"
  15265. };
  15266. });
  15267. CodeMirror.defineMIME("text/x-go", "go");
  15268. });
  15269. /* ---- mode/htmlembedded.js ---- */
  15270. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  15271. // Distributed under an MIT license: https://codemirror.net/LICENSE
  15272. (function(mod) {
  15273. if (typeof exports == "object" && typeof module == "object") // CommonJS
  15274. mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"),
  15275. require("../../addon/mode/multiplex"));
  15276. else if (typeof define == "function" && define.amd) // AMD
  15277. define(["../../lib/codemirror", "../htmlmixed/htmlmixed",
  15278. "../../addon/mode/multiplex"], mod);
  15279. else // Plain browser env
  15280. mod(CodeMirror);
  15281. })(function(CodeMirror) {
  15282. "use strict";
  15283. CodeMirror.defineMode("htmlembedded", function(config, parserConfig) {
  15284. var closeComment = parserConfig.closeComment || "--%>"
  15285. return CodeMirror.multiplexingMode(CodeMirror.getMode(config, "htmlmixed"), {
  15286. open: parserConfig.openComment || "<%--",
  15287. close: closeComment,
  15288. delimStyle: "comment",
  15289. mode: {token: function(stream) {
  15290. stream.skipTo(closeComment) || stream.skipToEnd()
  15291. return "comment"
  15292. }}
  15293. }, {
  15294. open: parserConfig.open || parserConfig.scriptStartRegex || "<%",
  15295. close: parserConfig.close || parserConfig.scriptEndRegex || "%>",
  15296. mode: CodeMirror.getMode(config, parserConfig.scriptingModeSpec)
  15297. });
  15298. }, "htmlmixed");
  15299. CodeMirror.defineMIME("application/x-ejs", {name: "htmlembedded", scriptingModeSpec:"javascript"});
  15300. CodeMirror.defineMIME("application/x-aspx", {name: "htmlembedded", scriptingModeSpec:"text/x-csharp"});
  15301. CodeMirror.defineMIME("application/x-jsp", {name: "htmlembedded", scriptingModeSpec:"text/x-java"});
  15302. CodeMirror.defineMIME("application/x-erb", {name: "htmlembedded", scriptingModeSpec:"ruby"});
  15303. });
  15304. /* ---- mode/htmlmixed.js ---- */
  15305. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  15306. // Distributed under an MIT license: https://codemirror.net/LICENSE
  15307. (function(mod) {
  15308. if (typeof exports == "object" && typeof module == "object") // CommonJS
  15309. mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
  15310. else if (typeof define == "function" && define.amd) // AMD
  15311. define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod);
  15312. else // Plain browser env
  15313. mod(CodeMirror);
  15314. })(function(CodeMirror) {
  15315. "use strict";
  15316. var defaultTags = {
  15317. script: [
  15318. ["lang", /(javascript|babel)/i, "javascript"],
  15319. ["type", /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i, "javascript"],
  15320. ["type", /./, "text/plain"],
  15321. [null, null, "javascript"]
  15322. ],
  15323. style: [
  15324. ["lang", /^css$/i, "css"],
  15325. ["type", /^(text\/)?(x-)?(stylesheet|css)$/i, "css"],
  15326. ["type", /./, "text/plain"],
  15327. [null, null, "css"]
  15328. ]
  15329. };
  15330. function maybeBackup(stream, pat, style) {
  15331. var cur = stream.current(), close = cur.search(pat);
  15332. if (close > -1) {
  15333. stream.backUp(cur.length - close);
  15334. } else if (cur.match(/<\/?$/)) {
  15335. stream.backUp(cur.length);
  15336. if (!stream.match(pat, false)) stream.match(cur);
  15337. }
  15338. return style;
  15339. }
  15340. var attrRegexpCache = {};
  15341. function getAttrRegexp(attr) {
  15342. var regexp = attrRegexpCache[attr];
  15343. if (regexp) return regexp;
  15344. return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*");
  15345. }
  15346. function getAttrValue(text, attr) {
  15347. var match = text.match(getAttrRegexp(attr))
  15348. return match ? /^\s*(.*?)\s*$/.exec(match[2])[1] : ""
  15349. }
  15350. function getTagRegexp(tagName, anchored) {
  15351. return new RegExp((anchored ? "^" : "") + "<\/\s*" + tagName + "\s*>", "i");
  15352. }
  15353. function addTags(from, to) {
  15354. for (var tag in from) {
  15355. var dest = to[tag] || (to[tag] = []);
  15356. var source = from[tag];
  15357. for (var i = source.length - 1; i >= 0; i--)
  15358. dest.unshift(source[i])
  15359. }
  15360. }
  15361. function findMatchingMode(tagInfo, tagText) {
  15362. for (var i = 0; i < tagInfo.length; i++) {
  15363. var spec = tagInfo[i];
  15364. if (!spec[0] || spec[1].test(getAttrValue(tagText, spec[0]))) return spec[2];
  15365. }
  15366. }
  15367. CodeMirror.defineMode("htmlmixed", function (config, parserConfig) {
  15368. var htmlMode = CodeMirror.getMode(config, {
  15369. name: "xml",
  15370. htmlMode: true,
  15371. multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
  15372. multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag
  15373. });
  15374. var tags = {};
  15375. var configTags = parserConfig && parserConfig.tags, configScript = parserConfig && parserConfig.scriptTypes;
  15376. addTags(defaultTags, tags);
  15377. if (configTags) addTags(configTags, tags);
  15378. if (configScript) for (var i = configScript.length - 1; i >= 0; i--)
  15379. tags.script.unshift(["type", configScript[i].matches, configScript[i].mode])
  15380. function html(stream, state) {
  15381. var style = htmlMode.token(stream, state.htmlState), tag = /\btag\b/.test(style), tagName
  15382. if (tag && !/[<>\s\/]/.test(stream.current()) &&
  15383. (tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase()) &&
  15384. tags.hasOwnProperty(tagName)) {
  15385. state.inTag = tagName + " "
  15386. } else if (state.inTag && tag && />$/.test(stream.current())) {
  15387. var inTag = /^([\S]+) (.*)/.exec(state.inTag)
  15388. state.inTag = null
  15389. var modeSpec = stream.current() == ">" && findMatchingMode(tags[inTag[1]], inTag[2])
  15390. var mode = CodeMirror.getMode(config, modeSpec)
  15391. var endTagA = getTagRegexp(inTag[1], true), endTag = getTagRegexp(inTag[1], false);
  15392. state.token = function (stream, state) {
  15393. if (stream.match(endTagA, false)) {
  15394. state.token = html;
  15395. state.localState = state.localMode = null;
  15396. return null;
  15397. }
  15398. return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState));
  15399. };
  15400. state.localMode = mode;
  15401. state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, "", ""));
  15402. } else if (state.inTag) {
  15403. state.inTag += stream.current()
  15404. if (stream.eol()) state.inTag += " "
  15405. }
  15406. return style;
  15407. };
  15408. return {
  15409. startState: function () {
  15410. var state = CodeMirror.startState(htmlMode);
  15411. return {token: html, inTag: null, localMode: null, localState: null, htmlState: state};
  15412. },
  15413. copyState: function (state) {
  15414. var local;
  15415. if (state.localState) {
  15416. local = CodeMirror.copyState(state.localMode, state.localState);
  15417. }
  15418. return {token: state.token, inTag: state.inTag,
  15419. localMode: state.localMode, localState: local,
  15420. htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
  15421. },
  15422. token: function (stream, state) {
  15423. return state.token(stream, state);
  15424. },
  15425. indent: function (state, textAfter, line) {
  15426. if (!state.localMode || /^\s*<\//.test(textAfter))
  15427. return htmlMode.indent(state.htmlState, textAfter, line);
  15428. else if (state.localMode.indent)
  15429. return state.localMode.indent(state.localState, textAfter, line);
  15430. else
  15431. return CodeMirror.Pass;
  15432. },
  15433. innerMode: function (state) {
  15434. return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
  15435. }
  15436. };
  15437. }, "xml", "javascript", "css");
  15438. CodeMirror.defineMIME("text/html", "htmlmixed");
  15439. });
  15440. /* ---- mode/javascript.js ---- */
  15441. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  15442. // Distributed under an MIT license: https://codemirror.net/LICENSE
  15443. (function(mod) {
  15444. if (typeof exports == "object" && typeof module == "object") // CommonJS
  15445. mod(require("../../lib/codemirror"));
  15446. else if (typeof define == "function" && define.amd) // AMD
  15447. define(["../../lib/codemirror"], mod);
  15448. else // Plain browser env
  15449. mod(CodeMirror);
  15450. })(function(CodeMirror) {
  15451. "use strict";
  15452. CodeMirror.defineMode("javascript", function(config, parserConfig) {
  15453. var indentUnit = config.indentUnit;
  15454. var statementIndent = parserConfig.statementIndent;
  15455. var jsonldMode = parserConfig.jsonld;
  15456. var jsonMode = parserConfig.json || jsonldMode;
  15457. var isTS = parserConfig.typescript;
  15458. var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
  15459. // Tokenizer
  15460. var keywords = function(){
  15461. function kw(type) {return {type: type, style: "keyword"};}
  15462. var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"), D = kw("keyword d");
  15463. var operator = kw("operator"), atom = {type: "atom", style: "atom"};
  15464. return {
  15465. "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
  15466. "return": D, "break": D, "continue": D, "new": kw("new"), "delete": C, "void": C, "throw": C,
  15467. "debugger": kw("debugger"), "var": kw("var"), "const": kw("var"), "let": kw("var"),
  15468. "function": kw("function"), "catch": kw("catch"),
  15469. "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
  15470. "in": operator, "typeof": operator, "instanceof": operator,
  15471. "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
  15472. "this": kw("this"), "class": kw("class"), "super": kw("atom"),
  15473. "yield": C, "export": kw("export"), "import": kw("import"), "extends": C,
  15474. "await": C
  15475. };
  15476. }();
  15477. var isOperatorChar = /[+\-*&%=<>!?|~^@]/;
  15478. var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
  15479. function readRegexp(stream) {
  15480. var escaped = false, next, inSet = false;
  15481. while ((next = stream.next()) != null) {
  15482. if (!escaped) {
  15483. if (next == "/" && !inSet) return;
  15484. if (next == "[") inSet = true;
  15485. else if (inSet && next == "]") inSet = false;
  15486. }
  15487. escaped = !escaped && next == "\\";
  15488. }
  15489. }
  15490. // Used as scratch variables to communicate multiple values without
  15491. // consing up tons of objects.
  15492. var type, content;
  15493. function ret(tp, style, cont) {
  15494. type = tp; content = cont;
  15495. return style;
  15496. }
  15497. function tokenBase(stream, state) {
  15498. var ch = stream.next();
  15499. if (ch == '"' || ch == "'") {
  15500. state.tokenize = tokenString(ch);
  15501. return state.tokenize(stream, state);
  15502. } else if (ch == "." && stream.match(/^\d[\d_]*(?:[eE][+\-]?[\d_]+)?/)) {
  15503. return ret("number", "number");
  15504. } else if (ch == "." && stream.match("..")) {
  15505. return ret("spread", "meta");
  15506. } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
  15507. return ret(ch);
  15508. } else if (ch == "=" && stream.eat(">")) {
  15509. return ret("=>", "operator");
  15510. } else if (ch == "0" && stream.match(/^(?:x[\dA-Fa-f_]+|o[0-7_]+|b[01_]+)n?/)) {
  15511. return ret("number", "number");
  15512. } else if (/\d/.test(ch)) {
  15513. stream.match(/^[\d_]*(?:n|(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)?/);
  15514. return ret("number", "number");
  15515. } else if (ch == "/") {
  15516. if (stream.eat("*")) {
  15517. state.tokenize = tokenComment;
  15518. return tokenComment(stream, state);
  15519. } else if (stream.eat("/")) {
  15520. stream.skipToEnd();
  15521. return ret("comment", "comment");
  15522. } else if (expressionAllowed(stream, state, 1)) {
  15523. readRegexp(stream);
  15524. stream.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/);
  15525. return ret("regexp", "string-2");
  15526. } else {
  15527. stream.eat("=");
  15528. return ret("operator", "operator", stream.current());
  15529. }
  15530. } else if (ch == "`") {
  15531. state.tokenize = tokenQuasi;
  15532. return tokenQuasi(stream, state);
  15533. } else if (ch == "#" && stream.peek() == "!") {
  15534. stream.skipToEnd();
  15535. return ret("meta", "meta");
  15536. } else if (ch == "#" && stream.eatWhile(wordRE)) {
  15537. return ret("variable", "property")
  15538. } else if (ch == "<" && stream.match("!--") ||
  15539. (ch == "-" && stream.match("->") && !/\S/.test(stream.string.slice(0, stream.start)))) {
  15540. stream.skipToEnd()
  15541. return ret("comment", "comment")
  15542. } else if (isOperatorChar.test(ch)) {
  15543. if (ch != ">" || !state.lexical || state.lexical.type != ">") {
  15544. if (stream.eat("=")) {
  15545. if (ch == "!" || ch == "=") stream.eat("=")
  15546. } else if (/[<>*+\-]/.test(ch)) {
  15547. stream.eat(ch)
  15548. if (ch == ">") stream.eat(ch)
  15549. }
  15550. }
  15551. if (ch == "?" && stream.eat(".")) return ret(".")
  15552. return ret("operator", "operator", stream.current());
  15553. } else if (wordRE.test(ch)) {
  15554. stream.eatWhile(wordRE);
  15555. var word = stream.current()
  15556. if (state.lastType != ".") {
  15557. if (keywords.propertyIsEnumerable(word)) {
  15558. var kw = keywords[word]
  15559. return ret(kw.type, kw.style, word)
  15560. }
  15561. // backported ReDoS fix from
  15562. // https://github.com/codemirror/codemirror5/blob/a0854c752a76e4ba9512a9beedb9076f36e4f8f9/mode/javascript/javascript.js#L130C36-L130C36
  15563. // https://security.snyk.io/vuln/SNYK-JS-CODEMIRROR-1016937
  15564. if (word == "async" && stream.match(/^(\s|\/\*([^*]|\*(?!\/))*?\*\/)*[\[\(\w]/, false))
  15565. return ret("async", "keyword", word)
  15566. }
  15567. return ret("variable", "variable", word)
  15568. }
  15569. }
  15570. function tokenString(quote) {
  15571. return function(stream, state) {
  15572. var escaped = false, next;
  15573. if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
  15574. state.tokenize = tokenBase;
  15575. return ret("jsonld-keyword", "meta");
  15576. }
  15577. while ((next = stream.next()) != null) {
  15578. if (next == quote && !escaped) break;
  15579. escaped = !escaped && next == "\\";
  15580. }
  15581. if (!escaped) state.tokenize = tokenBase;
  15582. return ret("string", "string");
  15583. };
  15584. }
  15585. function tokenComment(stream, state) {
  15586. var maybeEnd = false, ch;
  15587. while (ch = stream.next()) {
  15588. if (ch == "/" && maybeEnd) {
  15589. state.tokenize = tokenBase;
  15590. break;
  15591. }
  15592. maybeEnd = (ch == "*");
  15593. }
  15594. return ret("comment", "comment");
  15595. }
  15596. function tokenQuasi(stream, state) {
  15597. var escaped = false, next;
  15598. while ((next = stream.next()) != null) {
  15599. if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
  15600. state.tokenize = tokenBase;
  15601. break;
  15602. }
  15603. escaped = !escaped && next == "\\";
  15604. }
  15605. return ret("quasi", "string-2", stream.current());
  15606. }
  15607. var brackets = "([{}])";
  15608. // This is a crude lookahead trick to try and notice that we're
  15609. // parsing the argument patterns for a fat-arrow function before we
  15610. // actually hit the arrow token. It only works if the arrow is on
  15611. // the same line as the arguments and there's no strange noise
  15612. // (comments) in between. Fallback is to only notice when we hit the
  15613. // arrow, and not declare the arguments as locals for the arrow
  15614. // body.
  15615. function findFatArrow(stream, state) {
  15616. if (state.fatArrowAt) state.fatArrowAt = null;
  15617. var arrow = stream.string.indexOf("=>", stream.start);
  15618. if (arrow < 0) return;
  15619. if (isTS) { // Try to skip TypeScript return type declarations after the arguments
  15620. var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow))
  15621. if (m) arrow = m.index
  15622. }
  15623. var depth = 0, sawSomething = false;
  15624. for (var pos = arrow - 1; pos >= 0; --pos) {
  15625. var ch = stream.string.charAt(pos);
  15626. var bracket = brackets.indexOf(ch);
  15627. if (bracket >= 0 && bracket < 3) {
  15628. if (!depth) { ++pos; break; }
  15629. if (--depth == 0) { if (ch == "(") sawSomething = true; break; }
  15630. } else if (bracket >= 3 && bracket < 6) {
  15631. ++depth;
  15632. } else if (wordRE.test(ch)) {
  15633. sawSomething = true;
  15634. } else if (/["'\/`]/.test(ch)) {
  15635. for (;; --pos) {
  15636. if (pos == 0) return
  15637. var next = stream.string.charAt(pos - 1)
  15638. if (next == ch && stream.string.charAt(pos - 2) != "\\") { pos--; break }
  15639. }
  15640. } else if (sawSomething && !depth) {
  15641. ++pos;
  15642. break;
  15643. }
  15644. }
  15645. if (sawSomething && !depth) state.fatArrowAt = pos;
  15646. }
  15647. // Parser
  15648. var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
  15649. function JSLexical(indented, column, type, align, prev, info) {
  15650. this.indented = indented;
  15651. this.column = column;
  15652. this.type = type;
  15653. this.prev = prev;
  15654. this.info = info;
  15655. if (align != null) this.align = align;
  15656. }
  15657. function inScope(state, varname) {
  15658. for (var v = state.localVars; v; v = v.next)
  15659. if (v.name == varname) return true;
  15660. for (var cx = state.context; cx; cx = cx.prev) {
  15661. for (var v = cx.vars; v; v = v.next)
  15662. if (v.name == varname) return true;
  15663. }
  15664. }
  15665. function parseJS(state, style, type, content, stream) {
  15666. var cc = state.cc;
  15667. // Communicate our context to the combinators.
  15668. // (Less wasteful than consing up a hundred closures on every call.)
  15669. cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
  15670. if (!state.lexical.hasOwnProperty("align"))
  15671. state.lexical.align = true;
  15672. while(true) {
  15673. var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
  15674. if (combinator(type, content)) {
  15675. while(cc.length && cc[cc.length - 1].lex)
  15676. cc.pop()();
  15677. if (cx.marked) return cx.marked;
  15678. if (type == "variable" && inScope(state, content)) return "variable-2";
  15679. return style;
  15680. }
  15681. }
  15682. }
  15683. // Combinator utils
  15684. var cx = {state: null, column: null, marked: null, cc: null};
  15685. function pass() {
  15686. for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
  15687. }
  15688. function cont() {
  15689. pass.apply(null, arguments);
  15690. return true;
  15691. }
  15692. function inList(name, list) {
  15693. for (var v = list; v; v = v.next) if (v.name == name) return true
  15694. return false;
  15695. }
  15696. function register(varname) {
  15697. var state = cx.state;
  15698. cx.marked = "def";
  15699. if (state.context) {
  15700. if (state.lexical.info == "var" && state.context && state.context.block) {
  15701. // FIXME function decls are also not block scoped
  15702. var newContext = registerVarScoped(varname, state.context)
  15703. if (newContext != null) {
  15704. state.context = newContext
  15705. return
  15706. }
  15707. } else if (!inList(varname, state.localVars)) {
  15708. state.localVars = new Var(varname, state.localVars)
  15709. return
  15710. }
  15711. }
  15712. // Fall through means this is global
  15713. if (parserConfig.globalVars && !inList(varname, state.globalVars))
  15714. state.globalVars = new Var(varname, state.globalVars)
  15715. }
  15716. function registerVarScoped(varname, context) {
  15717. if (!context) {
  15718. return null
  15719. } else if (context.block) {
  15720. var inner = registerVarScoped(varname, context.prev)
  15721. if (!inner) return null
  15722. if (inner == context.prev) return context
  15723. return new Context(inner, context.vars, true)
  15724. } else if (inList(varname, context.vars)) {
  15725. return context
  15726. } else {
  15727. return new Context(context.prev, new Var(varname, context.vars), false)
  15728. }
  15729. }
  15730. function isModifier(name) {
  15731. return name == "public" || name == "private" || name == "protected" || name == "abstract" || name == "readonly"
  15732. }
  15733. // Combinators
  15734. function Context(prev, vars, block) { this.prev = prev; this.vars = vars; this.block = block }
  15735. function Var(name, next) { this.name = name; this.next = next }
  15736. var defaultVars = new Var("this", new Var("arguments", null))
  15737. function pushcontext() {
  15738. cx.state.context = new Context(cx.state.context, cx.state.localVars, false)
  15739. cx.state.localVars = defaultVars
  15740. }
  15741. function pushblockcontext() {
  15742. cx.state.context = new Context(cx.state.context, cx.state.localVars, true)
  15743. cx.state.localVars = null
  15744. }
  15745. function popcontext() {
  15746. cx.state.localVars = cx.state.context.vars
  15747. cx.state.context = cx.state.context.prev
  15748. }
  15749. popcontext.lex = true
  15750. function pushlex(type, info) {
  15751. var result = function() {
  15752. var state = cx.state, indent = state.indented;
  15753. if (state.lexical.type == "stat") indent = state.lexical.indented;
  15754. else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
  15755. indent = outer.indented;
  15756. state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
  15757. };
  15758. result.lex = true;
  15759. return result;
  15760. }
  15761. function poplex() {
  15762. var state = cx.state;
  15763. if (state.lexical.prev) {
  15764. if (state.lexical.type == ")")
  15765. state.indented = state.lexical.indented;
  15766. state.lexical = state.lexical.prev;
  15767. }
  15768. }
  15769. poplex.lex = true;
  15770. function expect(wanted) {
  15771. function exp(type) {
  15772. if (type == wanted) return cont();
  15773. else if (wanted == ";" || type == "}" || type == ")" || type == "]") return pass();
  15774. else return cont(exp);
  15775. };
  15776. return exp;
  15777. }
  15778. function statement(type, value) {
  15779. if (type == "var") return cont(pushlex("vardef", value), vardef, expect(";"), poplex);
  15780. if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
  15781. if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
  15782. if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex);
  15783. if (type == "debugger") return cont(expect(";"));
  15784. if (type == "{") return cont(pushlex("}"), pushblockcontext, block, poplex, popcontext);
  15785. if (type == ";") return cont();
  15786. if (type == "if") {
  15787. if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
  15788. cx.state.cc.pop()();
  15789. return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse);
  15790. }
  15791. if (type == "function") return cont(functiondef);
  15792. if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
  15793. if (type == "class" || (isTS && value == "interface")) {
  15794. cx.marked = "keyword"
  15795. return cont(pushlex("form", type == "class" ? type : value), className, poplex)
  15796. }
  15797. if (type == "variable") {
  15798. if (isTS && value == "declare") {
  15799. cx.marked = "keyword"
  15800. return cont(statement)
  15801. } else if (isTS && (value == "module" || value == "enum" || value == "type") && cx.stream.match(/^\s*\w/, false)) {
  15802. cx.marked = "keyword"
  15803. if (value == "enum") return cont(enumdef);
  15804. else if (value == "type") return cont(typename, expect("operator"), typeexpr, expect(";"));
  15805. else return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex)
  15806. } else if (isTS && value == "namespace") {
  15807. cx.marked = "keyword"
  15808. return cont(pushlex("form"), expression, statement, poplex)
  15809. } else if (isTS && value == "abstract") {
  15810. cx.marked = "keyword"
  15811. return cont(statement)
  15812. } else {
  15813. return cont(pushlex("stat"), maybelabel);
  15814. }
  15815. }
  15816. if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), pushblockcontext,
  15817. block, poplex, poplex, popcontext);
  15818. if (type == "case") return cont(expression, expect(":"));
  15819. if (type == "default") return cont(expect(":"));
  15820. if (type == "catch") return cont(pushlex("form"), pushcontext, maybeCatchBinding, statement, poplex, popcontext);
  15821. if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
  15822. if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
  15823. if (type == "async") return cont(statement)
  15824. if (value == "@") return cont(expression, statement)
  15825. return pass(pushlex("stat"), expression, expect(";"), poplex);
  15826. }
  15827. function maybeCatchBinding(type) {
  15828. if (type == "(") return cont(funarg, expect(")"))
  15829. }
  15830. function expression(type, value) {
  15831. return expressionInner(type, value, false);
  15832. }
  15833. function expressionNoComma(type, value) {
  15834. return expressionInner(type, value, true);
  15835. }
  15836. function parenExpr(type) {
  15837. if (type != "(") return pass()
  15838. return cont(pushlex(")"), maybeexpression, expect(")"), poplex)
  15839. }
  15840. function expressionInner(type, value, noComma) {
  15841. if (cx.state.fatArrowAt == cx.stream.start) {
  15842. var body = noComma ? arrowBodyNoComma : arrowBody;
  15843. if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext);
  15844. else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
  15845. }
  15846. var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
  15847. if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
  15848. if (type == "function") return cont(functiondef, maybeop);
  15849. if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), classExpression, poplex); }
  15850. if (type == "keyword c" || type == "async") return cont(noComma ? expressionNoComma : expression);
  15851. if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
  15852. if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
  15853. if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
  15854. if (type == "{") return contCommasep(objprop, "}", null, maybeop);
  15855. if (type == "quasi") return pass(quasi, maybeop);
  15856. if (type == "new") return cont(maybeTarget(noComma));
  15857. if (type == "import") return cont(expression);
  15858. return cont();
  15859. }
  15860. function maybeexpression(type) {
  15861. if (type.match(/[;\}\)\],]/)) return pass();
  15862. return pass(expression);
  15863. }
  15864. function maybeoperatorComma(type, value) {
  15865. if (type == ",") return cont(maybeexpression);
  15866. return maybeoperatorNoComma(type, value, false);
  15867. }
  15868. function maybeoperatorNoComma(type, value, noComma) {
  15869. var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
  15870. var expr = noComma == false ? expression : expressionNoComma;
  15871. if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
  15872. if (type == "operator") {
  15873. if (/\+\+|--/.test(value) || isTS && value == "!") return cont(me);
  15874. if (isTS && value == "<" && cx.stream.match(/^([^<>]|<[^<>]*>)*>\s*\(/, false))
  15875. return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, me);
  15876. if (value == "?") return cont(expression, expect(":"), expr);
  15877. return cont(expr);
  15878. }
  15879. if (type == "quasi") { return pass(quasi, me); }
  15880. if (type == ";") return;
  15881. if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
  15882. if (type == ".") return cont(property, me);
  15883. if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
  15884. if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) }
  15885. if (type == "regexp") {
  15886. cx.state.lastType = cx.marked = "operator"
  15887. cx.stream.backUp(cx.stream.pos - cx.stream.start - 1)
  15888. return cont(expr)
  15889. }
  15890. }
  15891. function quasi(type, value) {
  15892. if (type != "quasi") return pass();
  15893. if (value.slice(value.length - 2) != "${") return cont(quasi);
  15894. return cont(expression, continueQuasi);
  15895. }
  15896. function continueQuasi(type) {
  15897. if (type == "}") {
  15898. cx.marked = "string-2";
  15899. cx.state.tokenize = tokenQuasi;
  15900. return cont(quasi);
  15901. }
  15902. }
  15903. function arrowBody(type) {
  15904. findFatArrow(cx.stream, cx.state);
  15905. return pass(type == "{" ? statement : expression);
  15906. }
  15907. function arrowBodyNoComma(type) {
  15908. findFatArrow(cx.stream, cx.state);
  15909. return pass(type == "{" ? statement : expressionNoComma);
  15910. }
  15911. function maybeTarget(noComma) {
  15912. return function(type) {
  15913. if (type == ".") return cont(noComma ? targetNoComma : target);
  15914. else if (type == "variable" && isTS) return cont(maybeTypeArgs, noComma ? maybeoperatorNoComma : maybeoperatorComma)
  15915. else return pass(noComma ? expressionNoComma : expression);
  15916. };
  15917. }
  15918. function target(_, value) {
  15919. if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); }
  15920. }
  15921. function targetNoComma(_, value) {
  15922. if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); }
  15923. }
  15924. function maybelabel(type) {
  15925. if (type == ":") return cont(poplex, statement);
  15926. return pass(maybeoperatorComma, expect(";"), poplex);
  15927. }
  15928. function property(type) {
  15929. if (type == "variable") {cx.marked = "property"; return cont();}
  15930. }
  15931. function objprop(type, value) {
  15932. if (type == "async") {
  15933. cx.marked = "property";
  15934. return cont(objprop);
  15935. } else if (type == "variable" || cx.style == "keyword") {
  15936. cx.marked = "property";
  15937. if (value == "get" || value == "set") return cont(getterSetter);
  15938. var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params
  15939. if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false)))
  15940. cx.state.fatArrowAt = cx.stream.pos + m[0].length
  15941. return cont(afterprop);
  15942. } else if (type == "number" || type == "string") {
  15943. cx.marked = jsonldMode ? "property" : (cx.style + " property");
  15944. return cont(afterprop);
  15945. } else if (type == "jsonld-keyword") {
  15946. return cont(afterprop);
  15947. } else if (isTS && isModifier(value)) {
  15948. cx.marked = "keyword"
  15949. return cont(objprop)
  15950. } else if (type == "[") {
  15951. return cont(expression, maybetype, expect("]"), afterprop);
  15952. } else if (type == "spread") {
  15953. return cont(expressionNoComma, afterprop);
  15954. } else if (value == "*") {
  15955. cx.marked = "keyword";
  15956. return cont(objprop);
  15957. } else if (type == ":") {
  15958. return pass(afterprop)
  15959. }
  15960. }
  15961. function getterSetter(type) {
  15962. if (type != "variable") return pass(afterprop);
  15963. cx.marked = "property";
  15964. return cont(functiondef);
  15965. }
  15966. function afterprop(type) {
  15967. if (type == ":") return cont(expressionNoComma);
  15968. if (type == "(") return pass(functiondef);
  15969. }
  15970. function commasep(what, end, sep) {
  15971. function proceed(type, value) {
  15972. if (sep ? sep.indexOf(type) > -1 : type == ",") {
  15973. var lex = cx.state.lexical;
  15974. if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
  15975. return cont(function(type, value) {
  15976. if (type == end || value == end) return pass()
  15977. return pass(what)
  15978. }, proceed);
  15979. }
  15980. if (type == end || value == end) return cont();
  15981. if (sep && sep.indexOf(";") > -1) return pass(what)
  15982. return cont(expect(end));
  15983. }
  15984. return function(type, value) {
  15985. if (type == end || value == end) return cont();
  15986. return pass(what, proceed);
  15987. };
  15988. }
  15989. function contCommasep(what, end, info) {
  15990. for (var i = 3; i < arguments.length; i++)
  15991. cx.cc.push(arguments[i]);
  15992. return cont(pushlex(end, info), commasep(what, end), poplex);
  15993. }
  15994. function block(type) {
  15995. if (type == "}") return cont();
  15996. return pass(statement, block);
  15997. }
  15998. function maybetype(type, value) {
  15999. if (isTS) {
  16000. if (type == ":") return cont(typeexpr);
  16001. if (value == "?") return cont(maybetype);
  16002. }
  16003. }
  16004. function maybetypeOrIn(type, value) {
  16005. if (isTS && (type == ":" || value == "in")) return cont(typeexpr)
  16006. }
  16007. function mayberettype(type) {
  16008. if (isTS && type == ":") {
  16009. if (cx.stream.match(/^\s*\w+\s+is\b/, false)) return cont(expression, isKW, typeexpr)
  16010. else return cont(typeexpr)
  16011. }
  16012. }
  16013. function isKW(_, value) {
  16014. if (value == "is") {
  16015. cx.marked = "keyword"
  16016. return cont()
  16017. }
  16018. }
  16019. function typeexpr(type, value) {
  16020. if (value == "keyof" || value == "typeof" || value == "infer") {
  16021. cx.marked = "keyword"
  16022. return cont(value == "typeof" ? expressionNoComma : typeexpr)
  16023. }
  16024. if (type == "variable" || value == "void") {
  16025. cx.marked = "type"
  16026. return cont(afterType)
  16027. }
  16028. if (value == "|" || value == "&") return cont(typeexpr)
  16029. if (type == "string" || type == "number" || type == "atom") return cont(afterType);
  16030. if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType)
  16031. if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType)
  16032. if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType, afterType)
  16033. if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr)
  16034. }
  16035. function maybeReturnType(type) {
  16036. if (type == "=>") return cont(typeexpr)
  16037. }
  16038. function typeprop(type, value) {
  16039. if (type == "variable" || cx.style == "keyword") {
  16040. cx.marked = "property"
  16041. return cont(typeprop)
  16042. } else if (value == "?" || type == "number" || type == "string") {
  16043. return cont(typeprop)
  16044. } else if (type == ":") {
  16045. return cont(typeexpr)
  16046. } else if (type == "[") {
  16047. return cont(expect("variable"), maybetypeOrIn, expect("]"), typeprop)
  16048. } else if (type == "(") {
  16049. return pass(functiondecl, typeprop)
  16050. }
  16051. }
  16052. function typearg(type, value) {
  16053. if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg)
  16054. if (type == ":") return cont(typeexpr)
  16055. if (type == "spread") return cont(typearg)
  16056. return pass(typeexpr)
  16057. }
  16058. function afterType(type, value) {
  16059. if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
  16060. if (value == "|" || type == "." || value == "&") return cont(typeexpr)
  16061. if (type == "[") return cont(typeexpr, expect("]"), afterType)
  16062. if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) }
  16063. if (value == "?") return cont(typeexpr, expect(":"), typeexpr)
  16064. }
  16065. function maybeTypeArgs(_, value) {
  16066. if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
  16067. }
  16068. function typeparam() {
  16069. return pass(typeexpr, maybeTypeDefault)
  16070. }
  16071. function maybeTypeDefault(_, value) {
  16072. if (value == "=") return cont(typeexpr)
  16073. }
  16074. function vardef(_, value) {
  16075. if (value == "enum") {cx.marked = "keyword"; return cont(enumdef)}
  16076. return pass(pattern, maybetype, maybeAssign, vardefCont);
  16077. }
  16078. function pattern(type, value) {
  16079. if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(pattern) }
  16080. if (type == "variable") { register(value); return cont(); }
  16081. if (type == "spread") return cont(pattern);
  16082. if (type == "[") return contCommasep(eltpattern, "]");
  16083. if (type == "{") return contCommasep(proppattern, "}");
  16084. }
  16085. function proppattern(type, value) {
  16086. if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
  16087. register(value);
  16088. return cont(maybeAssign);
  16089. }
  16090. if (type == "variable") cx.marked = "property";
  16091. if (type == "spread") return cont(pattern);
  16092. if (type == "}") return pass();
  16093. if (type == "[") return cont(expression, expect(']'), expect(':'), proppattern);
  16094. return cont(expect(":"), pattern, maybeAssign);
  16095. }
  16096. function eltpattern() {
  16097. return pass(pattern, maybeAssign)
  16098. }
  16099. function maybeAssign(_type, value) {
  16100. if (value == "=") return cont(expressionNoComma);
  16101. }
  16102. function vardefCont(type) {
  16103. if (type == ",") return cont(vardef);
  16104. }
  16105. function maybeelse(type, value) {
  16106. if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
  16107. }
  16108. function forspec(type, value) {
  16109. if (value == "await") return cont(forspec);
  16110. if (type == "(") return cont(pushlex(")"), forspec1, poplex);
  16111. }
  16112. function forspec1(type) {
  16113. if (type == "var") return cont(vardef, forspec2);
  16114. if (type == "variable") return cont(forspec2);
  16115. return pass(forspec2)
  16116. }
  16117. function forspec2(type, value) {
  16118. if (type == ")") return cont()
  16119. if (type == ";") return cont(forspec2)
  16120. if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression, forspec2) }
  16121. return pass(expression, forspec2)
  16122. }
  16123. function functiondef(type, value) {
  16124. if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
  16125. if (type == "variable") {register(value); return cont(functiondef);}
  16126. if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, statement, popcontext);
  16127. if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondef)
  16128. }
  16129. function functiondecl(type, value) {
  16130. if (value == "*") {cx.marked = "keyword"; return cont(functiondecl);}
  16131. if (type == "variable") {register(value); return cont(functiondecl);}
  16132. if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, popcontext);
  16133. if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondecl)
  16134. }
  16135. function typename(type, value) {
  16136. if (type == "keyword" || type == "variable") {
  16137. cx.marked = "type"
  16138. return cont(typename)
  16139. } else if (value == "<") {
  16140. return cont(pushlex(">"), commasep(typeparam, ">"), poplex)
  16141. }
  16142. }
  16143. function funarg(type, value) {
  16144. if (value == "@") cont(expression, funarg)
  16145. if (type == "spread") return cont(funarg);
  16146. if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(funarg); }
  16147. if (isTS && type == "this") return cont(maybetype, maybeAssign)
  16148. return pass(pattern, maybetype, maybeAssign);
  16149. }
  16150. function classExpression(type, value) {
  16151. // Class expressions may have an optional name.
  16152. if (type == "variable") return className(type, value);
  16153. return classNameAfter(type, value);
  16154. }
  16155. function className(type, value) {
  16156. if (type == "variable") {register(value); return cont(classNameAfter);}
  16157. }
  16158. function classNameAfter(type, value) {
  16159. if (value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, classNameAfter)
  16160. if (value == "extends" || value == "implements" || (isTS && type == ",")) {
  16161. if (value == "implements") cx.marked = "keyword";
  16162. return cont(isTS ? typeexpr : expression, classNameAfter);
  16163. }
  16164. if (type == "{") return cont(pushlex("}"), classBody, poplex);
  16165. }
  16166. function classBody(type, value) {
  16167. if (type == "async" ||
  16168. (type == "variable" &&
  16169. (value == "static" || value == "get" || value == "set" || (isTS && isModifier(value))) &&
  16170. cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) {
  16171. cx.marked = "keyword";
  16172. return cont(classBody);
  16173. }
  16174. if (type == "variable" || cx.style == "keyword") {
  16175. cx.marked = "property";
  16176. return cont(classfield, classBody);
  16177. }
  16178. if (type == "number" || type == "string") return cont(classfield, classBody);
  16179. if (type == "[")
  16180. return cont(expression, maybetype, expect("]"), classfield, classBody)
  16181. if (value == "*") {
  16182. cx.marked = "keyword";
  16183. return cont(classBody);
  16184. }
  16185. if (isTS && type == "(") return pass(functiondecl, classBody)
  16186. if (type == ";" || type == ",") return cont(classBody);
  16187. if (type == "}") return cont();
  16188. if (value == "@") return cont(expression, classBody)
  16189. }
  16190. function classfield(type, value) {
  16191. if (value == "?") return cont(classfield)
  16192. if (type == ":") return cont(typeexpr, maybeAssign)
  16193. if (value == "=") return cont(expressionNoComma)
  16194. var context = cx.state.lexical.prev, isInterface = context && context.info == "interface"
  16195. return pass(isInterface ? functiondecl : functiondef)
  16196. }
  16197. function afterExport(type, value) {
  16198. if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
  16199. if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
  16200. if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";"));
  16201. return pass(statement);
  16202. }
  16203. function exportField(type, value) {
  16204. if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); }
  16205. if (type == "variable") return pass(expressionNoComma, exportField);
  16206. }
  16207. function afterImport(type) {
  16208. if (type == "string") return cont();
  16209. if (type == "(") return pass(expression);
  16210. return pass(importSpec, maybeMoreImports, maybeFrom);
  16211. }
  16212. function importSpec(type, value) {
  16213. if (type == "{") return contCommasep(importSpec, "}");
  16214. if (type == "variable") register(value);
  16215. if (value == "*") cx.marked = "keyword";
  16216. return cont(maybeAs);
  16217. }
  16218. function maybeMoreImports(type) {
  16219. if (type == ",") return cont(importSpec, maybeMoreImports)
  16220. }
  16221. function maybeAs(_type, value) {
  16222. if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
  16223. }
  16224. function maybeFrom(_type, value) {
  16225. if (value == "from") { cx.marked = "keyword"; return cont(expression); }
  16226. }
  16227. function arrayLiteral(type) {
  16228. if (type == "]") return cont();
  16229. return pass(commasep(expressionNoComma, "]"));
  16230. }
  16231. function enumdef() {
  16232. return pass(pushlex("form"), pattern, expect("{"), pushlex("}"), commasep(enummember, "}"), poplex, poplex)
  16233. }
  16234. function enummember() {
  16235. return pass(pattern, maybeAssign);
  16236. }
  16237. function isContinuedStatement(state, textAfter) {
  16238. return state.lastType == "operator" || state.lastType == "," ||
  16239. isOperatorChar.test(textAfter.charAt(0)) ||
  16240. /[,.]/.test(textAfter.charAt(0));
  16241. }
  16242. function expressionAllowed(stream, state, backUp) {
  16243. return state.tokenize == tokenBase &&
  16244. /^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
  16245. (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
  16246. }
  16247. // Interface
  16248. return {
  16249. startState: function(basecolumn) {
  16250. var state = {
  16251. tokenize: tokenBase,
  16252. lastType: "sof",
  16253. cc: [],
  16254. lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
  16255. localVars: parserConfig.localVars,
  16256. context: parserConfig.localVars && new Context(null, null, false),
  16257. indented: basecolumn || 0
  16258. };
  16259. if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
  16260. state.globalVars = parserConfig.globalVars;
  16261. return state;
  16262. },
  16263. token: function(stream, state) {
  16264. if (stream.sol()) {
  16265. if (!state.lexical.hasOwnProperty("align"))
  16266. state.lexical.align = false;
  16267. state.indented = stream.indentation();
  16268. findFatArrow(stream, state);
  16269. }
  16270. if (state.tokenize != tokenComment && stream.eatSpace()) return null;
  16271. var style = state.tokenize(stream, state);
  16272. if (type == "comment") return style;
  16273. state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
  16274. return parseJS(state, style, type, content, stream);
  16275. },
  16276. indent: function(state, textAfter) {
  16277. if (state.tokenize == tokenComment) return CodeMirror.Pass;
  16278. if (state.tokenize != tokenBase) return 0;
  16279. var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top
  16280. // Kludge to prevent 'maybelse' from blocking lexical scope pops
  16281. if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
  16282. var c = state.cc[i];
  16283. if (c == poplex) lexical = lexical.prev;
  16284. else if (c != maybeelse) break;
  16285. }
  16286. while ((lexical.type == "stat" || lexical.type == "form") &&
  16287. (firstChar == "}" || ((top = state.cc[state.cc.length - 1]) &&
  16288. (top == maybeoperatorComma || top == maybeoperatorNoComma) &&
  16289. !/^[,\.=+\-*:?[\(]/.test(textAfter))))
  16290. lexical = lexical.prev;
  16291. if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
  16292. lexical = lexical.prev;
  16293. var type = lexical.type, closing = firstChar == type;
  16294. if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info.length + 1 : 0);
  16295. else if (type == "form" && firstChar == "{") return lexical.indented;
  16296. else if (type == "form") return lexical.indented + indentUnit;
  16297. else if (type == "stat")
  16298. return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
  16299. else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
  16300. return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
  16301. else if (lexical.align) return lexical.column + (closing ? 0 : 1);
  16302. else return lexical.indented + (closing ? 0 : indentUnit);
  16303. },
  16304. electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
  16305. blockCommentStart: jsonMode ? null : "/*",
  16306. blockCommentEnd: jsonMode ? null : "*/",
  16307. blockCommentContinue: jsonMode ? null : " * ",
  16308. lineComment: jsonMode ? null : "//",
  16309. fold: "brace",
  16310. closeBrackets: "()[]{}''\"\"``",
  16311. helperType: jsonMode ? "json" : "javascript",
  16312. jsonldMode: jsonldMode,
  16313. jsonMode: jsonMode,
  16314. expressionAllowed: expressionAllowed,
  16315. skipExpression: function(state) {
  16316. var top = state.cc[state.cc.length - 1]
  16317. if (top == expression || top == expressionNoComma) state.cc.pop()
  16318. }
  16319. };
  16320. });
  16321. CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
  16322. CodeMirror.defineMIME("text/javascript", "javascript");
  16323. CodeMirror.defineMIME("text/ecmascript", "javascript");
  16324. CodeMirror.defineMIME("application/javascript", "javascript");
  16325. CodeMirror.defineMIME("application/x-javascript", "javascript");
  16326. CodeMirror.defineMIME("application/ecmascript", "javascript");
  16327. CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
  16328. CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
  16329. CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
  16330. CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
  16331. CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
  16332. });
  16333. /* ---- mode/markdown.js ---- */
  16334. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  16335. // Distributed under an MIT license: https://codemirror.net/LICENSE
  16336. (function(mod) {
  16337. if (typeof exports == "object" && typeof module == "object") // CommonJS
  16338. mod(require("../../lib/codemirror"), require("../xml/xml"), require("../meta"));
  16339. else if (typeof define == "function" && define.amd) // AMD
  16340. define(["../../lib/codemirror", "../xml/xml", "../meta"], mod);
  16341. else // Plain browser env
  16342. mod(CodeMirror);
  16343. })(function(CodeMirror) {
  16344. "use strict";
  16345. CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
  16346. var htmlMode = CodeMirror.getMode(cmCfg, "text/html");
  16347. var htmlModeMissing = htmlMode.name == "null"
  16348. function getMode(name) {
  16349. if (CodeMirror.findModeByName) {
  16350. var found = CodeMirror.findModeByName(name);
  16351. if (found) name = found.mime || found.mimes[0];
  16352. }
  16353. var mode = CodeMirror.getMode(cmCfg, name);
  16354. return mode.name == "null" ? null : mode;
  16355. }
  16356. // Should characters that affect highlighting be highlighted separate?
  16357. // Does not include characters that will be output (such as `1.` and `-` for lists)
  16358. if (modeCfg.highlightFormatting === undefined)
  16359. modeCfg.highlightFormatting = false;
  16360. // Maximum number of nested blockquotes. Set to 0 for infinite nesting.
  16361. // Excess `>` will emit `error` token.
  16362. if (modeCfg.maxBlockquoteDepth === undefined)
  16363. modeCfg.maxBlockquoteDepth = 0;
  16364. // Turn on task lists? ("- [ ] " and "- [x] ")
  16365. if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
  16366. // Turn on strikethrough syntax
  16367. if (modeCfg.strikethrough === undefined)
  16368. modeCfg.strikethrough = false;
  16369. if (modeCfg.emoji === undefined)
  16370. modeCfg.emoji = false;
  16371. if (modeCfg.fencedCodeBlockHighlighting === undefined)
  16372. modeCfg.fencedCodeBlockHighlighting = true;
  16373. if (modeCfg.fencedCodeBlockDefaultMode === undefined)
  16374. modeCfg.fencedCodeBlockDefaultMode = 'text/plain';
  16375. if (modeCfg.xml === undefined)
  16376. modeCfg.xml = true;
  16377. // Allow token types to be overridden by user-provided token types.
  16378. if (modeCfg.tokenTypeOverrides === undefined)
  16379. modeCfg.tokenTypeOverrides = {};
  16380. var tokenTypes = {
  16381. header: "header",
  16382. code: "comment",
  16383. quote: "quote",
  16384. list1: "variable-2",
  16385. list2: "variable-3",
  16386. list3: "keyword",
  16387. hr: "hr",
  16388. image: "image",
  16389. imageAltText: "image-alt-text",
  16390. imageMarker: "image-marker",
  16391. formatting: "formatting",
  16392. linkInline: "link",
  16393. linkEmail: "link",
  16394. linkText: "link",
  16395. linkHref: "string",
  16396. em: "em",
  16397. strong: "strong",
  16398. strikethrough: "strikethrough",
  16399. emoji: "builtin"
  16400. };
  16401. for (var tokenType in tokenTypes) {
  16402. if (tokenTypes.hasOwnProperty(tokenType) && modeCfg.tokenTypeOverrides[tokenType]) {
  16403. tokenTypes[tokenType] = modeCfg.tokenTypeOverrides[tokenType];
  16404. }
  16405. }
  16406. var hrRE = /^([*\-_])(?:\s*\1){2,}\s*$/
  16407. , listRE = /^(?:[*\-+]|^[0-9]+([.)]))\s+/
  16408. , taskListRE = /^\[(x| )\](?=\s)/i // Must follow listRE
  16409. , atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/
  16410. , setextHeaderRE = /^ {0,3}(?:\={1,}|-{2,})\s*$/
  16411. , textRE = /^[^#!\[\]*_\\<>` "'(~:]+/
  16412. , fencedCodeRE = /^(~~~+|```+)[ \t]*([\w\/+#-]*)[^\n`]*$/
  16413. , linkDefRE = /^\s*\[[^\]]+?\]:.*$/ // naive link-definition
  16414. , punctuation = /[!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E42\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC9\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDF3C-\uDF3E]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]/
  16415. , expandedTab = " " // CommonMark specifies tab as 4 spaces
  16416. function switchInline(stream, state, f) {
  16417. state.f = state.inline = f;
  16418. return f(stream, state);
  16419. }
  16420. function switchBlock(stream, state, f) {
  16421. state.f = state.block = f;
  16422. return f(stream, state);
  16423. }
  16424. function lineIsEmpty(line) {
  16425. return !line || !/\S/.test(line.string)
  16426. }
  16427. // Blocks
  16428. function blankLine(state) {
  16429. // Reset linkTitle state
  16430. state.linkTitle = false;
  16431. state.linkHref = false;
  16432. state.linkText = false;
  16433. // Reset EM state
  16434. state.em = false;
  16435. // Reset STRONG state
  16436. state.strong = false;
  16437. // Reset strikethrough state
  16438. state.strikethrough = false;
  16439. // Reset state.quote
  16440. state.quote = 0;
  16441. // Reset state.indentedCode
  16442. state.indentedCode = false;
  16443. if (state.f == htmlBlock) {
  16444. var exit = htmlModeMissing
  16445. if (!exit) {
  16446. var inner = CodeMirror.innerMode(htmlMode, state.htmlState)
  16447. exit = inner.mode.name == "xml" && inner.state.tagStart === null &&
  16448. (!inner.state.context && inner.state.tokenize.isInText)
  16449. }
  16450. if (exit) {
  16451. state.f = inlineNormal;
  16452. state.block = blockNormal;
  16453. state.htmlState = null;
  16454. }
  16455. }
  16456. // Reset state.trailingSpace
  16457. state.trailingSpace = 0;
  16458. state.trailingSpaceNewLine = false;
  16459. // Mark this line as blank
  16460. state.prevLine = state.thisLine
  16461. state.thisLine = {stream: null}
  16462. return null;
  16463. }
  16464. function blockNormal(stream, state) {
  16465. var firstTokenOnLine = stream.column() === state.indentation;
  16466. var prevLineLineIsEmpty = lineIsEmpty(state.prevLine.stream);
  16467. var prevLineIsIndentedCode = state.indentedCode;
  16468. var prevLineIsHr = state.prevLine.hr;
  16469. var prevLineIsList = state.list !== false;
  16470. var maxNonCodeIndentation = (state.listStack[state.listStack.length - 1] || 0) + 3;
  16471. state.indentedCode = false;
  16472. var lineIndentation = state.indentation;
  16473. // compute once per line (on first token)
  16474. if (state.indentationDiff === null) {
  16475. state.indentationDiff = state.indentation;
  16476. if (prevLineIsList) {
  16477. state.list = null;
  16478. // While this list item's marker's indentation is less than the deepest
  16479. // list item's content's indentation,pop the deepest list item
  16480. // indentation off the stack, and update block indentation state
  16481. while (lineIndentation < state.listStack[state.listStack.length - 1]) {
  16482. state.listStack.pop();
  16483. if (state.listStack.length) {
  16484. state.indentation = state.listStack[state.listStack.length - 1];
  16485. // less than the first list's indent -> the line is no longer a list
  16486. } else {
  16487. state.list = false;
  16488. }
  16489. }
  16490. if (state.list !== false) {
  16491. state.indentationDiff = lineIndentation - state.listStack[state.listStack.length - 1]
  16492. }
  16493. }
  16494. }
  16495. // not comprehensive (currently only for setext detection purposes)
  16496. var allowsInlineContinuation = (
  16497. !prevLineLineIsEmpty && !prevLineIsHr && !state.prevLine.header &&
  16498. (!prevLineIsList || !prevLineIsIndentedCode) &&
  16499. !state.prevLine.fencedCodeEnd
  16500. );
  16501. var isHr = (state.list === false || prevLineIsHr || prevLineLineIsEmpty) &&
  16502. state.indentation <= maxNonCodeIndentation && stream.match(hrRE);
  16503. var match = null;
  16504. if (state.indentationDiff >= 4 && (prevLineIsIndentedCode || state.prevLine.fencedCodeEnd ||
  16505. state.prevLine.header || prevLineLineIsEmpty)) {
  16506. stream.skipToEnd();
  16507. state.indentedCode = true;
  16508. return tokenTypes.code;
  16509. } else if (stream.eatSpace()) {
  16510. return null;
  16511. } else if (firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(atxHeaderRE)) && match[1].length <= 6) {
  16512. state.quote = 0;
  16513. state.header = match[1].length;
  16514. state.thisLine.header = true;
  16515. if (modeCfg.highlightFormatting) state.formatting = "header";
  16516. state.f = state.inline;
  16517. return getType(state);
  16518. } else if (state.indentation <= maxNonCodeIndentation && stream.eat('>')) {
  16519. state.quote = firstTokenOnLine ? 1 : state.quote + 1;
  16520. if (modeCfg.highlightFormatting) state.formatting = "quote";
  16521. stream.eatSpace();
  16522. return getType(state);
  16523. } else if (!isHr && !state.setext && firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(listRE))) {
  16524. var listType = match[1] ? "ol" : "ul";
  16525. state.indentation = lineIndentation + stream.current().length;
  16526. state.list = true;
  16527. state.quote = 0;
  16528. // Add this list item's content's indentation to the stack
  16529. state.listStack.push(state.indentation);
  16530. // Reset inline styles which shouldn't propagate aross list items
  16531. state.em = false;
  16532. state.strong = false;
  16533. state.code = false;
  16534. state.strikethrough = false;
  16535. if (modeCfg.taskLists && stream.match(taskListRE, false)) {
  16536. state.taskList = true;
  16537. }
  16538. state.f = state.inline;
  16539. if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
  16540. return getType(state);
  16541. } else if (firstTokenOnLine && state.indentation <= maxNonCodeIndentation && (match = stream.match(fencedCodeRE, true))) {
  16542. state.quote = 0;
  16543. state.fencedEndRE = new RegExp(match[1] + "+ *$");
  16544. // try switching mode
  16545. state.localMode = modeCfg.fencedCodeBlockHighlighting && getMode(match[2] || modeCfg.fencedCodeBlockDefaultMode );
  16546. if (state.localMode) state.localState = CodeMirror.startState(state.localMode);
  16547. state.f = state.block = local;
  16548. if (modeCfg.highlightFormatting) state.formatting = "code-block";
  16549. state.code = -1
  16550. return getType(state);
  16551. // SETEXT has lowest block-scope precedence after HR, so check it after
  16552. // the others (code, blockquote, list...)
  16553. } else if (
  16554. // if setext set, indicates line after ---/===
  16555. state.setext || (
  16556. // line before ---/===
  16557. (!allowsInlineContinuation || !prevLineIsList) && !state.quote && state.list === false &&
  16558. !state.code && !isHr && !linkDefRE.test(stream.string) &&
  16559. (match = stream.lookAhead(1)) && (match = match.match(setextHeaderRE))
  16560. )
  16561. ) {
  16562. if ( !state.setext ) {
  16563. state.header = match[0].charAt(0) == '=' ? 1 : 2;
  16564. state.setext = state.header;
  16565. } else {
  16566. state.header = state.setext;
  16567. // has no effect on type so we can reset it now
  16568. state.setext = 0;
  16569. stream.skipToEnd();
  16570. if (modeCfg.highlightFormatting) state.formatting = "header";
  16571. }
  16572. state.thisLine.header = true;
  16573. state.f = state.inline;
  16574. return getType(state);
  16575. } else if (isHr) {
  16576. stream.skipToEnd();
  16577. state.hr = true;
  16578. state.thisLine.hr = true;
  16579. return tokenTypes.hr;
  16580. } else if (stream.peek() === '[') {
  16581. return switchInline(stream, state, footnoteLink);
  16582. }
  16583. return switchInline(stream, state, state.inline);
  16584. }
  16585. function htmlBlock(stream, state) {
  16586. var style = htmlMode.token(stream, state.htmlState);
  16587. if (!htmlModeMissing) {
  16588. var inner = CodeMirror.innerMode(htmlMode, state.htmlState)
  16589. if ((inner.mode.name == "xml" && inner.state.tagStart === null &&
  16590. (!inner.state.context && inner.state.tokenize.isInText)) ||
  16591. (state.md_inside && stream.current().indexOf(">") > -1)) {
  16592. state.f = inlineNormal;
  16593. state.block = blockNormal;
  16594. state.htmlState = null;
  16595. }
  16596. }
  16597. return style;
  16598. }
  16599. function local(stream, state) {
  16600. var currListInd = state.listStack[state.listStack.length - 1] || 0;
  16601. var hasExitedList = state.indentation < currListInd;
  16602. var maxFencedEndInd = currListInd + 3;
  16603. if (state.fencedEndRE && state.indentation <= maxFencedEndInd && (hasExitedList || stream.match(state.fencedEndRE))) {
  16604. if (modeCfg.highlightFormatting) state.formatting = "code-block";
  16605. var returnType;
  16606. if (!hasExitedList) returnType = getType(state)
  16607. state.localMode = state.localState = null;
  16608. state.block = blockNormal;
  16609. state.f = inlineNormal;
  16610. state.fencedEndRE = null;
  16611. state.code = 0
  16612. state.thisLine.fencedCodeEnd = true;
  16613. if (hasExitedList) return switchBlock(stream, state, state.block);
  16614. return returnType;
  16615. } else if (state.localMode) {
  16616. return state.localMode.token(stream, state.localState);
  16617. } else {
  16618. stream.skipToEnd();
  16619. return tokenTypes.code;
  16620. }
  16621. }
  16622. // Inline
  16623. function getType(state) {
  16624. var styles = [];
  16625. if (state.formatting) {
  16626. styles.push(tokenTypes.formatting);
  16627. if (typeof state.formatting === "string") state.formatting = [state.formatting];
  16628. for (var i = 0; i < state.formatting.length; i++) {
  16629. styles.push(tokenTypes.formatting + "-" + state.formatting[i]);
  16630. if (state.formatting[i] === "header") {
  16631. styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.header);
  16632. }
  16633. // Add `formatting-quote` and `formatting-quote-#` for blockquotes
  16634. // Add `error` instead if the maximum blockquote nesting depth is passed
  16635. if (state.formatting[i] === "quote") {
  16636. if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
  16637. styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.quote);
  16638. } else {
  16639. styles.push("error");
  16640. }
  16641. }
  16642. }
  16643. }
  16644. if (state.taskOpen) {
  16645. styles.push("meta");
  16646. return styles.length ? styles.join(' ') : null;
  16647. }
  16648. if (state.taskClosed) {
  16649. styles.push("property");
  16650. return styles.length ? styles.join(' ') : null;
  16651. }
  16652. if (state.linkHref) {
  16653. styles.push(tokenTypes.linkHref, "url");
  16654. } else { // Only apply inline styles to non-url text
  16655. if (state.strong) { styles.push(tokenTypes.strong); }
  16656. if (state.em) { styles.push(tokenTypes.em); }
  16657. if (state.strikethrough) { styles.push(tokenTypes.strikethrough); }
  16658. if (state.emoji) { styles.push(tokenTypes.emoji); }
  16659. if (state.linkText) { styles.push(tokenTypes.linkText); }
  16660. if (state.code) { styles.push(tokenTypes.code); }
  16661. if (state.image) { styles.push(tokenTypes.image); }
  16662. if (state.imageAltText) { styles.push(tokenTypes.imageAltText, "link"); }
  16663. if (state.imageMarker) { styles.push(tokenTypes.imageMarker); }
  16664. }
  16665. if (state.header) { styles.push(tokenTypes.header, tokenTypes.header + "-" + state.header); }
  16666. if (state.quote) {
  16667. styles.push(tokenTypes.quote);
  16668. // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
  16669. if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
  16670. styles.push(tokenTypes.quote + "-" + state.quote);
  16671. } else {
  16672. styles.push(tokenTypes.quote + "-" + modeCfg.maxBlockquoteDepth);
  16673. }
  16674. }
  16675. if (state.list !== false) {
  16676. var listMod = (state.listStack.length - 1) % 3;
  16677. if (!listMod) {
  16678. styles.push(tokenTypes.list1);
  16679. } else if (listMod === 1) {
  16680. styles.push(tokenTypes.list2);
  16681. } else {
  16682. styles.push(tokenTypes.list3);
  16683. }
  16684. }
  16685. if (state.trailingSpaceNewLine) {
  16686. styles.push("trailing-space-new-line");
  16687. } else if (state.trailingSpace) {
  16688. styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b"));
  16689. }
  16690. return styles.length ? styles.join(' ') : null;
  16691. }
  16692. function handleText(stream, state) {
  16693. if (stream.match(textRE, true)) {
  16694. return getType(state);
  16695. }
  16696. return undefined;
  16697. }
  16698. function inlineNormal(stream, state) {
  16699. var style = state.text(stream, state);
  16700. if (typeof style !== 'undefined')
  16701. return style;
  16702. if (state.list) { // List marker (*, +, -, 1., etc)
  16703. state.list = null;
  16704. return getType(state);
  16705. }
  16706. if (state.taskList) {
  16707. var taskOpen = stream.match(taskListRE, true)[1] === " ";
  16708. if (taskOpen) state.taskOpen = true;
  16709. else state.taskClosed = true;
  16710. if (modeCfg.highlightFormatting) state.formatting = "task";
  16711. state.taskList = false;
  16712. return getType(state);
  16713. }
  16714. state.taskOpen = false;
  16715. state.taskClosed = false;
  16716. if (state.header && stream.match(/^#+$/, true)) {
  16717. if (modeCfg.highlightFormatting) state.formatting = "header";
  16718. return getType(state);
  16719. }
  16720. var ch = stream.next();
  16721. // Matches link titles present on next line
  16722. if (state.linkTitle) {
  16723. state.linkTitle = false;
  16724. var matchCh = ch;
  16725. if (ch === '(') {
  16726. matchCh = ')';
  16727. }
  16728. matchCh = (matchCh+'').replace(/([.?*+^\[\]\\(){}|-])/g, "\\$1");
  16729. var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh;
  16730. if (stream.match(new RegExp(regex), true)) {
  16731. return tokenTypes.linkHref;
  16732. }
  16733. }
  16734. // If this block is changed, it may need to be updated in GFM mode
  16735. if (ch === '`') {
  16736. var previousFormatting = state.formatting;
  16737. if (modeCfg.highlightFormatting) state.formatting = "code";
  16738. stream.eatWhile('`');
  16739. var count = stream.current().length
  16740. if (state.code == 0 && (!state.quote || count == 1)) {
  16741. state.code = count
  16742. return getType(state)
  16743. } else if (count == state.code) { // Must be exact
  16744. var t = getType(state)
  16745. state.code = 0
  16746. return t
  16747. } else {
  16748. state.formatting = previousFormatting
  16749. return getType(state)
  16750. }
  16751. } else if (state.code) {
  16752. return getType(state);
  16753. }
  16754. if (ch === '\\') {
  16755. stream.next();
  16756. if (modeCfg.highlightFormatting) {
  16757. var type = getType(state);
  16758. var formattingEscape = tokenTypes.formatting + "-escape";
  16759. return type ? type + " " + formattingEscape : formattingEscape;
  16760. }
  16761. }
  16762. if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
  16763. state.imageMarker = true;
  16764. state.image = true;
  16765. if (modeCfg.highlightFormatting) state.formatting = "image";
  16766. return getType(state);
  16767. }
  16768. if (ch === '[' && state.imageMarker && stream.match(/[^\]]*\](\(.*?\)| ?\[.*?\])/, false)) {
  16769. state.imageMarker = false;
  16770. state.imageAltText = true
  16771. if (modeCfg.highlightFormatting) state.formatting = "image";
  16772. return getType(state);
  16773. }
  16774. if (ch === ']' && state.imageAltText) {
  16775. if (modeCfg.highlightFormatting) state.formatting = "image";
  16776. var type = getType(state);
  16777. state.imageAltText = false;
  16778. state.image = false;
  16779. state.inline = state.f = linkHref;
  16780. return type;
  16781. }
  16782. if (ch === '[' && !state.image) {
  16783. if (state.linkText && stream.match(/^.*?\]/)) return getType(state)
  16784. state.linkText = true;
  16785. if (modeCfg.highlightFormatting) state.formatting = "link";
  16786. return getType(state);
  16787. }
  16788. if (ch === ']' && state.linkText) {
  16789. if (modeCfg.highlightFormatting) state.formatting = "link";
  16790. var type = getType(state);
  16791. state.linkText = false;
  16792. state.inline = state.f = stream.match(/\(.*?\)| ?\[.*?\]/, false) ? linkHref : inlineNormal
  16793. return type;
  16794. }
  16795. if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) {
  16796. state.f = state.inline = linkInline;
  16797. if (modeCfg.highlightFormatting) state.formatting = "link";
  16798. var type = getType(state);
  16799. if (type){
  16800. type += " ";
  16801. } else {
  16802. type = "";
  16803. }
  16804. return type + tokenTypes.linkInline;
  16805. }
  16806. if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
  16807. state.f = state.inline = linkInline;
  16808. if (modeCfg.highlightFormatting) state.formatting = "link";
  16809. var type = getType(state);
  16810. if (type){
  16811. type += " ";
  16812. } else {
  16813. type = "";
  16814. }
  16815. return type + tokenTypes.linkEmail;
  16816. }
  16817. if (modeCfg.xml && ch === '<' && stream.match(/^(!--|\?|!\[CDATA\[|[a-z][a-z0-9-]*(?:\s+[a-z_:.\-]+(?:\s*=\s*[^>]+)?)*\s*(?:>|$))/i, false)) {
  16818. var end = stream.string.indexOf(">", stream.pos);
  16819. if (end != -1) {
  16820. var atts = stream.string.substring(stream.start, end);
  16821. if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) state.md_inside = true;
  16822. }
  16823. stream.backUp(1);
  16824. state.htmlState = CodeMirror.startState(htmlMode);
  16825. return switchBlock(stream, state, htmlBlock);
  16826. }
  16827. if (modeCfg.xml && ch === '<' && stream.match(/^\/\w*?>/)) {
  16828. state.md_inside = false;
  16829. return "tag";
  16830. } else if (ch === "*" || ch === "_") {
  16831. var len = 1, before = stream.pos == 1 ? " " : stream.string.charAt(stream.pos - 2)
  16832. while (len < 3 && stream.eat(ch)) len++
  16833. var after = stream.peek() || " "
  16834. // See http://spec.commonmark.org/0.27/#emphasis-and-strong-emphasis
  16835. var leftFlanking = !/\s/.test(after) && (!punctuation.test(after) || /\s/.test(before) || punctuation.test(before))
  16836. var rightFlanking = !/\s/.test(before) && (!punctuation.test(before) || /\s/.test(after) || punctuation.test(after))
  16837. var setEm = null, setStrong = null
  16838. if (len % 2) { // Em
  16839. if (!state.em && leftFlanking && (ch === "*" || !rightFlanking || punctuation.test(before)))
  16840. setEm = true
  16841. else if (state.em == ch && rightFlanking && (ch === "*" || !leftFlanking || punctuation.test(after)))
  16842. setEm = false
  16843. }
  16844. if (len > 1) { // Strong
  16845. if (!state.strong && leftFlanking && (ch === "*" || !rightFlanking || punctuation.test(before)))
  16846. setStrong = true
  16847. else if (state.strong == ch && rightFlanking && (ch === "*" || !leftFlanking || punctuation.test(after)))
  16848. setStrong = false
  16849. }
  16850. if (setStrong != null || setEm != null) {
  16851. if (modeCfg.highlightFormatting) state.formatting = setEm == null ? "strong" : setStrong == null ? "em" : "strong em"
  16852. if (setEm === true) state.em = ch
  16853. if (setStrong === true) state.strong = ch
  16854. var t = getType(state)
  16855. if (setEm === false) state.em = false
  16856. if (setStrong === false) state.strong = false
  16857. return t
  16858. }
  16859. } else if (ch === ' ') {
  16860. if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces
  16861. if (stream.peek() === ' ') { // Surrounded by spaces, ignore
  16862. return getType(state);
  16863. } else { // Not surrounded by spaces, back up pointer
  16864. stream.backUp(1);
  16865. }
  16866. }
  16867. }
  16868. if (modeCfg.strikethrough) {
  16869. if (ch === '~' && stream.eatWhile(ch)) {
  16870. if (state.strikethrough) {// Remove strikethrough
  16871. if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
  16872. var t = getType(state);
  16873. state.strikethrough = false;
  16874. return t;
  16875. } else if (stream.match(/^[^\s]/, false)) {// Add strikethrough
  16876. state.strikethrough = true;
  16877. if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
  16878. return getType(state);
  16879. }
  16880. } else if (ch === ' ') {
  16881. if (stream.match(/^~~/, true)) { // Probably surrounded by space
  16882. if (stream.peek() === ' ') { // Surrounded by spaces, ignore
  16883. return getType(state);
  16884. } else { // Not surrounded by spaces, back up pointer
  16885. stream.backUp(2);
  16886. }
  16887. }
  16888. }
  16889. }
  16890. if (modeCfg.emoji && ch === ":" && stream.match(/^(?:[a-z_\d+][a-z_\d+-]*|\-[a-z_\d+][a-z_\d+-]*):/)) {
  16891. state.emoji = true;
  16892. if (modeCfg.highlightFormatting) state.formatting = "emoji";
  16893. var retType = getType(state);
  16894. state.emoji = false;
  16895. return retType;
  16896. }
  16897. if (ch === ' ') {
  16898. if (stream.match(/^ +$/, false)) {
  16899. state.trailingSpace++;
  16900. } else if (state.trailingSpace) {
  16901. state.trailingSpaceNewLine = true;
  16902. }
  16903. }
  16904. return getType(state);
  16905. }
  16906. function linkInline(stream, state) {
  16907. var ch = stream.next();
  16908. if (ch === ">") {
  16909. state.f = state.inline = inlineNormal;
  16910. if (modeCfg.highlightFormatting) state.formatting = "link";
  16911. var type = getType(state);
  16912. if (type){
  16913. type += " ";
  16914. } else {
  16915. type = "";
  16916. }
  16917. return type + tokenTypes.linkInline;
  16918. }
  16919. stream.match(/^[^>]+/, true);
  16920. return tokenTypes.linkInline;
  16921. }
  16922. function linkHref(stream, state) {
  16923. // Check if space, and return NULL if so (to avoid marking the space)
  16924. if(stream.eatSpace()){
  16925. return null;
  16926. }
  16927. var ch = stream.next();
  16928. if (ch === '(' || ch === '[') {
  16929. state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]");
  16930. if (modeCfg.highlightFormatting) state.formatting = "link-string";
  16931. state.linkHref = true;
  16932. return getType(state);
  16933. }
  16934. return 'error';
  16935. }
  16936. var linkRE = {
  16937. ")": /^(?:[^\\\(\)]|\\.|\((?:[^\\\(\)]|\\.)*\))*?(?=\))/,
  16938. "]": /^(?:[^\\\[\]]|\\.|\[(?:[^\\\[\]]|\\.)*\])*?(?=\])/
  16939. }
  16940. function getLinkHrefInside(endChar) {
  16941. return function(stream, state) {
  16942. var ch = stream.next();
  16943. if (ch === endChar) {
  16944. state.f = state.inline = inlineNormal;
  16945. if (modeCfg.highlightFormatting) state.formatting = "link-string";
  16946. var returnState = getType(state);
  16947. state.linkHref = false;
  16948. return returnState;
  16949. }
  16950. stream.match(linkRE[endChar])
  16951. state.linkHref = true;
  16952. return getType(state);
  16953. };
  16954. }
  16955. function footnoteLink(stream, state) {
  16956. if (stream.match(/^([^\]\\]|\\.)*\]:/, false)) {
  16957. state.f = footnoteLinkInside;
  16958. stream.next(); // Consume [
  16959. if (modeCfg.highlightFormatting) state.formatting = "link";
  16960. state.linkText = true;
  16961. return getType(state);
  16962. }
  16963. return switchInline(stream, state, inlineNormal);
  16964. }
  16965. function footnoteLinkInside(stream, state) {
  16966. if (stream.match(/^\]:/, true)) {
  16967. state.f = state.inline = footnoteUrl;
  16968. if (modeCfg.highlightFormatting) state.formatting = "link";
  16969. var returnType = getType(state);
  16970. state.linkText = false;
  16971. return returnType;
  16972. }
  16973. stream.match(/^([^\]\\]|\\.)+/, true);
  16974. return tokenTypes.linkText;
  16975. }
  16976. function footnoteUrl(stream, state) {
  16977. // Check if space, and return NULL if so (to avoid marking the space)
  16978. if(stream.eatSpace()){
  16979. return null;
  16980. }
  16981. // Match URL
  16982. stream.match(/^[^\s]+/, true);
  16983. // Check for link title
  16984. if (stream.peek() === undefined) { // End of line, set flag to check next line
  16985. state.linkTitle = true;
  16986. } else { // More content on line, check if link title
  16987. stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true);
  16988. }
  16989. state.f = state.inline = inlineNormal;
  16990. return tokenTypes.linkHref + " url";
  16991. }
  16992. var mode = {
  16993. startState: function() {
  16994. return {
  16995. f: blockNormal,
  16996. prevLine: {stream: null},
  16997. thisLine: {stream: null},
  16998. block: blockNormal,
  16999. htmlState: null,
  17000. indentation: 0,
  17001. inline: inlineNormal,
  17002. text: handleText,
  17003. formatting: false,
  17004. linkText: false,
  17005. linkHref: false,
  17006. linkTitle: false,
  17007. code: 0,
  17008. em: false,
  17009. strong: false,
  17010. header: 0,
  17011. setext: 0,
  17012. hr: false,
  17013. taskList: false,
  17014. list: false,
  17015. listStack: [],
  17016. quote: 0,
  17017. trailingSpace: 0,
  17018. trailingSpaceNewLine: false,
  17019. strikethrough: false,
  17020. emoji: false,
  17021. fencedEndRE: null
  17022. };
  17023. },
  17024. copyState: function(s) {
  17025. return {
  17026. f: s.f,
  17027. prevLine: s.prevLine,
  17028. thisLine: s.thisLine,
  17029. block: s.block,
  17030. htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
  17031. indentation: s.indentation,
  17032. localMode: s.localMode,
  17033. localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,
  17034. inline: s.inline,
  17035. text: s.text,
  17036. formatting: false,
  17037. linkText: s.linkText,
  17038. linkTitle: s.linkTitle,
  17039. linkHref: s.linkHref,
  17040. code: s.code,
  17041. em: s.em,
  17042. strong: s.strong,
  17043. strikethrough: s.strikethrough,
  17044. emoji: s.emoji,
  17045. header: s.header,
  17046. setext: s.setext,
  17047. hr: s.hr,
  17048. taskList: s.taskList,
  17049. list: s.list,
  17050. listStack: s.listStack.slice(0),
  17051. quote: s.quote,
  17052. indentedCode: s.indentedCode,
  17053. trailingSpace: s.trailingSpace,
  17054. trailingSpaceNewLine: s.trailingSpaceNewLine,
  17055. md_inside: s.md_inside,
  17056. fencedEndRE: s.fencedEndRE
  17057. };
  17058. },
  17059. token: function(stream, state) {
  17060. // Reset state.formatting
  17061. state.formatting = false;
  17062. if (stream != state.thisLine.stream) {
  17063. state.header = 0;
  17064. state.hr = false;
  17065. if (stream.match(/^\s*$/, true)) {
  17066. blankLine(state);
  17067. return null;
  17068. }
  17069. state.prevLine = state.thisLine
  17070. state.thisLine = {stream: stream}
  17071. // Reset state.taskList
  17072. state.taskList = false;
  17073. // Reset state.trailingSpace
  17074. state.trailingSpace = 0;
  17075. state.trailingSpaceNewLine = false;
  17076. if (!state.localState) {
  17077. state.f = state.block;
  17078. if (state.f != htmlBlock) {
  17079. var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, expandedTab).length;
  17080. state.indentation = indentation;
  17081. state.indentationDiff = null;
  17082. if (indentation > 0) return null;
  17083. }
  17084. }
  17085. }
  17086. return state.f(stream, state);
  17087. },
  17088. innerMode: function(state) {
  17089. if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode};
  17090. if (state.localState) return {state: state.localState, mode: state.localMode};
  17091. return {state: state, mode: mode};
  17092. },
  17093. indent: function(state, textAfter, line) {
  17094. if (state.block == htmlBlock && htmlMode.indent) return htmlMode.indent(state.htmlState, textAfter, line)
  17095. if (state.localState && state.localMode.indent) return state.localMode.indent(state.localState, textAfter, line)
  17096. return CodeMirror.Pass
  17097. },
  17098. blankLine: blankLine,
  17099. getType: getType,
  17100. blockCommentStart: "<!--",
  17101. blockCommentEnd: "-->",
  17102. closeBrackets: "()[]{}''\"\"``",
  17103. fold: "markdown"
  17104. };
  17105. return mode;
  17106. }, "xml");
  17107. CodeMirror.defineMIME("text/markdown", "markdown");
  17108. CodeMirror.defineMIME("text/x-markdown", "markdown");
  17109. });
  17110. /* ---- mode/python.js ---- */
  17111. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  17112. // Distributed under an MIT license: https://codemirror.net/LICENSE
  17113. (function(mod) {
  17114. if (typeof exports == "object" && typeof module == "object") // CommonJS
  17115. mod(require("../../lib/codemirror"));
  17116. else if (typeof define == "function" && define.amd) // AMD
  17117. define(["../../lib/codemirror"], mod);
  17118. else // Plain browser env
  17119. mod(CodeMirror);
  17120. })(function(CodeMirror) {
  17121. "use strict";
  17122. function wordRegexp(words) {
  17123. return new RegExp("^((" + words.join(")|(") + "))\\b");
  17124. }
  17125. var wordOperators = wordRegexp(["and", "or", "not", "is"]);
  17126. var commonKeywords = ["as", "assert", "break", "class", "continue",
  17127. "def", "del", "elif", "else", "except", "finally",
  17128. "for", "from", "global", "if", "import",
  17129. "lambda", "pass", "raise", "return",
  17130. "try", "while", "with", "yield", "in"];
  17131. var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr",
  17132. "classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod",
  17133. "enumerate", "eval", "filter", "float", "format", "frozenset",
  17134. "getattr", "globals", "hasattr", "hash", "help", "hex", "id",
  17135. "input", "int", "isinstance", "issubclass", "iter", "len",
  17136. "list", "locals", "map", "max", "memoryview", "min", "next",
  17137. "object", "oct", "open", "ord", "pow", "property", "range",
  17138. "repr", "reversed", "round", "set", "setattr", "slice",
  17139. "sorted", "staticmethod", "str", "sum", "super", "tuple",
  17140. "type", "vars", "zip", "__import__", "NotImplemented",
  17141. "Ellipsis", "__debug__"];
  17142. CodeMirror.registerHelper("hintWords", "python", commonKeywords.concat(commonBuiltins));
  17143. function top(state) {
  17144. return state.scopes[state.scopes.length - 1];
  17145. }
  17146. CodeMirror.defineMode("python", function(conf, parserConf) {
  17147. var ERRORCLASS = "error";
  17148. var delimiters = parserConf.delimiters || parserConf.singleDelimiters || /^[\(\)\[\]\{\}@,:`=;\.\\]/;
  17149. // (Backwards-compatibility with old, cumbersome config system)
  17150. var operators = [parserConf.singleOperators, parserConf.doubleOperators, parserConf.doubleDelimiters, parserConf.tripleDelimiters,
  17151. parserConf.operators || /^([-+*/%\/&|^]=?|[<>=]+|\/\/=?|\*\*=?|!=|[~!@]|\.\.\.)/]
  17152. for (var i = 0; i < operators.length; i++) if (!operators[i]) operators.splice(i--, 1)
  17153. var hangingIndent = parserConf.hangingIndent || conf.indentUnit;
  17154. var myKeywords = commonKeywords, myBuiltins = commonBuiltins;
  17155. if (parserConf.extra_keywords != undefined)
  17156. myKeywords = myKeywords.concat(parserConf.extra_keywords);
  17157. if (parserConf.extra_builtins != undefined)
  17158. myBuiltins = myBuiltins.concat(parserConf.extra_builtins);
  17159. var py3 = !(parserConf.version && Number(parserConf.version) < 3)
  17160. if (py3) {
  17161. // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator
  17162. var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*/;
  17163. myKeywords = myKeywords.concat(["nonlocal", "False", "True", "None", "async", "await"]);
  17164. myBuiltins = myBuiltins.concat(["ascii", "bytes", "exec", "print"]);
  17165. var stringPrefixes = new RegExp("^(([rbuf]|(br)|(fr))?('{3}|\"{3}|['\"]))", "i");
  17166. } else {
  17167. var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/;
  17168. myKeywords = myKeywords.concat(["exec", "print"]);
  17169. myBuiltins = myBuiltins.concat(["apply", "basestring", "buffer", "cmp", "coerce", "execfile",
  17170. "file", "intern", "long", "raw_input", "reduce", "reload",
  17171. "unichr", "unicode", "xrange", "False", "True", "None"]);
  17172. var stringPrefixes = new RegExp("^(([rubf]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i");
  17173. }
  17174. var keywords = wordRegexp(myKeywords);
  17175. var builtins = wordRegexp(myBuiltins);
  17176. // tokenizers
  17177. function tokenBase(stream, state) {
  17178. var sol = stream.sol() && state.lastToken != "\\"
  17179. if (sol) state.indent = stream.indentation()
  17180. // Handle scope changes
  17181. if (sol && top(state).type == "py") {
  17182. var scopeOffset = top(state).offset;
  17183. if (stream.eatSpace()) {
  17184. var lineOffset = stream.indentation();
  17185. if (lineOffset > scopeOffset)
  17186. pushPyScope(state);
  17187. else if (lineOffset < scopeOffset && dedent(stream, state) && stream.peek() != "#")
  17188. state.errorToken = true;
  17189. return null;
  17190. } else {
  17191. var style = tokenBaseInner(stream, state);
  17192. if (scopeOffset > 0 && dedent(stream, state))
  17193. style += " " + ERRORCLASS;
  17194. return style;
  17195. }
  17196. }
  17197. return tokenBaseInner(stream, state);
  17198. }
  17199. function tokenBaseInner(stream, state, inFormat) {
  17200. if (stream.eatSpace()) return null;
  17201. // Handle Comments
  17202. if (!inFormat && stream.match(/^#.*/)) return "comment";
  17203. // Handle Number Literals
  17204. if (stream.match(/^[0-9\.]/, false)) {
  17205. var floatLiteral = false;
  17206. // Floats
  17207. if (stream.match(/^[\d_]*\.\d+(e[\+\-]?\d+)?/i)) { floatLiteral = true; }
  17208. if (stream.match(/^[\d_]+\.\d*/)) { floatLiteral = true; }
  17209. if (stream.match(/^\.\d+/)) { floatLiteral = true; }
  17210. if (floatLiteral) {
  17211. // Float literals may be "imaginary"
  17212. stream.eat(/J/i);
  17213. return "number";
  17214. }
  17215. // Integers
  17216. var intLiteral = false;
  17217. // Hex
  17218. if (stream.match(/^0x[0-9a-f_]+/i)) intLiteral = true;
  17219. // Binary
  17220. if (stream.match(/^0b[01_]+/i)) intLiteral = true;
  17221. // Octal
  17222. if (stream.match(/^0o[0-7_]+/i)) intLiteral = true;
  17223. // Decimal
  17224. if (stream.match(/^[1-9][\d_]*(e[\+\-]?[\d_]+)?/)) {
  17225. // Decimal literals may be "imaginary"
  17226. stream.eat(/J/i);
  17227. // TODO - Can you have imaginary longs?
  17228. intLiteral = true;
  17229. }
  17230. // Zero by itself with no other piece of number.
  17231. if (stream.match(/^0(?![\dx])/i)) intLiteral = true;
  17232. if (intLiteral) {
  17233. // Integer literals may be "long"
  17234. stream.eat(/L/i);
  17235. return "number";
  17236. }
  17237. }
  17238. // Handle Strings
  17239. if (stream.match(stringPrefixes)) {
  17240. var isFmtString = stream.current().toLowerCase().indexOf('f') !== -1;
  17241. if (!isFmtString) {
  17242. state.tokenize = tokenStringFactory(stream.current(), state.tokenize);
  17243. return state.tokenize(stream, state);
  17244. } else {
  17245. state.tokenize = formatStringFactory(stream.current(), state.tokenize);
  17246. return state.tokenize(stream, state);
  17247. }
  17248. }
  17249. for (var i = 0; i < operators.length; i++)
  17250. if (stream.match(operators[i])) return "operator"
  17251. if (stream.match(delimiters)) return "punctuation";
  17252. if (state.lastToken == "." && stream.match(identifiers))
  17253. return "property";
  17254. if (stream.match(keywords) || stream.match(wordOperators))
  17255. return "keyword";
  17256. if (stream.match(builtins))
  17257. return "builtin";
  17258. if (stream.match(/^(self|cls)\b/))
  17259. return "variable-2";
  17260. if (stream.match(identifiers)) {
  17261. if (state.lastToken == "def" || state.lastToken == "class")
  17262. return "def";
  17263. return "variable";
  17264. }
  17265. // Handle non-detected items
  17266. stream.next();
  17267. return inFormat ? null :ERRORCLASS;
  17268. }
  17269. function formatStringFactory(delimiter, tokenOuter) {
  17270. while ("rubf".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)
  17271. delimiter = delimiter.substr(1);
  17272. var singleline = delimiter.length == 1;
  17273. var OUTCLASS = "string";
  17274. function tokenNestedExpr(depth) {
  17275. return function(stream, state) {
  17276. var inner = tokenBaseInner(stream, state, true)
  17277. if (inner == "punctuation") {
  17278. if (stream.current() == "{") {
  17279. state.tokenize = tokenNestedExpr(depth + 1)
  17280. } else if (stream.current() == "}") {
  17281. if (depth > 1) state.tokenize = tokenNestedExpr(depth - 1)
  17282. else state.tokenize = tokenString
  17283. }
  17284. }
  17285. return inner
  17286. }
  17287. }
  17288. function tokenString(stream, state) {
  17289. while (!stream.eol()) {
  17290. stream.eatWhile(/[^'"\{\}\\]/);
  17291. if (stream.eat("\\")) {
  17292. stream.next();
  17293. if (singleline && stream.eol())
  17294. return OUTCLASS;
  17295. } else if (stream.match(delimiter)) {
  17296. state.tokenize = tokenOuter;
  17297. return OUTCLASS;
  17298. } else if (stream.match('{{')) {
  17299. // ignore {{ in f-str
  17300. return OUTCLASS;
  17301. } else if (stream.match('{', false)) {
  17302. // switch to nested mode
  17303. state.tokenize = tokenNestedExpr(0)
  17304. if (stream.current()) return OUTCLASS;
  17305. else return state.tokenize(stream, state)
  17306. } else if (stream.match('}}')) {
  17307. return OUTCLASS;
  17308. } else if (stream.match('}')) {
  17309. // single } in f-string is an error
  17310. return ERRORCLASS;
  17311. } else {
  17312. stream.eat(/['"]/);
  17313. }
  17314. }
  17315. if (singleline) {
  17316. if (parserConf.singleLineStringErrors)
  17317. return ERRORCLASS;
  17318. else
  17319. state.tokenize = tokenOuter;
  17320. }
  17321. return OUTCLASS;
  17322. }
  17323. tokenString.isString = true;
  17324. return tokenString;
  17325. }
  17326. function tokenStringFactory(delimiter, tokenOuter) {
  17327. while ("rubf".indexOf(delimiter.charAt(0).toLowerCase()) >= 0)
  17328. delimiter = delimiter.substr(1);
  17329. var singleline = delimiter.length == 1;
  17330. var OUTCLASS = "string";
  17331. function tokenString(stream, state) {
  17332. while (!stream.eol()) {
  17333. stream.eatWhile(/[^'"\\]/);
  17334. if (stream.eat("\\")) {
  17335. stream.next();
  17336. if (singleline && stream.eol())
  17337. return OUTCLASS;
  17338. } else if (stream.match(delimiter)) {
  17339. state.tokenize = tokenOuter;
  17340. return OUTCLASS;
  17341. } else {
  17342. stream.eat(/['"]/);
  17343. }
  17344. }
  17345. if (singleline) {
  17346. if (parserConf.singleLineStringErrors)
  17347. return ERRORCLASS;
  17348. else
  17349. state.tokenize = tokenOuter;
  17350. }
  17351. return OUTCLASS;
  17352. }
  17353. tokenString.isString = true;
  17354. return tokenString;
  17355. }
  17356. function pushPyScope(state) {
  17357. while (top(state).type != "py") state.scopes.pop()
  17358. state.scopes.push({offset: top(state).offset + conf.indentUnit,
  17359. type: "py",
  17360. align: null})
  17361. }
  17362. function pushBracketScope(stream, state, type) {
  17363. var align = stream.match(/^([\s\[\{\(]|#.*)*$/, false) ? null : stream.column() + 1
  17364. state.scopes.push({offset: state.indent + hangingIndent,
  17365. type: type,
  17366. align: align})
  17367. }
  17368. function dedent(stream, state) {
  17369. var indented = stream.indentation();
  17370. while (state.scopes.length > 1 && top(state).offset > indented) {
  17371. if (top(state).type != "py") return true;
  17372. state.scopes.pop();
  17373. }
  17374. return top(state).offset != indented;
  17375. }
  17376. function tokenLexer(stream, state) {
  17377. if (stream.sol()) state.beginningOfLine = true;
  17378. var style = state.tokenize(stream, state);
  17379. var current = stream.current();
  17380. // Handle decorators
  17381. if (state.beginningOfLine && current == "@")
  17382. return stream.match(identifiers, false) ? "meta" : py3 ? "operator" : ERRORCLASS;
  17383. if (/\S/.test(current)) state.beginningOfLine = false;
  17384. if ((style == "variable" || style == "builtin")
  17385. && state.lastToken == "meta")
  17386. style = "meta";
  17387. // Handle scope changes.
  17388. if (current == "pass" || current == "return")
  17389. state.dedent += 1;
  17390. if (current == "lambda") state.lambda = true;
  17391. if (current == ":" && !state.lambda && top(state).type == "py")
  17392. pushPyScope(state);
  17393. if (current.length == 1 && !/string|comment/.test(style)) {
  17394. var delimiter_index = "[({".indexOf(current);
  17395. if (delimiter_index != -1)
  17396. pushBracketScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
  17397. delimiter_index = "])}".indexOf(current);
  17398. if (delimiter_index != -1) {
  17399. if (top(state).type == current) state.indent = state.scopes.pop().offset - hangingIndent
  17400. else return ERRORCLASS;
  17401. }
  17402. }
  17403. if (state.dedent > 0 && stream.eol() && top(state).type == "py") {
  17404. if (state.scopes.length > 1) state.scopes.pop();
  17405. state.dedent -= 1;
  17406. }
  17407. return style;
  17408. }
  17409. var external = {
  17410. startState: function(basecolumn) {
  17411. return {
  17412. tokenize: tokenBase,
  17413. scopes: [{offset: basecolumn || 0, type: "py", align: null}],
  17414. indent: basecolumn || 0,
  17415. lastToken: null,
  17416. lambda: false,
  17417. dedent: 0
  17418. };
  17419. },
  17420. token: function(stream, state) {
  17421. var addErr = state.errorToken;
  17422. if (addErr) state.errorToken = false;
  17423. var style = tokenLexer(stream, state);
  17424. if (style && style != "comment")
  17425. state.lastToken = (style == "keyword" || style == "punctuation") ? stream.current() : style;
  17426. if (style == "punctuation") style = null;
  17427. if (stream.eol() && state.lambda)
  17428. state.lambda = false;
  17429. return addErr ? style + " " + ERRORCLASS : style;
  17430. },
  17431. indent: function(state, textAfter) {
  17432. if (state.tokenize != tokenBase)
  17433. return state.tokenize.isString ? CodeMirror.Pass : 0;
  17434. var scope = top(state), closing = scope.type == textAfter.charAt(0)
  17435. if (scope.align != null)
  17436. return scope.align - (closing ? 1 : 0)
  17437. else
  17438. return scope.offset - (closing ? hangingIndent : 0)
  17439. },
  17440. electricInput: /^\s*[\}\]\)]$/,
  17441. closeBrackets: {triples: "'\""},
  17442. lineComment: "#",
  17443. fold: "indent"
  17444. };
  17445. return external;
  17446. });
  17447. CodeMirror.defineMIME("text/x-python", "python");
  17448. var words = function(str) { return str.split(" "); };
  17449. CodeMirror.defineMIME("text/x-cython", {
  17450. name: "python",
  17451. extra_keywords: words("by cdef cimport cpdef ctypedef enum except "+
  17452. "extern gil include nogil property public "+
  17453. "readonly struct union DEF IF ELIF ELSE")
  17454. });
  17455. });
  17456. /* ---- mode/rust.js ---- */
  17457. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  17458. // Distributed under an MIT license: https://codemirror.net/LICENSE
  17459. (function(mod) {
  17460. if (typeof exports == "object" && typeof module == "object") // CommonJS
  17461. mod(require("../../lib/codemirror"), require("../../addon/mode/simple"));
  17462. else if (typeof define == "function" && define.amd) // AMD
  17463. define(["../../lib/codemirror", "../../addon/mode/simple"], mod);
  17464. else // Plain browser env
  17465. mod(CodeMirror);
  17466. })(function(CodeMirror) {
  17467. "use strict";
  17468. CodeMirror.defineSimpleMode("rust",{
  17469. start: [
  17470. // string and byte string
  17471. {regex: /b?"/, token: "string", next: "string"},
  17472. // raw string and raw byte string
  17473. {regex: /b?r"/, token: "string", next: "string_raw"},
  17474. {regex: /b?r#+"/, token: "string", next: "string_raw_hash"},
  17475. // character
  17476. {regex: /'(?:[^'\\]|\\(?:[nrt0'"]|x[\da-fA-F]{2}|u\{[\da-fA-F]{6}\}))'/, token: "string-2"},
  17477. // byte
  17478. {regex: /b'(?:[^']|\\(?:['\\nrt0]|x[\da-fA-F]{2}))'/, token: "string-2"},
  17479. {regex: /(?:(?:[0-9][0-9_]*)(?:(?:[Ee][+-]?[0-9_]+)|\.[0-9_]+(?:[Ee][+-]?[0-9_]+)?)(?:f32|f64)?)|(?:0(?:b[01_]+|(?:o[0-7_]+)|(?:x[0-9a-fA-F_]+))|(?:[0-9][0-9_]*))(?:u8|u16|u32|u64|i8|i16|i32|i64|isize|usize)?/,
  17480. token: "number"},
  17481. {regex: /(let(?:\s+mut)?|fn|enum|mod|struct|type|union)(\s+)([a-zA-Z_][a-zA-Z0-9_]*)/, token: ["keyword", null, "def"]},
  17482. {regex: /(?:abstract|alignof|as|async|await|box|break|continue|const|crate|do|dyn|else|enum|extern|fn|for|final|if|impl|in|loop|macro|match|mod|move|offsetof|override|priv|proc|pub|pure|ref|return|self|sizeof|static|struct|super|trait|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/, token: "keyword"},
  17483. {regex: /\b(?:Self|isize|usize|char|bool|u8|u16|u32|u64|f16|f32|f64|i8|i16|i32|i64|str|Option)\b/, token: "atom"},
  17484. {regex: /\b(?:true|false|Some|None|Ok|Err)\b/, token: "builtin"},
  17485. {regex: /\b(fn)(\s+)([a-zA-Z_][a-zA-Z0-9_]*)/,
  17486. token: ["keyword", null ,"def"]},
  17487. {regex: /#!?\[.*\]/, token: "meta"},
  17488. {regex: /\/\/.*/, token: "comment"},
  17489. {regex: /\/\*/, token: "comment", next: "comment"},
  17490. {regex: /[-+\/*=<>!]+/, token: "operator"},
  17491. {regex: /[a-zA-Z_]\w*!/,token: "variable-3"},
  17492. {regex: /[a-zA-Z_]\w*/, token: "variable"},
  17493. {regex: /[\{\[\(]/, indent: true},
  17494. {regex: /[\}\]\)]/, dedent: true}
  17495. ],
  17496. string: [
  17497. {regex: /"/, token: "string", next: "start"},
  17498. {regex: /(?:[^\\"]|\\(?:.|$))*/, token: "string"}
  17499. ],
  17500. string_raw: [
  17501. {regex: /"/, token: "string", next: "start"},
  17502. {regex: /[^"]*/, token: "string"}
  17503. ],
  17504. string_raw_hash: [
  17505. {regex: /"#+/, token: "string", next: "start"},
  17506. {regex: /(?:[^"]|"(?!#))*/, token: "string"}
  17507. ],
  17508. comment: [
  17509. {regex: /.*?\*\//, token: "comment", next: "start"},
  17510. {regex: /.*/, token: "comment"}
  17511. ],
  17512. meta: {
  17513. dontIndentStates: ["comment"],
  17514. electricInput: /^\s*\}$/,
  17515. blockCommentStart: "/*",
  17516. blockCommentEnd: "*/",
  17517. lineComment: "//",
  17518. fold: "brace"
  17519. }
  17520. });
  17521. CodeMirror.defineMIME("text/x-rustsrc", "rust");
  17522. CodeMirror.defineMIME("text/rust", "rust");
  17523. });
  17524. /* ---- mode/xml.js ---- */
  17525. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  17526. // Distributed under an MIT license: https://codemirror.net/LICENSE
  17527. (function(mod) {
  17528. if (typeof exports == "object" && typeof module == "object") // CommonJS
  17529. mod(require("../../lib/codemirror"));
  17530. else if (typeof define == "function" && define.amd) // AMD
  17531. define(["../../lib/codemirror"], mod);
  17532. else // Plain browser env
  17533. mod(CodeMirror);
  17534. })(function(CodeMirror) {
  17535. "use strict";
  17536. var htmlConfig = {
  17537. autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
  17538. 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
  17539. 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
  17540. 'track': true, 'wbr': true, 'menuitem': true},
  17541. implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
  17542. 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
  17543. 'th': true, 'tr': true},
  17544. contextGrabbers: {
  17545. 'dd': {'dd': true, 'dt': true},
  17546. 'dt': {'dd': true, 'dt': true},
  17547. 'li': {'li': true},
  17548. 'option': {'option': true, 'optgroup': true},
  17549. 'optgroup': {'optgroup': true},
  17550. 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
  17551. 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
  17552. 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
  17553. 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
  17554. 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
  17555. 'rp': {'rp': true, 'rt': true},
  17556. 'rt': {'rp': true, 'rt': true},
  17557. 'tbody': {'tbody': true, 'tfoot': true},
  17558. 'td': {'td': true, 'th': true},
  17559. 'tfoot': {'tbody': true},
  17560. 'th': {'td': true, 'th': true},
  17561. 'thead': {'tbody': true, 'tfoot': true},
  17562. 'tr': {'tr': true}
  17563. },
  17564. doNotIndent: {"pre": true},
  17565. allowUnquoted: true,
  17566. allowMissing: true,
  17567. caseFold: true
  17568. }
  17569. var xmlConfig = {
  17570. autoSelfClosers: {},
  17571. implicitlyClosed: {},
  17572. contextGrabbers: {},
  17573. doNotIndent: {},
  17574. allowUnquoted: false,
  17575. allowMissing: false,
  17576. allowMissingTagName: false,
  17577. caseFold: false
  17578. }
  17579. CodeMirror.defineMode("xml", function(editorConf, config_) {
  17580. var indentUnit = editorConf.indentUnit
  17581. var config = {}
  17582. var defaults = config_.htmlMode ? htmlConfig : xmlConfig
  17583. for (var prop in defaults) config[prop] = defaults[prop]
  17584. for (var prop in config_) config[prop] = config_[prop]
  17585. // Return variables for tokenizers
  17586. var type, setStyle;
  17587. function inText(stream, state) {
  17588. function chain(parser) {
  17589. state.tokenize = parser;
  17590. return parser(stream, state);
  17591. }
  17592. var ch = stream.next();
  17593. if (ch == "<") {
  17594. if (stream.eat("!")) {
  17595. if (stream.eat("[")) {
  17596. if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
  17597. else return null;
  17598. } else if (stream.match("--")) {
  17599. return chain(inBlock("comment", "-->"));
  17600. } else if (stream.match("DOCTYPE", true, true)) {
  17601. stream.eatWhile(/[\w\._\-]/);
  17602. return chain(doctype(1));
  17603. } else {
  17604. return null;
  17605. }
  17606. } else if (stream.eat("?")) {
  17607. stream.eatWhile(/[\w\._\-]/);
  17608. state.tokenize = inBlock("meta", "?>");
  17609. return "meta";
  17610. } else {
  17611. type = stream.eat("/") ? "closeTag" : "openTag";
  17612. state.tokenize = inTag;
  17613. return "tag bracket";
  17614. }
  17615. } else if (ch == "&") {
  17616. var ok;
  17617. if (stream.eat("#")) {
  17618. if (stream.eat("x")) {
  17619. ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
  17620. } else {
  17621. ok = stream.eatWhile(/[\d]/) && stream.eat(";");
  17622. }
  17623. } else {
  17624. ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
  17625. }
  17626. return ok ? "atom" : "error";
  17627. } else {
  17628. stream.eatWhile(/[^&<]/);
  17629. return null;
  17630. }
  17631. }
  17632. inText.isInText = true;
  17633. function inTag(stream, state) {
  17634. var ch = stream.next();
  17635. if (ch == ">" || (ch == "/" && stream.eat(">"))) {
  17636. state.tokenize = inText;
  17637. type = ch == ">" ? "endTag" : "selfcloseTag";
  17638. return "tag bracket";
  17639. } else if (ch == "=") {
  17640. type = "equals";
  17641. return null;
  17642. } else if (ch == "<") {
  17643. state.tokenize = inText;
  17644. state.state = baseState;
  17645. state.tagName = state.tagStart = null;
  17646. var next = state.tokenize(stream, state);
  17647. return next ? next + " tag error" : "tag error";
  17648. } else if (/[\'\"]/.test(ch)) {
  17649. state.tokenize = inAttribute(ch);
  17650. state.stringStartCol = stream.column();
  17651. return state.tokenize(stream, state);
  17652. } else {
  17653. stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
  17654. return "word";
  17655. }
  17656. }
  17657. function inAttribute(quote) {
  17658. var closure = function(stream, state) {
  17659. while (!stream.eol()) {
  17660. if (stream.next() == quote) {
  17661. state.tokenize = inTag;
  17662. break;
  17663. }
  17664. }
  17665. return "string";
  17666. };
  17667. closure.isInAttribute = true;
  17668. return closure;
  17669. }
  17670. function inBlock(style, terminator) {
  17671. return function(stream, state) {
  17672. while (!stream.eol()) {
  17673. if (stream.match(terminator)) {
  17674. state.tokenize = inText;
  17675. break;
  17676. }
  17677. stream.next();
  17678. }
  17679. return style;
  17680. }
  17681. }
  17682. function doctype(depth) {
  17683. return function(stream, state) {
  17684. var ch;
  17685. while ((ch = stream.next()) != null) {
  17686. if (ch == "<") {
  17687. state.tokenize = doctype(depth + 1);
  17688. return state.tokenize(stream, state);
  17689. } else if (ch == ">") {
  17690. if (depth == 1) {
  17691. state.tokenize = inText;
  17692. break;
  17693. } else {
  17694. state.tokenize = doctype(depth - 1);
  17695. return state.tokenize(stream, state);
  17696. }
  17697. }
  17698. }
  17699. return "meta";
  17700. };
  17701. }
  17702. function Context(state, tagName, startOfLine) {
  17703. this.prev = state.context;
  17704. this.tagName = tagName;
  17705. this.indent = state.indented;
  17706. this.startOfLine = startOfLine;
  17707. if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
  17708. this.noIndent = true;
  17709. }
  17710. function popContext(state) {
  17711. if (state.context) state.context = state.context.prev;
  17712. }
  17713. function maybePopContext(state, nextTagName) {
  17714. var parentTagName;
  17715. while (true) {
  17716. if (!state.context) {
  17717. return;
  17718. }
  17719. parentTagName = state.context.tagName;
  17720. if (!config.contextGrabbers.hasOwnProperty(parentTagName) ||
  17721. !config.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
  17722. return;
  17723. }
  17724. popContext(state);
  17725. }
  17726. }
  17727. function baseState(type, stream, state) {
  17728. if (type == "openTag") {
  17729. state.tagStart = stream.column();
  17730. return tagNameState;
  17731. } else if (type == "closeTag") {
  17732. return closeTagNameState;
  17733. } else {
  17734. return baseState;
  17735. }
  17736. }
  17737. function tagNameState(type, stream, state) {
  17738. if (type == "word") {
  17739. state.tagName = stream.current();
  17740. setStyle = "tag";
  17741. return attrState;
  17742. } else if (config.allowMissingTagName && type == "endTag") {
  17743. setStyle = "tag bracket";
  17744. return attrState(type, stream, state);
  17745. } else {
  17746. setStyle = "error";
  17747. return tagNameState;
  17748. }
  17749. }
  17750. function closeTagNameState(type, stream, state) {
  17751. if (type == "word") {
  17752. var tagName = stream.current();
  17753. if (state.context && state.context.tagName != tagName &&
  17754. config.implicitlyClosed.hasOwnProperty(state.context.tagName))
  17755. popContext(state);
  17756. if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) {
  17757. setStyle = "tag";
  17758. return closeState;
  17759. } else {
  17760. setStyle = "tag error";
  17761. return closeStateErr;
  17762. }
  17763. } else if (config.allowMissingTagName && type == "endTag") {
  17764. setStyle = "tag bracket";
  17765. return closeState(type, stream, state);
  17766. } else {
  17767. setStyle = "error";
  17768. return closeStateErr;
  17769. }
  17770. }
  17771. function closeState(type, _stream, state) {
  17772. if (type != "endTag") {
  17773. setStyle = "error";
  17774. return closeState;
  17775. }
  17776. popContext(state);
  17777. return baseState;
  17778. }
  17779. function closeStateErr(type, stream, state) {
  17780. setStyle = "error";
  17781. return closeState(type, stream, state);
  17782. }
  17783. function attrState(type, _stream, state) {
  17784. if (type == "word") {
  17785. setStyle = "attribute";
  17786. return attrEqState;
  17787. } else if (type == "endTag" || type == "selfcloseTag") {
  17788. var tagName = state.tagName, tagStart = state.tagStart;
  17789. state.tagName = state.tagStart = null;
  17790. if (type == "selfcloseTag" ||
  17791. config.autoSelfClosers.hasOwnProperty(tagName)) {
  17792. maybePopContext(state, tagName);
  17793. } else {
  17794. maybePopContext(state, tagName);
  17795. state.context = new Context(state, tagName, tagStart == state.indented);
  17796. }
  17797. return baseState;
  17798. }
  17799. setStyle = "error";
  17800. return attrState;
  17801. }
  17802. function attrEqState(type, stream, state) {
  17803. if (type == "equals") return attrValueState;
  17804. if (!config.allowMissing) setStyle = "error";
  17805. return attrState(type, stream, state);
  17806. }
  17807. function attrValueState(type, stream, state) {
  17808. if (type == "string") return attrContinuedState;
  17809. if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;}
  17810. setStyle = "error";
  17811. return attrState(type, stream, state);
  17812. }
  17813. function attrContinuedState(type, stream, state) {
  17814. if (type == "string") return attrContinuedState;
  17815. return attrState(type, stream, state);
  17816. }
  17817. return {
  17818. startState: function(baseIndent) {
  17819. var state = {tokenize: inText,
  17820. state: baseState,
  17821. indented: baseIndent || 0,
  17822. tagName: null, tagStart: null,
  17823. context: null}
  17824. if (baseIndent != null) state.baseIndent = baseIndent
  17825. return state
  17826. },
  17827. token: function(stream, state) {
  17828. if (!state.tagName && stream.sol())
  17829. state.indented = stream.indentation();
  17830. if (stream.eatSpace()) return null;
  17831. type = null;
  17832. var style = state.tokenize(stream, state);
  17833. if ((style || type) && style != "comment") {
  17834. setStyle = null;
  17835. state.state = state.state(type || style, stream, state);
  17836. if (setStyle)
  17837. style = setStyle == "error" ? style + " error" : setStyle;
  17838. }
  17839. return style;
  17840. },
  17841. indent: function(state, textAfter, fullLine) {
  17842. var context = state.context;
  17843. // Indent multi-line strings (e.g. css).
  17844. if (state.tokenize.isInAttribute) {
  17845. if (state.tagStart == state.indented)
  17846. return state.stringStartCol + 1;
  17847. else
  17848. return state.indented + indentUnit;
  17849. }
  17850. if (context && context.noIndent) return CodeMirror.Pass;
  17851. if (state.tokenize != inTag && state.tokenize != inText)
  17852. return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
  17853. // Indent the starts of attribute names.
  17854. if (state.tagName) {
  17855. if (config.multilineTagIndentPastTag !== false)
  17856. return state.tagStart + state.tagName.length + 2;
  17857. else
  17858. return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1);
  17859. }
  17860. if (config.alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
  17861. var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
  17862. if (tagAfter && tagAfter[1]) { // Closing tag spotted
  17863. while (context) {
  17864. if (context.tagName == tagAfter[2]) {
  17865. context = context.prev;
  17866. break;
  17867. } else if (config.implicitlyClosed.hasOwnProperty(context.tagName)) {
  17868. context = context.prev;
  17869. } else {
  17870. break;
  17871. }
  17872. }
  17873. } else if (tagAfter) { // Opening tag spotted
  17874. while (context) {
  17875. var grabbers = config.contextGrabbers[context.tagName];
  17876. if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
  17877. context = context.prev;
  17878. else
  17879. break;
  17880. }
  17881. }
  17882. while (context && context.prev && !context.startOfLine)
  17883. context = context.prev;
  17884. if (context) return context.indent + indentUnit;
  17885. else return state.baseIndent || 0;
  17886. },
  17887. electricInput: /<\/[\s\w:]+>$/,
  17888. blockCommentStart: "<!--",
  17889. blockCommentEnd: "-->",
  17890. configuration: config.htmlMode ? "html" : "xml",
  17891. helperType: config.htmlMode ? "html" : "xml",
  17892. skipAttribute: function(state) {
  17893. if (state.state == attrValueState)
  17894. state.state = attrState
  17895. },
  17896. xmlCurrentTag: function(state) {
  17897. return state.tagName ? {name: state.tagName, close: state.type == "closeTag"} : null
  17898. },
  17899. xmlCurrentContext: function(state) {
  17900. var context = []
  17901. for (var cx = state.context; cx; cx = cx.prev)
  17902. if (cx.tagName) context.push(cx.tagName)
  17903. return context.reverse()
  17904. }
  17905. };
  17906. });
  17907. CodeMirror.defineMIME("text/xml", "xml");
  17908. CodeMirror.defineMIME("application/xml", "xml");
  17909. if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
  17910. CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
  17911. });