1""" 2Implement the tikz package for html output. 3The original tikz and latex do most of the work and then pdf2svg (or similar 4software) turns it into a svg image. 5Needs Beautiful Soup, Jinja2, and pdf2svg or similar 6""" 7 8import os 9import string 10import subprocess 11import shutil 12import tempfile 13from plasTeX import Environment, NoCharSubEnvironment, Macro 14from plasTeX.PackageResource import PackageResource 15 16from plasTeX.Logging import getLogger 17log = getLogger() 18 19try: 20 from jinja2 import Template 21except ImportError: 22 log.warning('Cannot find jinja2 lib. Cannot use tikz.') 23 24try: 25 from bs4 import BeautifulSoup 26except ImportError: 27 log.warning('Cannot find BeautifulSoup lib. Cannot use tikz.') 28 29 30class tikzpicture(NoCharSubEnvironment): 31 """ 32 A tikz picture whose content will be converted in the processFileContent callback. 33 """ 34 class matrix(Environment): 35 """ 36 Avoids conflict with amsmath matrix thanks to the context stack 37 mechanism. 38 """ 39 40 class draw(Macro): 41 """ Only avoids unrecognized command warning. """ 42 43 class fill(Macro): 44 """ Only avoids unrecognized command warning. """ 45 46 class filldraw(Macro): 47 """ Only avoids unrecognized command warning. """ 48 49 class node(Macro): 50 """ Only avoids unrecognized command warning. """ 51 52 class path(Macro): 53 """ Only avoids unrecognized command warning. """ 54 55 class clip(Macro): 56 """ Only avoids unrecognized command warning. """ 57 58def tikzConvert(document, content, envname, placeholder): 59 tmp_dir = document.userdata[envname]['tmp_dir'] 60 working_dir = document.userdata['working-dir'] 61 outdir = document.config['files']['directory'] 62 outdir = string.Template(outdir).substitute( 63 {'jobname': document.userdata.get('jobname', '')}) 64 target_dir = os.path.join(working_dir, outdir, 'images') 65 if not os.path.isdir(target_dir): 66 os.makedirs(target_dir) 67 template = document.userdata[envname]['template'] 68 compiler = document.userdata[envname]['compiler'] 69 pdf2svg = document.userdata[envname]['pdf2svg'] 70 71 cwd = os.getcwd() 72 os.chdir(tmp_dir) 73 soup = BeautifulSoup(content, "html.parser") 74 encoding = soup.original_encoding 75 76 envs = soup.findAll(envname) 77 for env in envs: 78 object_id = env.attrs['id'] 79 basepath = os.path.join(tmp_dir, object_id) 80 texpath = basepath + '.tex' 81 pdfpath = basepath + '.pdf' 82 svgpath = basepath + '.svg' 83 84 context = { 'tikzpicture': env.text.strip() } 85 template.stream(**context).dump(texpath, encoding) 86 87 subprocess.call([compiler, texpath]) 88 subprocess.call([pdf2svg, pdfpath, svgpath]) 89 destination = os.path.join(target_dir, object_id+'.svg') 90 if os.path.isfile(destination): 91 os.remove(destination) 92 shutil.move(svgpath, target_dir) 93 94 obj = soup.new_tag( 95 'object', 96 type='image/svg+xml', 97 data='images/' + object_id + '.svg') 98 obj.string = document.context.terms.get( 99 placeholder, 100 placeholder) + '\n' + env.text.strip() 101 obj.attrs['class'] = envname 102 div = soup.new_tag('div') 103 div.attrs['class'] = envname 104 div.insert(1, obj) 105 106 env.replace_with(div) 107 os.chdir(cwd) 108 try: 109 # python2 110 result = unicode(soup) 111 except NameError: 112 # python3 113 result = str(soup) 114 return result 115 116def ProcessOptions(options, document): 117 """This is called when the package is loaded.""" 118 119 try: 120 with open(document.config['html5']['tikz-template'], "r") as file: 121 template = file.read() 122 except IOError: 123 log.info('Using default TikZ template.') 124 template = u"\\documentclass{standalone}\n\\usepackage{tikz}" + \ 125 u"\\begin{document}{{ tikzpicture }}\\end{document}" 126 document.userdata['tikzpicture'] = { 127 'template': Template(template), 128 'tmp_dir': tempfile.mkdtemp(), 129 'compiler': document.config['html5']['tikz-compiler'], 130 'pdf2svg': document.config['html5']['tikz-converter'], 131 } 132 133 def convert(document, content): 134 return tikzConvert(document, content, 'tikzpicture', 'TikZ picture') 135 136 cb = PackageResource( 137 renderers='html5', 138 key='processFileContents', 139 data=convert) 140 document.addPackageResource(cb) 141