Spaces:
Running
Running
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
""" | |
Convert the markdown generated from Jupyter notebooks to preserve | |
rendered images, etc. | |
""" | |
import os | |
import pathlib | |
import re | |
import sys | |
import time | |
import traceback | |
import typing | |
from icecream import ic # pylint: disable=E0401 | |
from selenium import webdriver # pylint: disable=E0401 | |
class Converter: | |
""" | |
HTML/Markdown conversion | |
""" | |
PAT_HEADER = re.compile(r"^(```python\n\# for use.*production:\n.*\n```\n)", re.MULTILINE) | |
PAT_SOURCE = re.compile(r"\s+src\=\"(\S+)\"") | |
REPLACEMENT_HEADER: str = """ | |
!!! note | |
To run this notebook in JupyterLab, load [`examples/{}.ipynb`]({}/examples/{}.ipynb) | |
""" | |
def __init__ ( | |
self, | |
src_url: str, | |
) -> None: | |
""" | |
Constructor. | |
""" | |
self.src_url: str = src_url | |
def replace_sys_header ( | |
self, | |
text: str, | |
stem: str, | |
*, | |
debug: bool = False, | |
) -> str: | |
""" | |
Replace the initial cell in a tutorial notebook. | |
""" | |
output: typing.List[ str ] = [] | |
for chunk in self.PAT_HEADER.split(text): | |
m_header: typing.Optional[ re.Match ] = self.PAT_HEADER.match(chunk) | |
if debug: | |
ic(m_header) | |
if m_header: | |
header: str = self.REPLACEMENT_HEADER.format(stem, self.src_url, stem) | |
output.append(header) | |
else: | |
output.append(chunk) | |
return "\n".join(output) | |
def get_pyvis_html ( | |
self, | |
iframe: str, | |
*, | |
debug: bool = False, | |
) -> str: | |
""" | |
Locate the HTML files generated by `PyVis` if any. | |
This assumes the HTML files are named `tmp.fig*.*` | |
""" | |
source_html: typing.Optional[ str ] = None | |
m_source: typing.Optional[ re.Match ] = self.PAT_SOURCE.search(iframe) | |
if m_source: | |
source_html = m_source.group(1) | |
if debug: | |
ic(source_html) | |
if "tmp.fig" not in source_html: # type: ignore | |
# <iframe/> wasn't generated by PyVis | |
source_html = None | |
return source_html # type: ignore | |
def render_screenshot ( | |
self, | |
source_html: str, | |
source_png, | |
) -> None: | |
""" | |
use Selenium to render `source_png` from `source_html` | |
""" | |
#chrome_path = os.getcwd() + "/chromedriver" | |
#chrome_options = Options() | |
browser: webdriver.Chrome = webdriver.Chrome() | |
browser.get(source_html) | |
time.sleep(10) | |
browser.get_screenshot_as_file(source_png) | |
browser.quit() | |
def replace_pyvis_iframe ( | |
self, | |
text: str, | |
parent: pathlib.Path, | |
stem: str, | |
*, | |
debug: bool = False, | |
) -> str: | |
""" | |
Substitute static images for the rendered graphs. | |
""" | |
output: typing.List[ str ] = [] | |
in_iframe: bool = False | |
for line in text.split("\n"): | |
if line.startswith("<iframe"): | |
in_iframe = True | |
if not in_iframe: | |
output.append(line) | |
elif line.strip().startswith("src="): | |
src_html: str = self.get_pyvis_html(line) | |
src_png: str = src_html.replace(".html", ".png") | |
if debug: | |
ic(src_png) | |
try: | |
os.mkdir(f"{parent}/{stem}_files") | |
except: # pylint: disable=W0702 | |
pass | |
self.render_screenshot( | |
f"file://{os.getcwd()}/examples/{src_html}", | |
f"{parent}/{stem}_files/{src_png}", | |
) | |
output.append(f"") | |
if line.startswith("></iframe>"): | |
in_iframe = False | |
return "\n".join(output) | |
if __name__ == "__main__": | |
try: | |
conv: Converter = Converter( | |
"https://github.com/DerwenAI/textgraphs/blob/main", | |
) | |
filename: pathlib.Path = pathlib.Path(sys.argv[1]) | |
_parent: pathlib.Path = filename.parent | |
_stem: str = filename.stem | |
ic(filename, _parent, _stem) | |
with open(filename, "r", encoding = "utf-8") as fp: | |
html: str = fp.read() | |
html = conv.replace_sys_header( # pylint: disable=C0103 | |
html, | |
_stem, | |
debug = False, # True | |
) | |
#print(text) | |
#sys.exit(0) | |
html = conv.replace_pyvis_iframe( # pylint: disable=C0103 | |
html, | |
_parent, | |
_stem, | |
debug = True, # False | |
) | |
with open(filename, "w", encoding = "utf-8") as fp: | |
fp.write(html) | |
except Exception as ex: # pylint: disable=W0718 | |
ic(ex) | |
traceback.print_exc() | |