Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file b0_html.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332(*---------------------------------------------------------------------------
Copyright (c) 2016 The htmlit programmers. All rights reserved.
SPDX-License-Identifier: ISC
---------------------------------------------------------------------------*)(* HTML escaping *)moduleString_set=Set.Make(String)letadd_escapedbs=letadds=Buffer.add_stringinletlen=String.lengthsinletmax_idx=len-1inletflushbstarti=ifstart<lenthenBuffer.add_substringbsstart(i-start);inletrecloopstarti=ifi>max_idxthenflushbstartielseletnext=i+1inmatchString.getsiwith|'&'->flushbstarti;addsb"&";loopnextnext|'<'->flushbstarti;addsb"<";loopnextnext|'>'->flushbstarti;addsb">";loopnextnext|'\''->flushbstarti;addsb"'";loopnextnext|'\"'->flushbstarti;addsb""";loopnextnext|c->loopstartnextinloop00letescapes=letb=Buffer.create255inadd_escapedbs;Buffer.contentsb(* Attributes *)moduleAt=structtypename=stringtypet=name*stringletvnv=(n,v)letvoid=("","")letintni=(n,string_of_inti)lettrue'n=(n,"")letif'bat=ifbthenatelsevoidletif_some=functionNone->void|Someat->atletis_void(n,_)=String.equaln""letequal=Stdlib.(=)letcompare=Stdlib.compareletto_pair=Fun.idletof_pair=Fun.idletppppf(n,v)=matchnwith|""->()|n->Format.fprintfppf"@[%s=\"%s\"@]"nvtype'acons='a->tletaccesskeys=v"accesskey"sletactions=v"action"sletalts=v"alt"sletautocompletes=v"autocomplete"sletautofocus=true'"autofocus"letcharset=v"charset"letchecked=true'"checked"letclass's=v"class"sletcolsi=int"cols"iletcolspani=int"cols"iletcontents=v"content"sletcontenteditables=true'"contenteditable"letdatetimes=v"datetime"sletdefer=true'"defer"letdirs=v"dir"sletdisabled=true'"disabled"letdraggableb=v"draggable"(string_of_booltrue)(* not a boolean attr *)letdownloads=v"download"sletfor's=v"for"sletheighti=int"height"ilethidden=true'"hidden"lethrefs=v"href"sletids=v"id"sletlangs=v"lang"sletlists=v"list"sletmedias=v"media"sletmethod's=v"method"sletnames=v"name"sletplaceholders=v"placeholder"sletpopovers=v"popover"sletpopovertargets=v"popovertarget"sletpopovertargetactions=v"popovertargetaction"sletrels=v"rel"sletrequired=true'"required"letroles=v"role"sletrowsi=int"rows"iletrowspani=int"rowspan"iletselected=true'"selected"letspellcheck=v"spellcheck"letsrcs=v"src"sletstyles=v"style"slettabindexi=int"tabindex"ilettitles=v"title"slettype's=v"type"sletvalues=v"value"sletwidthi=int"width"iletwraps=v"value"send(* HTML elements and fragments *)moduleEl=structmoduleLow=structtypename=stringtypet=|Elofname*At.tlist*tlist|Txtofstring|Spliceoftoption*tlist|Rawofstringletof_htmlf=fendtypename=Low.nametypehtml=Low.tletv?(at=[])ncs=Low.El(n,at,cs)lettxtv=Low.Txtvlettxt_offv=Low.Txt(fv)letsp=Low.Txt" "letnbsp=Low.Txt"\u{00A0}"letsplice?sepcs=Low.Splice(sep,cs)letunsafe_rawf=Low.Rawfletvoid=Low.Splice(None,[])letis_void=function|Low.Splice(_,[])|Low.Txt""|Low.Raw""->true|_->false(* Rendering *)letaddc=Buffer.add_charletadds=Buffer.add_stringletadd_doctypeb=addsb"<!DOCTYPE html>\n"letadd_atbnv=addsbn;addsb"=\"";add_escapedbv;addcb'\"'letrecadd_attsbcs(* classes *)ss(* styles *)=function|("",_)::atts->add_attsbcsssatts|("class",c)::atts->add_attsb(c::cs)ssatts|("style",s)::atts->add_attsbcs(s::ss)atts|(n,v)::atts->addcb' ';add_atbnv;add_attsbcsssatts|[]->letmergesepvs=String.concatsep(List.revvs)inifcs<>[]then(addcb' ';add_atb"class"(merge" "cs));ifss<>[]then(addcb' ';add_atb"style"(merge";"ss))letvoid_els=String_set.of_list["area";"base";"br";"col";"embed";"hr";"img";"input";"link";"meta";"param";"source";"track";"wbr"]letrecadd_childb=function(* not tail-recursive *)|Low.Rawr->addsbr|Low.Txttxt->add_escapedbtxt|Low.El(n,atts,cs)->addcb'<';addsbn;add_attsb[][]atts;addcb'>';ifnot(String_set.memnvoid_els)then(List.iter(add_childb)cs;addsb"</";addsbn;addcb'>')|Low.Splice(None,cs)->List.iter(add_childb)cs|Low.Splice(Somesep,[])->()|Low.Splice(Somesep,c::cs)->letaddbc=add_childbsep;add_childbcinadd_childbc;List.iter(addb)csletbuffer_add~doctypebcs=ifdoctypethenadd_doctypeb;add_childbcsletto_string~doctypeg=letb=Buffer.create1024inbuffer_add~doctypebg;Buffer.contentsb(* Predefined element constructors *)typecons=?at:At.tlist->htmllist->htmltypevoid_cons=?at:At.tlist->unit->htmlletconse?atels=v?ateelsletvoid_conse?at()=ve?at[]leta=cons"a"letabbr=cons"abbr"letaddress=cons"address"letarea=void_cons"area"letarticle=cons"article"letaside=cons"aside"letaudio=cons"audio"letb=cons"b"letbase=void_cons"base"letbdi=cons"bdi"letbdo=cons"bdo"letblockquote=cons"blockquote"letbody=cons"body"letbr=void_cons"br"letbutton=cons"button"letcanvas=cons"canvas"letcaption=cons"caption"letcite=cons"cite"letcode=cons"code"letcol=void_cons"col"letcolgroup=cons"colgroup"letcommand=cons"command"letdatalist=cons"datalist"letdd=cons"dd"letdel=cons"del"letdetails=cons"details"letdfn=cons"dfn"letdiv=cons"div"letdl=cons"dl"letdt=cons"dt"letem=cons"em"letembed=void_cons"embed"letfieldset=cons"fieldset"letfigcaption=cons"figcaption"letfigure=cons"figure"letfooter=cons"footer"letform=cons"form"leth1=cons"h1"leth2=cons"h2"leth3=cons"h3"leth4=cons"h4"leth5=cons"h5"leth6=cons"h6"lethead=cons"head"letheader=cons"header"lethgroup=cons"hgroup"lethr=void_cons"hr"lethtml=cons"html"leti=cons"i"letiframe=cons"iframe"letimg=void_cons"img"letinput=void_cons"input"letins=cons"ins"letkbd=cons"kbd"letkeygen=cons"keygen"letlabel=cons"label"letlegend=cons"legend"letli=cons"li"letlink=void_cons"link"letmain=cons"main"letmap=cons"map"letmark=cons"mark"letmenu=cons"menu"letmeta=void_cons"meta"letmeter=cons"meter"letnav=cons"nav"letnoscript=cons"noscript"letobject'=cons"object"letol=cons"ol"letoptgroup=cons"optgroup"letoption=cons"option"letoutput=cons"output"letp=cons"p"letparam=void_cons"param"letpre=cons"pre"letprogress=cons"progress"letq=cons"q"letrp=cons"rp"letrt=cons"rt"letruby=cons"ruby"lets=cons"s"letsamp=cons"samp"letscript=cons"script"letsection=cons"section"letselect=cons"select"letsmall=cons"small"letsource=void_cons"source"letspan=cons"span"letstrong=cons"strong"letstyle=cons"style"letsub=cons"sub"letsummary=cons"summary"letsup=cons"sup"lettable=cons"table"lettbody=cons"tbody"lettd=cons"td"lettextarea=cons"textarea"lettfoot=cons"tfoot"letth=cons"th"letthead=cons"thead"lettime=cons"time"lettitle=cons"title"lettr=cons"tr"lettrack=void_cons"track"letu=cons"u"letul=cons"ul"letvar=cons"var"letvideo=cons"video"letwbr=void_cons"wbr"(* Page *)letpage?(lang="")?(generator="")?(styles=[])?(scripts=[])?(more_head=void)~title:tbody=letviewport="width=device-width, initial-scale=1.0, viewport-fit=cover"inletgenerator=matchgeneratorwith|""->void|g->meta~at:At.[name"generator";contentg]()inletstyle=function|""->void|url->link~at:At.[rel"stylesheet";type'"text/css";hrefurl]()inletscript=function|""->void|url->script~at:At.[type'"text/javascript";defer;srcurl][]inlett=matchString.trimtwith""->"Untitled"|t->tinlethead=head[meta~at:At.[charset"utf-8"]();generator;meta~at:At.[name"viewport";contentviewport]();splice(List.mapstylestyles);splice(List.mapscriptscripts);more_head;title[txtt]]inletat=iflang=""then[]else[At.langlang]inhtml~at[head;body]lettitle_of_filepathf=letrecbase~sndinitf=letstart=refinitinletlast=ref(init+1)inwhilenot(!start<0||f.[!start]='/'||f.[!start]='\\')doiff.[!start]='.'thenlast:=!start;decrstartdone;letfirst=!start+1inletlast=!last-1iniffirst<=last&&last<=initthenbeginlets=String.subffirst(last-first+1)inifnot(s="index"||s="")thenselseifsnd=truethen"Untitled"elsebase~snd:true(!start-1)fendelseif!start<0||snd=truethen"Untitled"elsebase~snd:true(!start-1)finbase~snd:false(String.lengthf-1)fend