Skip to content

Commit 6d3d514

Browse files
committed
rework
1 parent fa4c579 commit 6d3d514

2 files changed

Lines changed: 55 additions & 44 deletions

File tree

sphinx/ext/imgmath.py

Lines changed: 37 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -237,35 +237,42 @@ def render_math(self: HTMLTranslator, math: str) -> Tuple[Optional[str], Optiona
237237
depth = read_png_depth(outfn)
238238
elif image_format == 'svg':
239239
depth = read_svg_depth(outfn)
240-
return relfn, depth
241-
242-
# if latex or dvipng (dvisvgm) has failed once, don't bother to try again
243-
if hasattr(self.builder, '_imgmath_warned_latex') or \
244-
hasattr(self.builder, '_imgmath_warned_image_translator'):
245-
return None, None
246-
247-
# .tex -> .dvi
248-
try:
249-
dvipath = compile_math(latex, self.builder)
250-
except InvokeError:
251-
self.builder._imgmath_warned_latex = True # type: ignore
252-
return None, None
240+
else:
241+
# if latex or dvipng (dvisvgm) has failed once, don't bother to try again
242+
if hasattr(self.builder, '_imgmath_warned_latex') or \
243+
hasattr(self.builder, '_imgmath_warned_image_translator'):
244+
return None, None
245+
246+
# .tex -> .dvi
247+
try:
248+
dvipath = compile_math(latex, self.builder)
249+
except InvokeError:
250+
self.builder._imgmath_warned_latex = True # type: ignore
251+
return None, None
252+
253+
# .dvi -> .png/.svg
254+
try:
255+
if image_format == 'png':
256+
imgpath, depth = convert_dvi_to_png(dvipath, self.builder)
257+
elif image_format == 'svg':
258+
imgpath, depth = convert_dvi_to_svg(dvipath, self.builder)
259+
except InvokeError:
260+
self.builder._imgmath_warned_image_translator = True # type: ignore
261+
return None, None
253262

254-
# .dvi -> .png/.svg
255-
try:
256-
if image_format == 'png':
257-
imgpath, depth = convert_dvi_to_png(dvipath, self.builder)
258-
elif image_format == 'svg':
259-
imgpath, depth = convert_dvi_to_svg(dvipath, self.builder)
260-
except InvokeError:
261-
self.builder._imgmath_warned_image_translator = True # type: ignore
262-
return None, None
263+
if self.builder.config.imgmath_embed:
264+
encoded = base64.b64encode(open(outfn, "rb").read()).decode()
265+
mimetype = {'png': 'image/png', 'svg': 'image/svg+xml'}[image_format]
266+
img_src = f'data:{mimetype};base64,{encoded}'
267+
else:
268+
img_src = relfn
263269

264-
# Move generated image on tempdir to build dir
265-
ensuredir(path.dirname(outfn))
266-
shutil.move(imgpath, outfn)
270+
if not path.isfile(outfn):
271+
# Move generated image on tempdir to build dir
272+
ensuredir(path.dirname(outfn))
273+
shutil.move(imgpath, outfn)
267274

268-
return relfn, depth
275+
return img_src, depth
269276

270277

271278
def cleanup_tempdir(app: Sphinx, exc: Exception) -> None:
@@ -285,34 +292,21 @@ def get_tooltip(self: HTMLTranslator, node: Element) -> str:
285292
return ''
286293

287294

288-
def html_get_img_src(self: HTMLTranslator, fname: str) -> str:
289-
if self.builder.config.imgmath_embed:
290-
bname = path.basename(fname)
291-
outfn = path.join(self.builder.outdir, self.builder.imagedir, 'math', bname)
292-
mimetype = guess_mimetype(outfn, default='*')
293-
encoded = base64.b64encode(open(outfn, "rb").read()).decode()
294-
remove(outfn)
295-
return f'data:{mimetype};base64,{encoded}'
296-
else:
297-
return fname
298-
299-
300295
def html_visit_math(self: HTMLTranslator, node: nodes.math) -> None:
301296
try:
302-
fname, depth = render_math(self, '$' + node.astext() + '$')
297+
img_src, depth = render_math(self, '$' + node.astext() + '$')
303298
except MathExtError as exc:
304299
msg = str(exc)
305300
sm = nodes.system_message(msg, type='WARNING', level=2,
306301
backrefs=[], source=node.astext())
307302
sm.walkabout(self)
308303
logger.warning(__('display latex %r: %s'), node.astext(), msg)
309304
raise nodes.SkipNode from exc
310-
if fname is None:
305+
if img_src is None:
311306
# something failed -- use text-only as a bad substitute
312307
self.body.append('<span class="math">%s</span>' %
313308
self.encode(node.astext()).strip())
314309
else:
315-
img_src = html_get_img_src(self, fname)
316310
c = ('<img class="math" src="%s"' % img_src) + get_tooltip(self, node)
317311
if depth is not None:
318312
c += ' style="vertical-align: %dpx"' % (-depth)
@@ -326,7 +320,7 @@ def html_visit_displaymath(self: HTMLTranslator, node: nodes.math_block) -> None
326320
else:
327321
latex = wrap_displaymath(node.astext(), None, False)
328322
try:
329-
fname, depth = render_math(self, latex)
323+
img_src, depth = render_math(self, latex)
330324
except MathExtError as exc:
331325
msg = str(exc)
332326
sm = nodes.system_message(msg, type='WARNING', level=2,
@@ -341,12 +335,11 @@ def html_visit_displaymath(self: HTMLTranslator, node: nodes.math_block) -> None
341335
self.body.append('<span class="eqno">(%s)' % number)
342336
self.add_permalink_ref(node, _('Permalink to this equation'))
343337
self.body.append('</span>')
344-
if fname is None:
338+
if img_src is None:
345339
# something failed -- use text-only as a bad substitute
346340
self.body.append('<span class="math">%s</span></p>\n</div>' %
347341
self.encode(node.astext()).strip())
348342
else:
349-
img_src = html_get_img_src(self, fname)
350343
self.body.append(('<img src="%s"' % img_src) + get_tooltip(self, node) +
351344
'/></p>\n</div>')
352345
raise nodes.SkipNode

tests/test_ext_math.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,24 @@ def test_imgmath_svg(app, status, warning):
5656
assert re.search(html, content, re.S)
5757

5858

59+
@pytest.mark.skipif(not has_binary('dvisvgm'),
60+
reason='Requires dvisvgm" binary')
61+
@pytest.mark.sphinx('html', testroot='ext-math-simple',
62+
confoverrides={'extensions': ['sphinx.ext.imgmath'],
63+
'imgmath_image_format': 'svg',
64+
'imgmath_embed': True})
65+
def test_imgmath_svg_embed(app, status, warning):
66+
app.builder.build_all()
67+
if "LaTeX command 'latex' cannot be run" in warning.getvalue():
68+
raise pytest.skip.Exception('LaTeX command "latex" is not available')
69+
if "dvisvgm command 'dvisvgm' cannot be run" in warning.getvalue():
70+
raise pytest.skip.Exception('dvisvgm command "dvisvgm" is not available')
71+
72+
content = (app.outdir / 'index.html').read_text(encoding='utf8')
73+
html='<img src="data:image/svg\+xml;base64,[\w\+/]+="'
74+
assert re.search(html, content, re.S)
75+
76+
5977
@pytest.mark.sphinx('html', testroot='ext-math',
6078
confoverrides={'extensions': ['sphinx.ext.mathjax'],
6179
'mathjax_options': {'integrity': 'sha384-0123456789'}})

0 commit comments

Comments
 (0)