WeChatMsg/resource/render/engine.py
2023-05-22 11:32:12 +08:00

122 lines
4.0 KiB
Python

import os
try:
from collections.abc import Iterable
except ImportError:
from collections import Iterable
from jinja2 import Environment
from ..commons import utils
from ..datasets import EXTRA, FILENAMES
from ..globals import CurrentConfig, NotebookType
from ..types import Any, Optional
from .display import HTML, Javascript
def write_utf8_html_file(file_name: str, html_content: str):
with open(file_name, "w+", encoding="utf-8") as html_file:
html_file.write(html_content)
class RenderEngine:
def __init__(self, env: Optional[Environment] = None):
self.env = env or CurrentConfig.GLOBAL_ENV
@staticmethod
def generate_js_link(chart: Any) -> Any:
if not chart.js_host:
chart.js_host = CurrentConfig.ONLINE_HOST
links = []
for dep in chart.js_dependencies.items:
# TODO: if?
if dep.startswith("https://api.map.baidu.com"):
links.append(dep)
if dep in FILENAMES:
f, ext = FILENAMES[dep]
links.append("{}{}.{}".format(chart.js_host, f, ext))
else:
for url, files in EXTRA.items():
if dep in files:
f, ext = files[dep]
links.append("{}{}.{}".format(url, f, ext))
break
chart.dependencies = links
return chart
def render_chart_to_file(self, template_name: str, chart: Any, path: str, **kwargs):
"""
Render a chart or page to local html files.
:param chart: A Chart or Page object
:param path: The destination file which the html code write to
:param template_name: The name of template file.
"""
tpl = self.env.get_template(template_name)
html = utils.replace_placeholder(
tpl.render(chart=self.generate_js_link(chart), **kwargs)
)
write_utf8_html_file(path, html)
def render_chart_to_template(self, template_name: str, chart: Any, **kwargs) -> str:
tpl = self.env.get_template(template_name)
return utils.replace_placeholder(
tpl.render(chart=self.generate_js_link(chart), **kwargs)
)
def render_chart_to_notebook(self, template_name: str, **kwargs) -> str:
tpl = self.env.get_template(template_name)
return utils.replace_placeholder(tpl.render(**kwargs))
def render(
chart, path: str, template_name: str, env: Optional[Environment], **kwargs
) -> str:
RenderEngine(env).render_chart_to_file(
template_name=template_name, chart=chart, path=path, **kwargs
)
return os.path.abspath(path)
def render_embed(
chart, template_name: str, env: Optional[Environment], **kwargs
) -> str:
return RenderEngine(env).render_chart_to_template(
template_name=template_name, chart=chart, **kwargs
)
def render_notebook(self, notebook_template, lab_template):
instance = self if isinstance(self, Iterable) else (self,)
if CurrentConfig.NOTEBOOK_TYPE == NotebookType.JUPYTER_NOTEBOOK:
require_config = utils.produce_require_dict(self.js_dependencies, self.js_host)
return HTML(
RenderEngine().render_chart_to_notebook(
template_name=notebook_template,
charts=instance,
config_items=require_config["config_items"],
libraries=require_config["libraries"],
)
)
if CurrentConfig.NOTEBOOK_TYPE == NotebookType.JUPYTER_LAB:
return HTML(
RenderEngine().render_chart_to_notebook(
template_name=lab_template, charts=instance
)
)
if CurrentConfig.NOTEBOOK_TYPE == NotebookType.NTERACT:
return HTML(self.render_embed())
if CurrentConfig.NOTEBOOK_TYPE == NotebookType.ZEPPELIN:
print("%html " + self.render_embed())
def load_javascript(chart):
scripts = []
for dep in chart.js_dependencies.items:
f, ext = FILENAMES[dep]
scripts.append("{}{}.{}".format(CurrentConfig.ONLINE_HOST, f, ext))
return Javascript(lib=scripts)