123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243(*********************************************************************************)(* Stog *)(* *)(* Copyright (C) 2012-2015 INRIA All rights reserved. *)(* Author: Maxence Guesdon, INRIA Saclay *)(* *)(* This program is free software; you can redistribute it and/or modify *)(* it under the terms of the GNU General Public License as *)(* published by the Free Software Foundation, version 3 of the License. *)(* *)(* This program is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU General Public License for more details. *)(* *)(* You should have received a copy of the GNU General Public *)(* License along with this program; if not, write to the Free Software *)(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)(* 02111-1307 USA *)(* *)(* As a special exception, you have permission to link this program *)(* with the OCaml compiler and distribute executables, as long as you *)(* follow the requirements of the GNU GPL in regard to all of the *)(* software in the executable aside from the OCaml compiler. *)(* *)(* Contact: Maxence.Guesdon@inria.fr *)(* *)(*********************************************************************************)(** *)moduleXR=Xtmpl.RewritemoduleXml=Xtmpl.Xmlletgensym=letcpt=ref0infun()->incrcpt;!cpt;;letcache=Hashtbl.create111;;letlatex_code_use_packagesl=String.concat""(List.map(funs->Printf.sprintf"\\usepackage%s\n"s)l);;letbuild_preambule~packages~defs~def_files=Printf.sprintf"\\pagestyle{empty}\n\\usepackage[utf8]{inputenc}\n%s\n%s\n%s"(latex_code_use_packagespackages)(String.concat"\n"(List.map(funfile->"\\input{"^file^"}")def_files))defs;;letget_latex_defsstogenv=let(stog,def_files)=let(stog,xmls)=Engine.get_in_envstogenv("","latex-defs-files")inmatchxmlswith[]->(stog,[])|_->lets=matchxmlswith[XR.Ds]->s.Xml.text|_->letmsg="Invalid filenames: "^(XR.to_stringxmls)infailwithmsginletfiles=List.mapStog_base.Misc.strip_string(Stog_base.Misc.split_strings[',';';'])inletfiles=List.filter((<>)"")filesinmatchfileswith[]->(stog,files)|_->let(stog,path)=Engine.get_pathstogenvinlet(_,doc)=Types.doc_by_pathstogpathinletdir=Filename.dirnamedoc.Types.doc_srcinletffilename=ifFilename.is_relativefilenamethenFilename.concatdirfilenameelsefilenamein(stog,List.mapffiles)inlet(stog,defs)=let(stog,xmls)=Engine.get_in_envstogenv("","latex-defs")inletdefs=matchxmlswith[]->""|_->XR.to_stringxmlsin(stog,defs)in(stog,defs,def_files);;letmake_svgoutdir?(packages=[])?(scale=1.1)?(def_files=[])?defslatex_code=letdefs=matchdefswithNone->""|Somes->s^"\n"intryHashtbl.findcachelatex_codewithNot_found->lettex=Filename.temp_file"stog"".tex"inlettex_aux=Filename.chop_extensiontex^".aux"inlettex_log=Filename.chop_extensiontex^".log"inletcode=Printf.sprintf"\\documentclass[12pt]{article}
%s
\\begin{document}
%s
\\end{document}
"(build_preambule~packages~defs~def_files)latex_codeinletbase=Filename.chop_extensiontexinletdvi=base^".dvi"inletsvg=Filename.concatoutdir(Filename.basename(Printf.sprintf"_latex%d.svg"(gensym())))inStog_base.Misc.file_of_string~file:texcode;letlog=Filename.temp_file"stog"".log"inletcommand=Printf.sprintf"(latex -output-directory=%s -interaction=batchmode %s > %s 2>&1) && \
dvisvgm -e --scale=%f -M 1.5 --no-fonts %s -s 2>> %s > %s"(Filename.get_temp_dir_name()|>Filename.quote)(Filename.quotetex)(Filename.quotelog)scale(Filename.quotedvi)(Filename.quotelog)(Filename.quotesvg)inmatchSys.commandcommandwith0->List.iter(funf->trySys.removefwith_->())[tex;tex_aux;tex_log;dvi;log];Hashtbl.addcachelatex_codesvg;svg|n->letlog=Stog_base.Misc.string_of_fileloginList.iter(funf->trySys.removefwith_->())[tex_aux;tex_log;log];failwith(Printf.sprintf"Command failed [%d]: %s\n=== log ===\n%s\n=== tex code ===\n%s"ncommandloglatex_code);;letcode_of_subs=letfb=functionXR.Dcode->Buffer.add_stringbcode.Xml.text|xml->failwith(Printf.sprintf"Invalid latex code: %s"(XR.to_string[xml]))infunction|[XR.Dcode]->code.Xml.text|subs->letb=Buffer.create256inList.iter(fb)subs;Buffer.contentsb;;letget_packagesstogenvargs=let(stog,s)=matchXR.get_att_cdataargs("","packages")withSomes->(stog,s)|None->let(stog,xmls)=Engine.get_in_args_or_envstogenvargs("","latex-packages")inmatchxmlswith[XR.Ds]->(stog,s.Xml.text)|_->(stog,"")inletl=List.mapStog_base.Misc.strip_string(Stog_base.Misc.split_strings[';'])in(stog,l);;letfun_latexstogenv?locargssubs=letcode=code_of_subssubsinlet(stog,packages)=get_packagesstogenvargsinletshowcode=XR.opt_att_cdataargs("","showcode")="true"inlet(stog,defs,def_files)=get_latex_defsstogenvinlet(stog,scale)=let(stog,xmls)=Engine.get_in_envstogenv("","latex-svg-scale")inletscale=matchxmlswith[]->None|_->lets=XR.to_stringxmlsintrySome(float_of_strings)with_->failwith(Printf.sprintf"Invalid latex-svg-scale %S"s)in(stog,scale)inletsvg=Filename.basename(make_svgstog.Types.stog_outdir~packages?scale~def_files~defscode)inleturl=Url.concatstog.Types.stog_base_urlsvginletxmls=(XR.node("","img")~atts:(XR.atts_of_list[("","class"),[XR.cdata"latex"];("","src"),[XR.cdata(Url.to_stringurl)];("","alt"),[XR.cdatacode];("","title"),[XR.cdatacode]])[])::(matchshowcodewithfalse->[]|true->[XR.node("","hcode")~atts:(XR.atts_one("","lang")[XR.cdata"tex"])[XR.cdatacode]])in(stog,xmls);;letfun_latex_bodystogenv?locargssubs=let(stog,packages)=get_packagesstogenvargsinlet(stog,defs,def_files)=get_latex_defsstogenvinletcode=code_of_subssubsinletcode=(build_preambule~packages~defs~def_files)^"\n\\begin{document}"^code^"\\end{document}"inlet(stog,path)=Engine.get_pathstogenvinlet(_,doc)=Types.doc_by_pathstogpathinletdoc_dir=Filename.dirnamedoc.Types.doc_srcinlet(stog,xmls)=Engine.get_in_envstogenv("","sectionning")inletsectionning=matchxmlswith[XR.D{Xml.text}]->List.mapStog_base.Misc.strip_string(Stog_base.Misc.split_stringtext[','])|_->Tags.default_sectionninginletparams={prefix=None;ext_file_prefix="";envs=[];Of_latex.sectionning=sectionning;image_sizes=Of_latex.SMap.empty;}inlet(tex,_)=Of_latex.parseparamscodedoc_dirin(stog,Of_latex.to_xmltex.Of_latex.body);;