Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file generator.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406(*
* Copyright (c) 2016 Thomas Refis <trefis@janestreet.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*)openOdoc_document.TypesmoduleHtml=Tyxml.HtmlmoduleDoctree=Odoc_document.Doctreetypeany=Html_types.flow5typeitem=Html_types.flow5_without_header_footertypeflow=Html_types.flow5_without_sectioning_heading_header_footertypephrasing=Html_types.phrasingtypenon_link_phrasing=Html_types.phrasing_without_interactiveletmk_anchor_linkid=[Html.a~a:[Html.a_href("#"^id);Html.a_class["anchor"]][]]letmk_anchoranchor=matchanchorwith|None->([],[])|Some{Odoc_document.Url.Anchor.anchor;_}->letlink=mk_anchor_linkanchorinletattrib=[Html.a_idanchor;Html.a_class["anchored"]]in(attrib,link)letclass_(l:Class.t)=ifl=[]then[]else[Html.a_classl]andraw_markup(t:Raw_markup.t)=lettarget,content=tinmatchAstring.String.Ascii.lowercasetargetwith|"html"->(* This is OK because we output *textual* HTML.
In theory, we should try to parse the HTML with lambdasoup and rebuild
the HTML tree from there.
*)[Html.Unsafe.datacontent]|_->[]andsourcek?a(t:Source.t)=letrectoken(x:Source.token)=matchxwith|Elti->ki|Tag(None,l)->letcontent=tokenslinifcontent=[]then[]else[Html.spancontent]|Tag(Somes,l)->[Html.span~a:[Html.a_class[s]](tokensl)]andtokenst=Utils.list_concat_mapt~f:tokeninUtils.optional_eltHtml.code?a(tokenst)andstyledstyle~emph_level=matchstylewith|`Emphasis->leta=ifemph_levelmod2=0then[]else[Html.a_class["odd"]]in(emph_level+1,Html.em~a)|`Bold->(emph_level,Html.b~a:[])|`Italic->(emph_level,Html.i~a:[])|`Superscript->(emph_level,Html.sup~a:[])|`Subscript->(emph_level,Html.sub~a:[])letrecinternallink~emph_level~resolve?(a=[])(t:InternalLink.t)=matchtwith|Resolved(uri,content)->lethref=Link.href~resolveuriinleta=(a:>Html_types.a_attribHtml.attriblist)inletelt=Html.a~a:(Html.a_hrefhref::a)(inline_nolink~emph_levelcontent)inletelt=(elt:>phrasingHtml.elt)in[elt]|Unresolvedcontent->(* let title =
* Html.a_title (Printf.sprintf "unresolved reference to %S"
* (ref_to_string ref)
* in *)leta=Html.a_class["xref-unresolved"]::ainletelt=Html.span~a(inline~emph_level~resolvecontent)inletelt=(elt:>phrasingHtml.elt)in[elt]andinternallink_nolink~emph_level~(a:Html_types.span_attribHtml.attriblist)(t:InternalLink.t)=matchtwith|Resolved(_,content)|Unresolvedcontent->[Html.span~a(inline_nolink~emph_levelcontent)]andinline?(emph_level=0)~resolve(l:Inline.t):phrasingHtml.eltlist=letone(t:Inline.one)=leta=class_t.attrinmatcht.descwith|Text""->[]|Texts->ifa=[]then[Html.txts]else[Html.span~a[Html.txts]]|Entitys->ifa=[]then[Html.entitys]else[Html.span~a[Html.entitys]]|Linebreak->[Html.br~a()]|Styled(style,c)->letemph_level,app_style=styledstyle~emph_levelin[app_style@@inline~emph_level~resolvec]|Link(href,c)->leta=(a:>Html_types.a_attribHtml.attriblist)inletcontent=inline_nolink~emph_levelcin[Html.a~a:(Html.a_hrefhref::a)content]|InternalLinkc->internallink~emph_level~resolve~ac|Sourcec->source(inline~emph_level~resolve)~ac|Raw_markupr->raw_markuprinUtils.list_concat_map~f:onelandinline_nolink?(emph_level=0)(l:Inline.t):non_link_phrasingHtml.eltlist=letone(t:Inline.one)=leta=class_t.attrinmatcht.descwith|Text""->[]|Texts->ifa=[]then[Html.txts]else[Html.span~a[Html.txts]]|Entitys->ifa=[]then[Html.entitys]else[Html.span~a[Html.entitys]]|Linebreak->[Html.br~a()]|Styled(style,c)->letemph_level,app_style=styledstyle~emph_levelin[app_style@@inline_nolink~emph_levelc]|Link(_,c)->inline_nolink~emph_levelc|InternalLinkc->internallink_nolink~emph_level~ac|Sourcec->source(inline_nolink~emph_level)~ac|Raw_markupr->raw_markuprinUtils.list_concat_map~f:onelletheading~resolve(h:Heading.t)=leta,anchor=matchh.labelwith|Someid->([Html.a_idid],mk_anchor_linkid)|None->([],[])inletcontent=inline~resolveh.titleinletmk=matchh.levelwith|0->Html.h1|1->Html.h2|2->Html.h3|3->Html.h4|4->Html.h5|_->Html.h6inmk~a(anchor@content)letrecblock~resolve(l:Block.t):flowHtml.eltlist=letas_flowx=(x:phrasingHtml.eltlist:>flowHtml.eltlist)inletone(t:Block.one)=leta=class_t.attrinmatcht.descwith|Inlinei->ifa=[]thenas_flow@@inline~resolveielse[Html.span~a(inline~resolvei)]|Paragraphi->[Html.p~a(inline~resolvei)]|List(typ,l)->letmk=matchtypwithOrdered->Html.ol|Unordered->Html.ulin[mk~a(List.map(funx->Html.li(block~resolvex))l)]|Descriptionl->[(letitemi=leta=class_i.Description.attrinletterm=(inline~resolvei.Description.key:phrasingHtml.eltlist:>flowHtml.eltlist)inletdef=block~resolvei.Description.definitioninHtml.li~a(term@(Html.txt" "::def))inHtml.ul~a(List.mapiteml));]|Raw_markupr->raw_markupr|Verbatims->[Html.pre~a[Html.txts]]|Sourcec->[Html.pre~a(source(inline~resolve)c)]inUtils.list_concat_mapl~f:one(* This coercion is actually sound, but is not currently accepted by Tyxml.
See https://github.com/ocsigen/tyxml/pull/265 for details
Can be replaced by a simple type coercion once this is fixed
*)letflow_to_item:flowHtml.eltlist->itemHtml.eltlist=funx->Html.totl@@Html.toeltlxletdiv:([<Html_types.div_attrib],[<item],[>Html_types.div])Html.star=Html.Unsafe.node"div"letspec_class=function[]->[]|attr->class_("spec"::attr)letspec_doc_div~resolve=function|[]->[]|docs->leta=[Html.a_class["spec-doc"]]in[div~a(flow_to_item@@block~resolvedocs)]letrecdocumentedSrc~resolve(t:DocumentedSrc.t):itemHtml.eltlist=letopenDocumentedSrcinlettake_codel=Doctree.Take.untill~classify:(function|Codecode->Accumcode|Alternative(Expansion{summary;_})->Accumsummary|_->Stop_and_keep)inlettake_descrl=Doctree.Take.untill~classify:(function|Documented{attrs;anchor;code;doc;markers}->Accum[{DocumentedSrc.attrs;anchor;code=`Dcode;doc;markers}]|Nested{attrs;anchor;code;doc;markers}->Accum[{DocumentedSrc.attrs;anchor;code=`Ncode;doc;markers}]|_->Stop_and_keep)inletrecto_htmlt:itemHtml.eltlist=matchtwith|[]->[]|(Code_|Alternative_)::_->letcode,_,rest=take_codetinsource(inline~resolve)code@to_htmlrest|Subpagesubp::_->subpage~resolvesubp|(Documented_|Nested_)::_->letl,_,rest=take_descrtinletone{DocumentedSrc.attrs;anchor;code;doc;markers}=letcontent=matchcodewith|`Dcode->(inline~resolvecode:>itemHtml.eltlist)|`Nn->to_htmlninletdoc=matchdocwith|[]->[]|doc->letopening,closing=markersin[Html.td~a:(class_["def-doc"])(Html.span~a:(class_["comment-delim"])[Html.txtopening]::block~resolvedoc@[Html.span~a:(class_["comment-delim"])[Html.txtclosing];]);]inleta,link=mk_anchoranchorinletcontent=letc=link@contentinHtml.td~a:(class_attrs)(c:>anyHtml.eltlist)inHtml.tr~a(content::doc)inHtml.table(List.maponel)::to_htmlrestinto_htmltandsubpage~resolve(subp:Subpage.t):itemHtml.eltlist=items~resolvesubp.content.itemsanditems~resolvel:itemHtml.eltlist=letrecwalk_itemsacc(t:Item.tlist):itemHtml.eltlist=letcontinue_withrestelts=(walk_items[@tailcall])(List.rev_appendeltsacc)restinmatchtwith|[]->List.revacc|Text_::_ast->lettext,_,rest=Doctree.Take.untilt~classify:(function|Item.Texttext->Accumtext|_->Stop_and_keep)inletcontent=flow_to_item@@block~resolvetextin(continue_with[@tailcall])restcontent|Headingh::rest->(continue_with[@tailcall])rest[heading~resolveh]|Include{attr;anchor;doc;content={summary;status;content}}::rest->letdoc=spec_doc_div~resolvedocinletincluded_html=(itemscontent:>anyHtml.eltlist)inleta_class=ifList.lengthcontent=0then["odoc-include";"shadowed-include"]else["odoc-include"]inletcontent=letdetails~open'=letopen'=ifopen'then[Html.a_open()]else[]inletsummary=letanchor_attrib,anchor_link=mk_anchoranchorinleta=spec_classattr@anchor_attribinHtml.summary~a@@anchor_link@source(inline~resolve)summaryin[Html.details~a:open'summaryincluded_html]inmatchstatuswith|`Inline->included_html|`Closed->details~open':false|`Open->details~open':true|`Default->details~open':!Tree.open_detailsinletinc=[Html.div~a:[Html.a_classa_class](doc@content)]in(continue_with[@tailcall])restinc|Declaration{Item.attr;anchor;content;doc}::rest->letanchor_attrib,anchor_link=mk_anchoranchorinleta=spec_classattr@anchor_attribinletcontent=anchor_link@documentedSrc~resolvecontentinletspec=letdoc=spec_doc_div~resolvedocin[div~a:[Html.a_class["odoc-spec"]](div~acontent::doc)]in(continue_with[@tailcall])restspecanditemsl=walk_items[]linitemslmoduleToc=structopenOdoc_document.Doctreeletrender_toc~resolve(toc:Toc.t)=letrecsection{Toc.url;text;children}=lettext=inline_nolinktextinlettext=(text:non_link_phrasingHtml.eltlist:>Html_types.flow5_without_interactiveHtml.eltlist)inlethref=Link.href~resolveurlinletlink=Html.a~a:[Html.a_hrefhref]textinmatchchildrenwith[]->[link]|_->[link;sectionschildren]andsectionsthe_sections=the_sections|>List.map(funthe_section->Html.li(sectionthe_section))|>Html.ulinmatchtocwith|[]->[]|_->[Html.nav~a:[Html.a_class["odoc-toc"]][sectionstoc]]leton_sub:Subpage.status->bool=function|`Closed|`Open|`Default->false|`Inline->trueletfrom_items~resolve~pathi=render_toc~resolve@@Toc.computepath~on_subiendmodulePage=structleton_sub=function|`Page_->None|`Includex->(matchx.Include.statuswith|`Closed|`Open|`Default->None|`Inline->Some0)letrecinclude_?theme_uriindent{Subpage.content;_}=[page?theme_uriindentcontent]andsubpages?theme_uriindentsubpages=Utils.list_concat_map~f:(include_?theme_uriindent)subpagesandpage?theme_uri?support_uriindentp=let{Page.title;header;items=i;url}=Doctree.Labels.disambiguate_pagepandsubpages=(* Don't use the output of [disambiguate_page] to avoid unecessarily
mangled labels. *)subpages?theme_uriindent@@Doctree.Subpages.computepinletresolve=Link.Currenturlinleti=Doctree.Shift.compute~on_subiinlettoc=Toc.from_items~resolve~path:urliinletheader=items~resolveheaderinletcontent=(items~resolvei:>anyHtml.eltlist)inletpage=Tree.make?theme_uri?support_uri~indent~header~toc~urltitlecontentsubpagesinpageendletrender?theme_uri?support_uri~indentpage=Page.page?theme_uri?support_uriindentpageletdoc~xref_base_urib=letresolve=Link.Basexref_base_uriinblock~resolveb