123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258openPpxlibtypestatic_part=|Static_strofstring|Dynamic_stringofexpression|Dynamic_intofexpression|Dynamic_floatofexpression|Dynamic_elementofexpressiontypestatic_attr_value=Static_stringofstring|Static_intofint|Static_boolofbooltypeattr_render_info={html_name:string;is_boolean:bool;kind:DomProps.attributeType}typeparsed_attr=|Static_attrofattr_render_info*static_attr_value|Optional_attrofattr_render_info*expression|Dynamic_attrofstring*expressiontypeattr_validation_result=Valid_attrofattr_render_info|Invalid_attrtypeattr_analysis_result=Okofparsed_attroption|Invalidtypeattrs_analysis=|All_staticofstring|Has_optionalof(attr_render_info*expression)list*string|Has_dynamic|Validation_failedtypechildren_analysis=|No_children|All_static_childrenofstring|All_string_dynamicofstatic_partlist|Mixed_childrenofstatic_partlisttypeelement_analysis=|Fully_staticofstring|Needs_string_concatofstatic_partlist|Needs_bufferofstatic_partlist|Cannot_optimizeletreccoalesce_static_parts=function|Static_stra::Static_strb::rest->coalesce_static_parts(Static_str(a^b)::rest)|x::rest->x::coalesce_static_partsrest|[]->[]letescape_htmls=letlen=String.lengthsinletbuf=Buffer.create(len*2)infori=0tolen-1domatchs.[i]with|'&'->Buffer.add_stringbuf"&"|'<'->Buffer.add_stringbuf"<"|'>'->Buffer.add_stringbuf">"|'\''->Buffer.add_stringbuf"'"|'"'->Buffer.add_stringbuf"""|c->Buffer.add_charbufcdone;Buffer.contentsbuf(* Must match Html.is_self_closing_tag *)letis_self_closing_tag=function|"area"|"base"|"basefont"|"bgsound"|"br"|"col"|"command"|"embed"|"frame"|"hr"|"image"|"img"|"input"|"keygen"|"link"|"meta"|"param"|"source"|"track"|"wbr"->true|_->falseletrecextract_literal_stringexpr=matchexpr.pexp_descwith|Pexp_constant(Pconst_string(s,_,_))->Somes|Pexp_constraint(inner,_)->extract_literal_stringinner|_->Noneletrecextract_literal_intexpr=matchexpr.pexp_descwith|Pexp_constant(Pconst_integer(s,_))->(trySome(int_of_strings)with_->None)|Pexp_constraint(inner,_)->extract_literal_intinner|_->Noneletrecextract_literal_floatexpr=matchexpr.pexp_descwith|Pexp_constant(Pconst_float(s,_))->(trySome(float_of_strings)with_->None)|Pexp_constraint(inner,_)->extract_literal_floatinner|_->Noneletrecextract_literal_boolexpr=matchexpr.pexp_descwith|Pexp_construct({txt=Lident"true";_},None)->Sometrue|Pexp_construct({txt=Lident"false";_},None)->Somefalse|Pexp_constraint(inner,_)->extract_literal_boolinner|_->Noneletextract_react_string_argexpr=matchexpr.pexp_descwith|Pexp_apply({pexp_desc=Pexp_ident{txt=Ldot(Lident"React",("string"|"text"));_};_},[(Nolabel,arg)])->Somearg|Pexp_apply({pexp_desc=Pexp_ident{txt=Lident("string"|"text");_};_},[(Nolabel,arg)])->Somearg|_->Noneletextract_react_int_argexpr=matchexpr.pexp_descwith|Pexp_apply({pexp_desc=Pexp_ident{txt=Ldot(Lident"React","int");_};_},[(Nolabel,arg)])->Somearg|Pexp_apply({pexp_desc=Pexp_ident{txt=Lident"int";_};_},[(Nolabel,arg)])->Somearg|_->Noneletextract_react_float_argexpr=matchexpr.pexp_descwith|Pexp_apply({pexp_desc=Pexp_ident{txt=Ldot(Lident"React","float");_};_},[(Nolabel,arg)])->Somearg|Pexp_apply({pexp_desc=Pexp_ident{txt=Lident"float";_};_},[(Nolabel,arg)])->Somearg|_->Noneletextract_react_text_literalexpr=matchextract_react_string_argexprwithSomearg->extract_literal_stringarg|None->Noneletextract_react_int_literalexpr=matchextract_react_int_argexprwithSomearg->extract_literal_intarg|None->Noneletextract_react_float_literalexpr=matchextract_react_float_argexprwithSomearg->extract_literal_floatarg|None->Noneletextract_unsafe_literalexpr=matchexpr.pexp_descwith|Pexp_apply({pexp_desc=Pexp_ident{txt=Ldot(Lident"Html","raw");_};_},[(Nolabel,arg)])->extract_literal_stringarg|_->Noneletextract_static_attr_valueexpr=matchextract_literal_stringexprwith|Somes->Some(Static_strings)|None->(matchextract_literal_intexprwith|Somei->Some(Static_inti)|None->(matchextract_literal_boolexprwithSomeb->Some(Static_boolb)|None->None))letrender_attr_value=function|Static_strings->escape_htmls|Static_inti->string_of_inti|Static_booltrue->"true"|Static_boolfalse->"false"letvalidate_attr_for_static~tag_namejsx_name=matchDomProps.findByJsxName~tag:tag_namejsx_namewith|Error_->Invalid_attr|Okprop->lethtml_name,kind=matchpropwith|DomProps.Attribute{name;type_;_}->(name,type_)|DomProps.Event{jsxName;_}->(jsxName,DomProps.String)inletis_boolean=kind=DomProps.BoolinValid_attr{html_name;is_boolean;kind}letrender_static_attr_with_infoinfovalue=matchvaluewith|Static_boolfalsewheninfo.is_boolean->""|Static_booltruewheninfo.is_boolean->" "^info.html_name|Static_boolbwheninfo.kind=DomProps.BooleanishString->Printf.sprintf" %s=\"%s\""info.html_name(ifbthen"true"else"false")|_->letvalue_str=render_attr_valuevalueinPrintf.sprintf" %s=\"%s\""info.html_namevalue_strletanalyze_attribute~tag_name(label,expr):attr_analysis_result=matchlabelwith|Nolabel->OkNone|Optionalname->(matchnamewith|"ref"->OkNone|_->(matchvalidate_attr_for_static~tag_namenamewith|Invalid_attr->Invalid|Valid_attrinfo->Ok(Some(Optional_attr(info,expr)))))|Labelledname->(matchnamewith|"key"|"children"|"ref"->OkNone|_->(matchvalidate_attr_for_static~tag_namenamewith|Invalid_attr->Invalid|Valid_attrinfo->(matchextract_static_attr_valueexprwith|Somevalue->Ok(Some(Static_attr(info,value)))|None->Ok(Some(Dynamic_attr(info.html_name,expr))))))letanalyze_attributes~tag_nameattrs=letrecloopstatic_bufoptionals=function|[]->ifoptionals=[]thenAll_static(Buffer.contentsstatic_buf)elseHas_optional(List.revoptionals,Buffer.contentsstatic_buf)|attr::rest->(matchanalyze_attribute~tag_nameattrwith|Invalid->Validation_failed|OkNone->loopstatic_bufoptionalsrest|Ok(Some(Static_attr(info,value)))->Buffer.add_stringstatic_buf(render_static_attr_with_infoinfovalue);loopstatic_bufoptionalsrest|Ok(Some(Optional_attr(info,expr)))->loopstatic_buf((info,expr)::optionals)rest|Ok(Some(Dynamic_attr_))->Has_dynamic)inloop(Buffer.create64)[]attrsletanalyze_child(expr:expression):static_part=letextractions=[(fun()->extract_unsafe_literalexpr|>Option.map(funs->Static_strs));(fun()->extract_react_text_literalexpr|>Option.map(funs->Static_str(escape_htmls)));(fun()->extract_literal_stringexpr|>Option.map(funs->Static_str(escape_htmls)));(fun()->extract_react_int_literalexpr|>Option.map(funi->Static_str(string_of_inti)));(fun()->extract_react_float_literalexpr|>Option.map(funf->Static_str(Float.to_stringf)));(fun()->extract_react_string_argexpr|>Option.map(fune->Dynamic_stringe));(fun()->extract_react_int_argexpr|>Option.map(fune->Dynamic_inte));(fun()->extract_react_float_argexpr|>Option.map(fune->Dynamic_floate));]inList.find_map(funf->f())extractions|>Option.value~default:(Dynamic_elementexpr)letanalyze_childrenchildren=matchchildrenwith|None->No_children|Some[]->No_children|Somechildren->letparts=List.mapanalyze_childchildreninletall_static=List.for_all(functionStatic_str_->true|_->false)partsinlethas_element_dynamic=List.exists(functionDynamic_element_->true|_->false)partsinifall_staticthen(letbuf=Buffer.create128inList.iter(functionStatic_strs->Buffer.add_stringbufs|_->())parts;All_static_children(Buffer.contentsbuf))elseifnothas_element_dynamicthenAll_string_dynamic(coalesce_static_partsparts)elseMixed_children(coalesce_static_partsparts)letanalyze_element~tag_name~attrs~children=letattrs_result=analyze_attributes~tag_nameattrsinletchildren_result=analyze_childrenchildreninmatch(attrs_result,children_result)with|Validation_failed,_->Cannot_optimize|Has_dynamic,_->Cannot_optimize|Has_optional_,_->Cannot_optimize|All_staticattrs_html,No_childrenwhenis_self_closing_tagtag_name->lethtml=Printf.sprintf"<%s%s />"tag_nameattrs_htmlinFully_statichtml|All_staticattrs_html,No_children->lethtml=Printf.sprintf"<%s%s></%s>"tag_nameattrs_htmltag_nameinFully_statichtml|All_staticattrs_html,All_static_childrenchildren_html->lethtml=Printf.sprintf"<%s%s>%s</%s>"tag_nameattrs_htmlchildren_htmltag_nameinFully_statichtml|All_staticattrs_html,All_string_dynamicparts->letopen_tag=Printf.sprintf"<%s%s>"tag_nameattrs_htmlinletclose_tag=Printf.sprintf"</%s>"tag_nameinletall_parts=[Static_stropen_tag]@parts@[Static_strclose_tag]inNeeds_string_concat(coalesce_static_partsall_parts)|All_staticattrs_html,Mixed_childrenparts->letopen_tag=Printf.sprintf"<%s%s>"tag_nameattrs_htmlinletclose_tag=Printf.sprintf"</%s>"tag_nameinletall_parts=[Static_stropen_tag]@parts@[Static_strclose_tag]inNeeds_buffer(coalesce_static_partsall_parts)letmaybe_add_doctypetag_namehtml=iftag_name="html"then"<!DOCTYPE html>"^htmlelsehtml