Skip to content

Commit

Permalink
added static icon rendering for HTML files
Browse files Browse the repository at this point in the history
  • Loading branch information
o-smirnov committed Sep 22, 2023
1 parent 36f2ce2 commit 6f8987a
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 30 deletions.
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ include requirements.txt

# needs to be installed in site-packages
recursive-include radiopadre/notebooks *.ipynb
recursive-include radiopadre/ *.js *.css *.ico
recursive-include radiopadre/ *.js *.css *.ico *.png
recursive-include radiopadre_kernel/js9 *.html

# needs to be in tarball, copied over by setup script
Expand Down
Binary file added radiopadre/html/html-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 36 additions & 22 deletions radiopadre/htmlfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,34 +30,37 @@
message(f"{os.getcwd()}$ npm list -g puppeteer returns code {exc.returncode}")
nodejs = None

_methods = (["puppeteer"] if nodejs else []) + (["phantomjs"] if phantomjs else [])
_methods = (["puppeteer"] if nodejs else []) + (["phantomjs"] if phantomjs else []) + ["icon"]

settings.html.method = _methods[0], DocString(f"HTML rendering method (available: {', '.join(_methods)})")
settings.html.use_pngs = True, DocString(f"use static PNG renderings (*.png for *.html) if provided in directory")

_icon_url = "/static/radiopadre-www/html-icon.png"

if _methods:
settings.html.method = _methods[0], DocString(f"HTML rendering method (available: {', '.join(_methods)})")
else:
settings.html.method = None, DocString(f"No HTML rendering (phantomjs/nodejs not found)")
settings.html.debug = False, DocString("enables debugging output from phantomjs and/or puppeteer")

class RenderError(RuntimeError):
pass

def _render_html(url, dest, width, height, timeout):
def _render_html_thumbnail(url_or_path, img_repr_path, width, height, timeout):
"""Renders an HTML document (url or path) to a PNG image at imag_repr_path.
url_link is the URL that the thumbnail will HREF to.
The static/icon methods may ignore img_repr_path and use a different image.
"""
if settings.html.method == "phantomjs":
script = os.path.join(os.path.dirname(__file__), "html/phantomjs-html-thumbnail.js")
cmd = [phantomjs]
if settings.html.debug:
cmd.append("--debug=true")
cmd += [script, url, dest, width, height, timeout]
cmd += [script, url_or_path, img_repr_path, width, height, timeout]
env = os.environ.copy()
env['QT_QPA_PLATFORM'] = 'offscreen'
elif settings.html.method == "puppeteer":
script = os.path.join(os.path.dirname(__file__), "html/puppeteer-html-thumbnail.js")
cmd = [nodejs, script, url, dest, width, height, timeout]
cmd = [nodejs, script, url_or_path, img_repr_path, width, height, timeout]
env = os.environ.copy()
env['NODE_PATH'] = f"{sys.prefix}/node_modules:{sys.prefix}/lib/node_modules"
else:
raise RenderError("settings.html.method not set")


# run a renderer
error = None
cmd = list(map(str, cmd))
# run the command set up
Expand Down Expand Up @@ -98,17 +101,25 @@ def _render_thumb_impl(self, width=None, height=None, refresh=False, **kw):
width = settings.html.get(width=width)
height = settings.html.get(height=height)

thumbnail, thumbnail_url, update = self._get_cache_file("html-render", "png",
keydict=dict(width=width, height=height))
img_representation = os.path.splitext(self.fullpath)[0] + ".png"
document_url = render_url(self.fullpath)

# make fresh image if we don't have a static one, or use_pngs is disabled
if not os.path.exists(img_representation) or not settings.html.use_pngs:
if settings.html.method == "icon":
return f"<a href='{document_url}' target='_blank'><img src='{_icon_url}' width={width} alt='?'></a>"

if update or refresh:
url = "file://" + os.path.abspath(self.fullpath)
try:
_render_html(url, thumbnail, width, height, 200)
except Exception as exc:
return render_error(str(exc))
img_representation, thumbnail_url, update = self._get_cache_file("html-render", "png",
keydict=dict(width=width, height=height))

return imagefile.ImageFile._render_thumbnail(thumbnail, url=render_url(self.fullpath), npix=width) + "\n"
if update or refresh:
url = "file://" + os.path.abspath(self.fullpath)
try:
_render_html_thumbnail(url, img_representation, width, height, 200)
except Exception as exc:
return render_error(str(exc))

return imagefile.ImageFile._render_thumbnail(img_representation, url=document_url, npix=width) + "\n"


class URL(ItemBase):
Expand All @@ -135,11 +146,14 @@ def _render_thumb_impl(self, width=None, height=None, **kw):
delay = kw.get('delay', 200)
filename = re.sub(r"[/:;&?#]", "_", self.url) + ".png"

if settings.hmtl.method == "icon":
return f"<a href='{self.url}' target='_blank'><img src='{_icon_url}' width={width} alt='?'></a>"

basepath, baseurl = radiopadre.get_cache_dir("./.urls", "html-render") # fake ".urls" name which will be stripped
thumbnail = f"{basepath}/{filename}"

try:
_render_html(self.url, thumbnail, width, height, delay)
_render_html_thumbnail(self.url, thumbnail, width, height, delay)
except Exception as exc:
return render_error(str(exc))

Expand Down
16 changes: 9 additions & 7 deletions radiopadre/pdffile.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import subprocess
import shlex

from radiopadre.file import FileBase
from radiopadre.render import render_url, render_error
Expand All @@ -11,17 +12,18 @@ def __init__(self, *args, **kw):
def render_html(self,**kw):
return self.render_thumb(**kw)

def _render_thumb_impl(self, npix=None, **kw):
def _render_thumb_impl(self, npix=None, refresh=False, **kw):
thumbnail, thumbnail_url, update = self._get_cache_file("pdf-render", "png")
npix = npix or 800

if update:
cmd = "gs -sDEVICE=png16m -sOutputFile={thumbnail} -dLastPage=1 -r300 -dDownScaleFactor=4 -dBATCH " \
"-dNOPAUSE {self.fullpath}".format(**locals())
if update or refresh:
cmd = f"gs -sDEVICE=png16m -sOutputFile={shlex.quote(thumbnail)} -dLastPage=1 -r300 -dDownScaleFactor=4 -dBATCH " + \
f"-dNOPAUSE {shlex.quote(self.fullpath)}"
try:
output = subprocess.check_output(cmd, shell=True)
cmd = subprocess.run(cmd, check=True, shell=True, capture_output=True)
except subprocess.CalledProcessError as exc:
print(f"{cmd}: {exc.output}")
return render_error(f"phantomjs error (code {exc.returncode})")
print(f"{cmd} stdout: {exc.stdout.decode()}")
print(f"{cmd} stderr: {exc.stderr.decode()}")
return render_error(f"gs error (code {exc.returncode})")

return imagefile.ImageFile._render_thumbnail(thumbnail, url=render_url(self.fullpath), npix=npix) + "\n"

0 comments on commit 6f8987a

Please sign in to comment.