12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788(* Claude Code
*
* Copyright (C) 2026 Yoann Padioleau
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* (LGPL) as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*)(* See Dtd.mli *)typeorigin=Core|Netscapeletvoid=["area";"base";"basefont";"br";"col";"embed";"frame";"hr";"img";"input";"isindex";"link";"meta";"param";"wbr"]lethead=["title";"meta";"link";"base";"style";"script"]letheadings=["h1";"h2";"h3";"h4";"h5";"h6"]letblocks=["address";"blockquote";"center";"dir";"div";"dl";"form";"hr";"menu";"ol";"p";"pre";"table";"ul"]@headings(* where no search goes through: the table's cells and the root (the
* WHATWG's "scope") *)letscope=["html";"table";"td";"th";"caption";"applet";"object"]letis_voidname=List.memnamevoidletis_head_elementname=List.memnameheadletis_blockname=List.memnameblocksletcloses(x:string)(y:string):bool=matchywith|"p"->is_blockx||List.memx["li";"dt";"dd"]|"li"->x="li"|"dt"|"dd"->x="dt"||x="dd"|"option"->x="option"|"tr"->x="tr"|"td"|"th"->List.memx["td";"th";"tr"]|ywhenList.memyheadings->List.memxheadings|_->falseletstops(x:string)(y:string):bool=List.memyscope||matchxwith(* an item ends the item of its own list only: not across a nested
* list, nor across a block (other than the p, div, address an item
* may hold) *)|"li"->List.memy["ul";"ol";"dir";"menu"]||(is_blocky&¬(List.memy["p";"div";"address"]))|"dt"|"dd"->y="dl"||(is_blocky&¬(List.memy["p";"div";"address"]))|_->false(*****************************************************************************)(* Netscape's extensions *)(*****************************************************************************)letnetscape_elements=["basefont";"blink";"center";"font";"nobr";"wbr"](* 1.1's tables (the HTML 3.0 draft's), and the row groups HTML 4
* added to them *)@["table";"caption";"tr";"td";"th";"thead";"tbody";"tfoot"]letnetscape_attributes=[("body",["bgcolor";"text";"link";"vlink";"alink";"background"]);("hr",["size";"width";"align";"noshade"]);("br",["clear"]);("img",["width";"height";"border";"hspace";"vspace"]);("ul",["type"]);("ol",["type";"start"]);("li",["type";"value"]);("p",["align"]);]@List.map(funh->(h,["align"]))headings(* an attribute of HTML 2.0 given new values *)letnetscape_values=[(("img","align"),["left";"right";"texttop";"absmiddle";"baseline";"absbottom"])]letelement_origin(name:string):origin=ifList.memnamenetscape_elementsthenNetscapeelseCoreletattribute_origin(element:string)((name,value):string*string):origin=letlisted=matchList.assoc_optelementnetscape_attributeswithSomenames->List.memnamenames|None->falseinletvalue_listed=matchList.assoc_opt(element,name)netscape_valueswith|Somevalues->List.mem(String.lowercase_asciivalue)values|None->falseiniflisted||value_listedthenNetscapeelseCore