<html><head> <link rel="stylesheet" href="style.css" type="text/css"> <meta content="text/html; charset=iso-8859-1" http-equiv="Content-Type"> <link rel="Start" href="index.html"> <link title="Index of types" rel=Appendix href="index_types.html"> <link title="Index of exceptions" rel=Appendix href="index_exceptions.html"> <link title="Index of values" rel=Appendix href="index_values.html"> <link title="Index of modules" rel=Appendix href="index_modules.html"> <link title="Textile" rel="Chapter" href="Textile.html"> <link title="Textile_parser" rel="Chapter" href="Textile_parser.html"> <link title="Textile_html" rel="Chapter" href="Textile_html.html"><title>Textile_html</title> </head> <body> <code class="code"><span class="comment">(* This file is part of textile-ocaml.<br> *<br> * textile-ocaml is free software: you can redistribute it and/or modify<br> * it under the terms of the GNU General Public License as published by<br> * the Free Software Foundation, either version 3 of the License, or<br> * (at your option) any later version.<br> *<br> * textile-ocaml is distributed in the hope that it will be useful,<br> * but WITHOUT ANY WARRANTY; without even the implied warranty of<br> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br> * GNU General Public License for more details.<br> *<br> * You should have received a copy of the GNU General Public License<br> * along with textile-ocaml. If not, see <http://www.gnu.org/licenses/>.<br> *<br> * Copyright 2011 Alexander Markov *)</span><br> <br> <span class="keyword">open</span> <span class="constructor">Printf</span><br> <span class="keyword">open</span> <span class="constructor">Textile</span><br> <br> <span class="keyword">exception</span> <span class="constructor">Invalid_textile</span> <span class="keyword">of</span> string<br> <br> <span class="keyword">let</span> of_block ?(escape_cdata=<span class="keyword">false</span>) ?(escape_nott=<span class="keyword">false</span>) block =<br> <span class="keyword">let</span> esc s =<br> <span class="keyword">let</span> strlen = <span class="constructor">String</span>.length s <span class="keyword">in</span><br> <span class="keyword">let</span> buf = <span class="constructor">Buffer</span>.create strlen <span class="keyword">in</span><br> <span class="keyword">let</span> f = <span class="keyword">function</span><br> <span class="keywordsign">|</span> <span class="string">'&'</span> <span class="keywordsign">-></span> <span class="constructor">Buffer</span>.add_string buf <span class="string">"&amp;"</span><br> <span class="keywordsign">|</span> <span class="string">'<'</span> <span class="keywordsign">-></span> <span class="constructor">Buffer</span>.add_string buf <span class="string">"&lt;"</span><br> <span class="keywordsign">|</span> <span class="string">'>'</span> <span class="keywordsign">-></span> <span class="constructor">Buffer</span>.add_string buf <span class="string">"&gt;"</span><br> <span class="keywordsign">|</span> <span class="string">'"'</span> <span class="keywordsign">-></span> <span class="constructor">Buffer</span>.add_string buf <span class="string">"&quot;"</span><br> <span class="keywordsign">|</span> c <span class="keywordsign">-></span> <span class="constructor">Buffer</span>.add_char buf c <span class="keyword">in</span><br> <span class="constructor">String</span>.iter f s;<br> <span class="constructor">Buffer</span>.contents buf <span class="keyword">in</span><br> <span class="keyword">let</span> dont_esc s = s <span class="keyword">in</span><br> <span class="keyword">let</span> print_cdata = <span class="keyword">if</span> escape_cdata <span class="keyword">then</span> esc <span class="keyword">else</span> dont_esc <span class="keyword">in</span><br> <span class="keyword">let</span> print_nott = <span class="keyword">if</span> escape_nott <span class="keyword">then</span> esc <span class="keyword">else</span> dont_esc <span class="keyword">in</span><br> <br> <span class="keyword">let</span> parse_attr = <span class="keyword">function</span><br> <span class="keywordsign">|</span> <span class="constructor">Class</span> s <span class="keywordsign">-></span> sprintf <span class="string">"class=\"%s\""</span> (esc s)<br> <span class="keywordsign">|</span> <span class="constructor">Id</span> s <span class="keywordsign">-></span> sprintf <span class="string">"id=\"%s\""</span> (esc s)<br> <span class="keywordsign">|</span> <span class="constructor">Style</span> s <span class="keywordsign">-></span> sprintf <span class="string">"style=\"%s\""</span> (esc s)<br> <span class="keywordsign">|</span> <span class="constructor">Language</span> s <span class="keywordsign">-></span> sprintf <span class="string">"lang=\"%s\""</span> (esc s) <span class="keyword">in</span><br> <br> <span class="keyword">let</span> parse_attrs = <span class="keyword">function</span><br> <span class="keywordsign">|</span> [] <span class="keywordsign">-></span> <span class="string">""</span><br> <span class="keywordsign">|</span> attrs <span class="keywordsign">-></span><br> <span class="keyword">let</span> buf = <span class="constructor">Buffer</span>.create 80 <span class="keyword">in</span><br> <span class="constructor">List</span>.iter (<span class="keyword">fun</span> attr <span class="keywordsign">-></span><br> <span class="constructor">Buffer</span>.add_char buf <span class="string">' '</span>;<br> <span class="constructor">Buffer</span>.add_string buf (parse_attr attr)) attrs;<br> <span class="constructor">Buffer</span>.contents buf <span class="keyword">in</span><br> <span class="keyword">let</span> pa = parse_attrs <span class="keyword">in</span><br> <br> <span class="keyword">let</span> <span class="keyword">rec</span> parse_phrase =<br> <span class="keyword">let</span> p = sprintf <span class="keyword">in</span><br> <span class="keyword">let</span> pl = parse_line <span class="keyword">in</span> <span class="keyword">function</span><br> <span class="keywordsign">|</span> <span class="constructor">CData</span> str <span class="keywordsign">-></span> (print_cdata str)<br> <span class="keywordsign">|</span> <span class="constructor">Strong</span> (a,l) <span class="keywordsign">-></span> p <span class="string">"<strong%s>%s</strong>"</span> (pa a) (pl l)<br> <span class="keywordsign">|</span> <span class="constructor">Italic</span> (a,l) <span class="keywordsign">-></span> p <span class="string">"<i%s>%s</i>"</span> (pa a) (pl l)<br> <span class="keywordsign">|</span> <span class="constructor">Bold</span> (a,l) <span class="keywordsign">-></span> p <span class="string">"<b%s>%s</b>"</span> (pa a) (pl l)<br> <span class="keywordsign">|</span> <span class="constructor">Emphasis</span> (a,l) <span class="keywordsign">-></span> p <span class="string">"<em%s>%s</em>"</span> (pa a) (pl l)<br> <span class="keywordsign">|</span> <span class="constructor">Citation</span> (a,l) <span class="keywordsign">-></span> p <span class="string">"<cite%s>%s</cite>"</span> (pa a) (pl l)<br> <span class="keywordsign">|</span> <span class="constructor">Deleted</span> (a,l) <span class="keywordsign">-></span> p <span class="string">"<del%s>%s</del>"</span> (pa a) (pl l)<br> <span class="keywordsign">|</span> <span class="constructor">Inserted</span> (a,l) <span class="keywordsign">-></span> p <span class="string">"<ins%s>%s</ins>"</span> (pa a) (pl l)<br> <span class="keywordsign">|</span> <span class="constructor">Superscript</span> (a,l) <span class="keywordsign">-></span> p <span class="string">"<sup%s>%s</sup>"</span> (pa a) (pl l)<br> <span class="keywordsign">|</span> <span class="constructor">Subscript</span> (a,l) <span class="keywordsign">-></span> p <span class="string">"<sub%s>%s</sub>"</span> (pa a) (pl l)<br> <span class="keywordsign">|</span> <span class="constructor">Span</span> (a,l) <span class="keywordsign">-></span> p <span class="string">"<span%s>%s</span>"</span> (pa a) (pl l)<br> <span class="keywordsign">|</span> <span class="constructor">Code</span> (a,s) <span class="keywordsign">-></span> p <span class="string">"<code%s>%s</code>"</span> (pa a) (esc s)<br> <span class="keywordsign">|</span> <span class="constructor">Notextile</span> s <span class="keywordsign">-></span> p <span class="string">"%s"</span> (print_nott s)<br> <span class="keywordsign">|</span> <span class="constructor">Acronym</span> (a, b) <span class="keywordsign">-></span><br> p <span class="string">"<acronym title=\"%s\">%s</acronym>"</span> (esc b) (print_cdata a)<br> <span class="keywordsign">|</span> <span class="constructor">Image</span> (a, float, src, alt) <span class="keywordsign">-></span><br> (<span class="keyword">let</span> alt = <span class="keyword">match</span> alt <span class="keyword">with</span><br> <span class="keywordsign">|</span> <span class="constructor">Some</span> s <span class="keywordsign">-></span> <span class="keyword">let</span> s = esc s <span class="keyword">in</span> p <span class="string">"alt=\"%s\" title=\"%s\""</span> s s<br> <span class="keywordsign">|</span> <span class="constructor">None</span> <span class="keywordsign">-></span> <span class="string">"alt=\"\""</span> <span class="keyword">in</span><br> <span class="keyword">let</span> float = <span class="keyword">match</span> float <span class="keyword">with</span><br> <span class="keywordsign">|</span> <span class="constructor">Some</span> <span class="constructor">Float_left</span> <span class="keywordsign">-></span> <span class="string">" style=\"float: left\""</span><br> <span class="keywordsign">|</span> <span class="constructor">Some</span> <span class="constructor">Float_right</span> <span class="keywordsign">-></span> <span class="string">" style=\"float: right\""</span><br> <span class="keywordsign">|</span> <span class="constructor">None</span> <span class="keywordsign">-></span> <span class="string">""</span> <span class="keyword">in</span><br> p <span class="string">"<img %s src=\"%s\"%s%s />"</span> alt (esc src) (pa a) float)<br> <span class="keywordsign">|</span> <span class="constructor">Link</span> ((attrs, l), title, url) <span class="keywordsign">-></span><br> (<span class="keyword">let</span> title = <span class="keyword">match</span> title <span class="keyword">with</span><br> <span class="keywordsign">|</span> <span class="constructor">Some</span> s <span class="keywordsign">-></span> sprintf <span class="string">" title=%S"</span> (esc s)<br> <span class="keywordsign">|</span> <span class="constructor">None</span> <span class="keywordsign">-></span> <span class="string">""</span> <span class="keyword">in</span><br> p <span class="string">"<a%s href=\"%s\"%s>%s</a>"</span> title (esc url) (pa attrs) (pl l))<br> <span class="keywordsign">|</span> <span class="constructor">Reference</span> i <span class="keywordsign">-></span><br> p <span class="string">"<sup class=\"footnote\"><a id=\"ref%d\" href=\"#fn%d\">%d</a></sup>"</span> i i i<br> <br> <span class="keyword">and</span> parse_line line =<br> <span class="constructor">String</span>.concat <span class="string">""</span> (<span class="constructor">List</span>.map parse_phrase line) <span class="keyword">in</span><br> <br> <span class="keyword">let</span> parse_lines lines =<br> <span class="constructor">String</span>.concat <span class="string">"<br />"</span> (<span class="constructor">List</span>.map parse_line lines) <span class="keyword">in</span><br> <br> <span class="keyword">let</span> to_lines print strings =<br> <span class="constructor">String</span>.concat <span class="string">"\n"</span> (<span class="constructor">List</span>.map print strings) <span class="keyword">in</span><br> <br> <span class="keyword">let</span> parse_talign = <span class="keyword">function</span><br> <span class="keywordsign">|</span> <span class="constructor">Some</span> talign <span class="keywordsign">-></span><br> (<span class="keyword">let</span> s = <span class="keyword">match</span> talign <span class="keyword">with</span><br> <span class="keywordsign">|</span> <span class="constructor">Right</span> <span class="keywordsign">-></span> <span class="string">"right"</span><br> <span class="keywordsign">|</span> <span class="constructor">Left</span> <span class="keywordsign">-></span> <span class="string">"left"</span><br> <span class="keywordsign">|</span> <span class="constructor">Center</span> <span class="keywordsign">-></span> <span class="string">"center"</span><br> <span class="keywordsign">|</span> <span class="constructor">Justify</span> <span class="keywordsign">-></span> <span class="string">"justify"</span> <span class="keyword">in</span><br> sprintf <span class="string">" style=\"text-align:%s\""</span> s)<br> <span class="keywordsign">|</span> <span class="constructor">None</span> <span class="keywordsign">-></span> <span class="string">""</span> <span class="keyword">in</span><br> <br> <span class="keyword">let</span> parse_padding = <span class="keyword">function</span><br> <span class="keywordsign">|</span> 0, 0 <span class="keywordsign">-></span> <span class="string">""</span><br> <span class="keywordsign">|</span> l, 0 <span class="keywordsign">-></span><br> sprintf <span class="string">" style=\"padding-left:%uem\""</span> l<br> <span class="keywordsign">|</span> 0, r <span class="keywordsign">-></span><br> sprintf <span class="string">" style=\"padding-right:%uem\""</span> r<br> <span class="keywordsign">|</span> l, r <span class="keywordsign">-></span><br> sprintf <span class="string">" style=\"padding-left:%uem; padding-right:%uem\""</span> l r <span class="keyword">in</span><br> <br> <span class="keyword">let</span> parse_options (attrs, talign, padding) =<br> <span class="constructor">String</span>.concat <span class="string">""</span> [parse_attrs attrs;<br> parse_talign talign;<br> parse_padding padding] <span class="keyword">in</span><br> <br> <span class="keyword">let</span> parse_valign = <span class="keyword">function</span><br> <span class="keywordsign">|</span> <span class="constructor">Some</span> x <span class="keywordsign">-></span><br> (<span class="keyword">let</span> s = <span class="keyword">match</span> x <span class="keyword">with</span><br> <span class="keywordsign">|</span> <span class="constructor">Top</span> <span class="keywordsign">-></span> <span class="string">"top"</span><br> <span class="keywordsign">|</span> <span class="constructor">Middle</span> <span class="keywordsign">-></span> <span class="string">"middle"</span><br> <span class="keywordsign">|</span> <span class="constructor">Bottom</span> <span class="keywordsign">-></span> <span class="string">"bottom"</span> <span class="keyword">in</span><br> sprintf <span class="string">" style=\"vertical-align:%s\""</span> s)<br> <span class="keywordsign">|</span> <span class="constructor">None</span> <span class="keywordsign">-></span> <span class="string">""</span> <span class="keyword">in</span><br> <br> <span class="keyword">let</span> parse_tableoptions (opts, valign) =<br> <span class="constructor">String</span>.concat <span class="string">""</span> [parse_options opts; parse_valign valign] <span class="keyword">in</span><br> <br> <span class="keyword">let</span> po = parse_options <span class="keyword">in</span><br> <span class="keyword">let</span> pt = parse_tableoptions <span class="keyword">in</span><br> <br> <span class="keyword">let</span> parse_cells (cells : cell list) =<br> <span class="constructor">String</span>.concat <span class="string">""</span> (<span class="constructor">List</span>.map (<span class="keyword">fun</span> ((celltype, topts, (colspan, rowspan)), lines) <span class="keywordsign">-></span><br> <span class="keyword">let</span> tag =<br> <span class="keyword">match</span> celltype <span class="keyword">with</span><br> <span class="keywordsign">|</span> <span class="constructor">Data</span> <span class="keywordsign">-></span> <span class="string">"td"</span><br> <span class="keywordsign">|</span> <span class="constructor">Head</span> <span class="keywordsign">-></span> <span class="string">"th"</span> <span class="keyword">in</span><br> <span class="keyword">let</span> rowspan =<br> <span class="keyword">match</span> rowspan <span class="keyword">with</span><br> <span class="keywordsign">|</span> <span class="constructor">Some</span> rowspan <span class="keywordsign">-></span> sprintf <span class="string">" rowspan=\"%d\""</span> rowspan<br> <span class="keywordsign">|</span> <span class="constructor">None</span> <span class="keywordsign">-></span> <span class="string">""</span> <span class="keyword">in</span><br> <span class="keyword">let</span> colspan =<br> <span class="keyword">match</span> colspan <span class="keyword">with</span><br> <span class="keywordsign">|</span> <span class="constructor">Some</span> colspan <span class="keywordsign">-></span> sprintf <span class="string">" colspan=\"%d\""</span> colspan<br> <span class="keywordsign">|</span> <span class="constructor">None</span> <span class="keywordsign">-></span> <span class="string">""</span> <span class="keyword">in</span><br> <span class="keyword">let</span> topts = pt topts <span class="keyword">in</span><br> <span class="keyword">let</span> attrs = <span class="constructor">String</span>.concat <span class="string">""</span> [topts; rowspan; colspan] <span class="keyword">in</span><br> sprintf <span class="string">"<%s%s>%s</%s>"</span> tag attrs (parse_lines lines) tag) cells) <span class="keyword">in</span><br> <br> <span class="keyword">let</span> parse_rows (rows : <span class="constructor">Textile</span>.row list) =<br> <span class="constructor">String</span>.concat <span class="string">""</span> (<span class="constructor">List</span>.map (<span class="keyword">fun</span> (topts, cells) <span class="keywordsign">-></span><br> sprintf <span class="string">"<tr%s>%s</tr>"</span> (pt topts) (parse_cells cells)) rows) <span class="keyword">in</span><br> <br> <span class="keyword">let</span> parse_list f =<br> <span class="keyword">let</span> <span class="keyword">rec</span> fill_lvl filled_lvl prev acc =<br> <span class="keyword">function</span><br> <span class="keywordsign">|</span> (lvl, line) :: t <span class="keyword">when</span> lvl = filled_lvl <span class="keywordsign">-></span><br> fill_lvl filled_lvl (parse_line line) (sprintf <span class="string">"%s<li>%s</li>"</span> acc prev) t<br> <span class="keywordsign">|</span> (lvl, line) :: t <span class="keyword">when</span> lvl = filled_lvl + 1 <span class="keywordsign">-></span><br> <span class="keyword">let</span> first = parse_line line <span class="keyword">in</span><br> <span class="keyword">let</span> lis, rest = fill_lvl lvl first <span class="string">""</span> t <span class="keyword">in</span><br> fill_lvl filled_lvl (prev ^ (f lis)) acc rest<br> <span class="keywordsign">|</span> ((lvl, _) :: t) <span class="keyword">as</span> l <span class="keyword">when</span> lvl < filled_lvl <span class="keywordsign">-></span><br> sprintf <span class="string">"%s<li>%s</li>"</span> acc prev, l<br> <span class="keywordsign">|</span> [] <span class="keyword">as</span> l <span class="keywordsign">-></span><br> sprintf <span class="string">"%s<li>%s</li>"</span> acc prev, l<br> <span class="keywordsign">|</span> (lvl, _) :: _ <span class="keywordsign">-></span><br> raise (<span class="constructor">Invalid_textile</span> (<br> sprintf <span class="string">"strange bull- or numlist: filled level is %d, but the next element has level %d"</span><br> filled_lvl lvl)) <span class="keyword">in</span><br> <span class="keyword">function</span><br> <span class="keywordsign">|</span> [] <span class="keywordsign">-></span> raise (<span class="constructor">Invalid_textile</span> <span class="string">"empty bull- or numlist"</span>)<br> <span class="keywordsign">|</span> (1, line)::t <span class="keywordsign">-></span><br> <span class="keyword">let</span> first = parse_line line <span class="keyword">in</span><br> <span class="keyword">let</span> lis, _ = fill_lvl 1 first <span class="string">""</span> t <span class="keyword">in</span><br> f lis<br> <span class="keywordsign">|</span> _ <span class="keywordsign">-></span> raise (<span class="constructor">Invalid_textile</span> <span class="string">"strange bull- or numlist"</span>) <span class="keyword">in</span><br> <br> <span class="keyword">let</span> pl = parse_lines <span class="keyword">in</span><br> <span class="keyword">match</span> block <span class="keyword">with</span><br> <span class="keywordsign">|</span> <span class="constructor">Header</span> (i, (opts, lines)) <span class="keywordsign">-></span><br> sprintf <span class="string">"<h%d%s>%s</h%d>"</span> i (po opts) (pl lines) i<br> <span class="keywordsign">|</span> <span class="constructor">Blockquote</span> (opts, lines) <span class="keywordsign">-></span><br> <span class="keyword">let</span> popts = po opts <span class="keyword">in</span><br> sprintf <span class="string">"<blockquote%s><p%s>%s</p></blockquote>"</span><br> popts popts (pl lines)<br> <span class="keywordsign">|</span> <span class="constructor">Footnote</span> (i, (opts, lines)) <span class="keywordsign">-></span><br> sprintf <span class="string">"<p id=\"fn%d\" class=\"footnote\"%s><sup>%d</sup> <a href=\"#ref%d\">↑</a> %s</p>"</span><br> i (po opts) i i (pl lines)<br> <span class="keywordsign">|</span> <span class="constructor">Paragraph</span> (opts, lines) <span class="keywordsign">-></span><br> sprintf <span class="string">"<p%s>%s</p>"</span> (po opts) (pl lines)<br> <span class="keywordsign">|</span> <span class="constructor">Blockcode</span> (opts, strings) <span class="keywordsign">-></span><br> <span class="keyword">let</span> popts = po opts <span class="keyword">in</span><br> sprintf <span class="string">"<pre%s class=\"blockcode\"><code>%s</code></pre>"</span><br> popts (to_lines esc strings)<br> <span class="keywordsign">|</span> <span class="constructor">Pre</span> (opts, strings) <span class="keywordsign">-></span><br> sprintf <span class="string">"<pre%s>%s</pre>"</span><br> (po opts) (to_lines esc strings)<br> <span class="keywordsign">|</span> <span class="constructor">Blocknott</span> (opts, strings) <span class="keywordsign">-></span><br> sprintf <span class="string">"<div%s>%s</div>"</span><br> (po opts) (to_lines print_nott strings)<br> <span class="keywordsign">|</span> <span class="constructor">Numlist</span> elements <span class="keywordsign">-></span><br> parse_list (sprintf <span class="string">"<ol>%s</ol>"</span>) elements<br> <span class="keywordsign">|</span> <span class="constructor">Bulllist</span> elements <span class="keywordsign">-></span><br> parse_list (sprintf <span class="string">"<ul>%s</ul>"</span>) elements<br> <span class="keywordsign">|</span> <span class="constructor">Table</span> (topts, rows) <span class="keywordsign">-></span><br> sprintf <span class="string">"<table%s>%s</table>"</span> (pt topts) (parse_rows rows)<br> <br> <span class="keyword">let</span> of_stream ?(escape_cdata=<span class="keyword">false</span>) ?(escape_nott=<span class="keyword">false</span>) stream =<br> <span class="keyword">let</span> next _ =<br> <span class="keyword">try</span><br> <span class="constructor">Some</span> (of_block ~escape_cdata ~escape_nott (<span class="constructor">Stream</span>.next stream))<br> <span class="keyword">with</span> <span class="constructor">Stream</span>.<span class="constructor">Failure</span> <span class="keywordsign">-></span> <span class="constructor">None</span> <span class="keyword">in</span><br> <span class="constructor">Stream</span>.from next<br> <br> </code></body></html>