123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293moduleRenderAttrs=structmoduleC=Cmarkit_renderer.ContextopenCmarkitletadd_attrc(key,value)=matchvaluewith|Some{Cmarkit.Attributes.v=value;delimiter=Somed}->lets=Format.sprintf" %s=%c%s%c"keydvaluedinC.stringcs|Some{Cmarkit.Attributes.v=value;delimiter=None}->C.stringc(" "^key^"="^value)|None->C.stringc(" "^key)letadd_attrsc?(include_id=true)attrs=letkv_attrs=letkv_attrs=Cmarkit.Attributes.kv_attributesattrsinList.map(fun((k,_),v)->letv=matchvwithNone->None|Some(v,_)->Somevin(k,v))kv_attrsinletclass'=letclass'=Cmarkit.Attributes.class'attrsinletclass'=List.map(fun(c,_)->c)class'inmatchclass'with|[]->[]|_->letv=String.concat" "class'in[("class",Some{Cmarkit.Attributes.v;delimiter=Some'"'})]inletid=letid=Cmarkit.Attributes.idattrsinmatchidwith|Some(id,_)wheninclude_id->letattr={Cmarkit.Attributes.v=id;delimiter=Some'"'}in[("id",Someattr)]|_->[]inletattrs=id@class'@kv_attrsinList.iter(add_attrc)attrsletopen_block?(with_newline=true)ctagattrs=C.stringc"<";C.stringctag;add_attrscattrs;C.stringc">";ifwith_newlinethenC.stringc"\n"letclose_block?(with_newline=true)ctag=C.stringc"</";C.stringctag;C.stringc">";ifwith_newlinethenC.stringc"\n"letin_blockc?(with_newline=true)tagattrsf=open_block~with_newlinectagattrs;f();close_block~with_newlinectagletwith_attrs_spanc?(with_newline=true)attrsf=ifAttributes.is_emptyattrsthenf()elsein_blockc~with_newline"span"attrsflet()=ignorewith_attrs_spanletblock_linesc=function(* newlines only between lines *)|[]->()|(l,_)::ls->letlinec(l,_)=C.bytec'\n';C.stringclinC.stringcl;List.iter(linec)lsendletto_string=function(* Standard Cmarkit nodes *)|Cmarkit.Block.Blank_line_->"Blank line"|Cmarkit.Block.Block_quote_->"Block_quote"|Cmarkit.Block.Blocks_->"Blocks"|Cmarkit.Block.Code_block_->"Code_block"|Cmarkit.Block.Heading_->"Heading"|Cmarkit.Block.Html_block_->"Html_block"|Cmarkit.Block.Link_reference_definition_->"Link_reference_definition"|Cmarkit.Block.List_->"List"|Cmarkit.Block.Paragraph_->"Paragraph"|Cmarkit.Block.Thematic_break_->"Thematic_break"(* Extension Cmarkit nodes *)|Cmarkit.Block.Ext_math_block_->"Ext_math_block"|Cmarkit.Block.Ext_table_->"Ext_table"|Cmarkit.Block.Ext_footnote_definition_->"Ext_footnote_definition"|Cmarkit.Block.Ext_standalone_attributes_->"Ext_standalone_attributes"|Cmarkit.Block.Ext_attribute_definition_->"Ext_attribute_definition"(* Slipshow nodes *)|Ast.Included_->"Included"|Ast.Div_->"Div"|Ast.Slide_->"Slide"|Ast.Slip_->"Slip"|Ast.SlipScript_->"SlipScript"|_->"other"let()=ignoreto_stringmoduleC=Cmarkit_renderer.Contextletsrcurifiles=matchuriwith|Asset.Uri.Linkl->l|Pathp->(matchFpath.Map.find_optp(files:Ast.Files.map)with|None->Fpath.to_stringp|Some{content;mode=`Base64;_}->letmime_type=Magic_mime.lookup(Fpath.filenamep)inletbase64=Base64.encode_stringcontentinFormat.sprintf"data:%s;base64,%s"mime_typebase64)(* Inspired from Cmarkit's image rendering *)letpdfc~uri~id:_~filesiattrs=letopenCmarkitinmatchuriwith|Asset.Uri.Linkl->Logs.warn(funm->m"pdf does not work with urls: ignoring %s"l)|Pathp->letattrs=Attributes.add_classattrs("slipshow__carousel",Meta.none)inletsrc=matchFpath.Map.find_optp(files:Ast.Files.map)with|None->Logs.warn(funm->m"No pdf found: %a"Fpath.ppp);Fpath.to_stringp|Some{content;mode=`Base64;_}->letbase64=Base64.encode_stringcontentinFormat.sprintf"%s"base64inletplain_texti=letlines=Inline.to_plain_text~break_on_soft:falseiinString.concat"\n"(List.map(String.concat"")lines)inC.stringc"<span slipshow-pdf";C.stringc" pdf-src=\"";Cmarkit_html.pct_encoded_stringcsrc;C.stringc"\" alt=\"";Cmarkit_html.html_escaped_stringc(plain_text(Inline.Link.texti));C.bytec'\"';RenderAttrs.add_attrscattrs;C.stringc">";C.stringc"</span>"(* Inspired from Cmarkit's image rendering *)letmedia?(close=" >")~media_namec~uri~id:_~filesiattrs=letopenCmarkitinletsrc=srcurifilesinletplain_texti=letlines=Inline.to_plain_text~break_on_soft:falseiinString.concat"\n"(List.map(String.concat"")lines)inC.bytec'<';C.stringcmedia_name;C.stringc" src=\"";Cmarkit_html.pct_encoded_stringcsrc;C.stringc"\" alt=\"";Cmarkit_html.html_escaped_stringc(plain_text(Inline.Link.texti));C.bytec'\"';iffalsethenC.stringc" controls";RenderAttrs.add_attrscattrs;C.stringccloseletcustom_html_renderer(files:Ast.Files.map)=letopenCmarkit_rendererinletopenCmarkitinletopenCmarkit_htmlinletdefault=renderer~safe:false()inletcustom_html=letinlinec=function|Inline.Text((t,(attrs,_)),_)->(* Put text inside spans to be able to apply styles on them *)Context.stringc"<span";add_attrscattrs;Context.bytec'>';html_escaped_stringct;Context.stringc"</span>";true|Ast.Pdf{uri;id;origin=(l,(attrs,_)),_}->pdfc~uri~id~fileslattrs;true|Ast.Video{uri;id;origin=(l,(attrs,_)),_}->media~media_name:"video"c~uri~id~fileslattrs;true|Ast.Image{uri;id;origin=(l,(attrs,_)),_}->media~media_name:"img"c~uri~id~fileslattrs;true|Ast.Audio{uri;id;origin=(l,(attrs,_)),_}->media~media_name:"audio"c~uri~id~fileslattrs;true|_->false(* let the default HTML renderer handle that *)inletblockc=function|Ast.Included((b,(attrs,_)),_)|Ast.Div((b,(attrs,_)),_)->letshould_include_div=letattrs_is_not_empty=not@@Attributes.is_emptyattrsinletcontains_multiple_blocks=letis_multiplel=l|>List.filter(function|Block.Blank_line_->false|_->true)|>List.length|>(<=)2inmatchbwith|Block.Blocks(l,_)whenis_multiplel->true|_->falseinattrs_is_not_empty||contains_multiple_blocksinifshould_include_divthenRenderAttrs.in_blockc"div"attrs(fun()->Context.blockcb)elseContext.blockcb;true|Ast.Carousel((l,(attrs,_)),_)->letattrs=Attributes.add_classattrs("slipshow__carousel",Meta.none)inletchildren_attrs=Attributes.make~class':[("slipshow__carousel_children",Meta.none)]()inRenderAttrs.in_blockc"div"attrs(fun()->List.iteri(funib->letattrs=ifi=0thenAttributes.add_classchildren_attrs("slipshow__carousel_active",Meta.none)elsechildren_attrsinRenderAttrs.in_blockc"div"attrs@@fun()->Context.blockcb)l);true|Ast.Slide(({content;title},(attrs,_)),_)->let()=RenderAttrs.in_blockc"div"(Attributes.add_classattrs("slipshow-rescaler",Meta.none))@@fun()->RenderAttrs.in_blockc"div"(Attributes.make~class':[("slide",Meta.none)]())@@fun()->(matchtitlewith|None->()|Some(title,(title_attrs,_))->RenderAttrs.in_blockc"div"(Attributes.add_classtitle_attrs("slide-title",Meta.none))(fun()->Context.inlinectitle));RenderAttrs.in_blockc"div"(Attributes.make~class':[("slide-body",Meta.none)]())@@fun()->Context.blockccontentintrue|Ast.Slip((slip,(attrs,_)),_)->let()=RenderAttrs.in_blockc"div"(Attributes.add_classattrs("slipshow-rescaler",Meta.none))@@fun()->RenderAttrs.in_blockc"div"(Attributes.make~class':[("slip",Meta.none)]())@@fun()->RenderAttrs.in_blockc"div"(Attributes.make~class':[("slip-body",Meta.none)]())@@fun()->Context.blockcslipintrue|Ast.SlipScript((cb,(attrs,_)),_)->letattrs=Attributes.add("type",Meta.none)(Some({v="slip-script";delimiter=None},Meta.none))attrsinRenderAttrs.in_blockc"script"attrs(fun()->RenderAttrs.block_linesc(Block.Code_block.codecb));true|_->falseinmake~inline~block()incomposedefaultcustom_htmlletto_html_string(doc:Ast.t)=Cmarkit_renderer.doc_to_string(custom_html_rendererdoc.files)doc.doc