File: C:/Users/fred/anaconda3/Lib/site-packages/bokeh/embed/elements.py
#-----------------------------------------------------------------------------
# Copyright (c) Anaconda, Inc., and Bokeh Contributors.
# All rights reserved.
#
# The full license is in the file LICENSE.txt, distributed with this software.
#-----------------------------------------------------------------------------
''' Generate various HTML elements from Bokeh render items.
'''
#-----------------------------------------------------------------------------
# Boilerplate
#-----------------------------------------------------------------------------
from __future__ import annotations
import logging # isort:skip
log = logging.getLogger(__name__)
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
# Standard library imports
from html import escape
from typing import TYPE_CHECKING, Any
## External imports
if TYPE_CHECKING:
from jinja2 import Template
# Bokeh imports
from ..core.json_encoder import serialize_json
from ..core.templates import (
DOC_JS,
FILE,
MACROS,
PLOT_DIV,
get_env,
)
from ..document.document import DEFAULT_TITLE
from ..settings import settings
from ..util.serialization import make_globally_unique_css_safe_id
from .util import RenderItem
from .wrappers import wrap_in_onload, wrap_in_safely, wrap_in_script_tag
if TYPE_CHECKING:
from ..core.types import ID
from ..document.document import DocJson
from .bundle import Bundle
#-----------------------------------------------------------------------------
# Globals and constants
#-----------------------------------------------------------------------------
__all__ = (
'div_for_render_item',
'html_page_for_render_items',
'script_for_render_items',
)
#-----------------------------------------------------------------------------
# General API
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Dev API
#-----------------------------------------------------------------------------
def div_for_render_item(item: RenderItem) -> str:
''' Render an HTML div for a Bokeh render item.
Args:
item (RenderItem):
the item to create a div for
Returns:
str
'''
return PLOT_DIV.render(doc=item, macros=MACROS)
def html_page_for_render_items(
bundle: Bundle | tuple[str, str],
docs_json: dict[ID, DocJson],
render_items: list[RenderItem],
title: str | None,
template: Template | str | None = None,
template_variables: dict[str, Any] = {},
) -> str:
''' Render an HTML page from a template and Bokeh render items.
Args:
bundle (tuple):
A tuple containing (bokeh_js, bokeh_css).
docs_json (JSON-like):
Serialized Bokeh Document.
render_items (RenderItems):
Specific items to render from the document and where.
title (str or None):
A title for the HTML page. If None, DEFAULT_TITLE is used.
template (str or Template or None, optional):
A Template to be used for the HTML page. If None, FILE is used.
template_variables (dict, optional):
Any Additional variables to pass to the template.
Returns:
str
'''
if title is None:
title = DEFAULT_TITLE
bokeh_js, bokeh_css = bundle
json_id = make_globally_unique_css_safe_id()
json = escape(serialize_json(docs_json), quote=False)
json = wrap_in_script_tag(json, "application/json", json_id)
script = wrap_in_script_tag(script_for_render_items(json_id, render_items))
context = template_variables.copy()
context.update(dict(
title = title,
bokeh_js = bokeh_js,
bokeh_css = bokeh_css,
plot_script = json + script,
docs = render_items,
base = FILE,
macros = MACROS,
))
if len(render_items) == 1:
context["doc"] = context["docs"][0]
context["roots"] = context["doc"].roots
# XXX: backwards compatibility, remove for 1.0
context["plot_div"] = "\n".join(div_for_render_item(item) for item in render_items)
if template is None:
template = FILE
elif isinstance(template, str):
template = get_env().from_string("{% extends base %}\n" + template)
html = template.render(context)
return html
def script_for_render_items(docs_json_or_id: ID | dict[ID, DocJson], render_items: list[RenderItem],
app_path: str | None = None, absolute_url: str | None = None) -> str:
''' Render an script for Bokeh render items.
Args:
docs_json_or_id:
can be None
render_items (RenderItems) :
Specific items to render from the document and where
app_path (str, optional) :
absolute_url (Theme, optional) :
Returns:
str
'''
if isinstance(docs_json_or_id, str):
docs_json = f"document.getElementById('{docs_json_or_id}').textContent"
else:
# XXX: encodes &, <, > and ', but not ". This is because " is used a lot in JSON,
# and encoding it would significantly increase size of generated files. Doing so
# is safe, because " in strings was already encoded by JSON, and the semi-encoded
# JSON string is included in JavaScript in single quotes.
docs_json = serialize_json(docs_json_or_id, pretty=False) # JSON string
docs_json = escape(docs_json, quote=False) # make HTML-safe
docs_json = docs_json.replace("'", "'") # remove single quotes
docs_json = docs_json.replace("\\", "\\\\") # double encode escapes
docs_json = "'" + docs_json + "'" # JS string
js = DOC_JS.render(
docs_json=docs_json,
render_items=serialize_json([ item.to_json() for item in render_items ], pretty=False),
app_path=app_path,
absolute_url=absolute_url,
)
if not settings.dev:
js = wrap_in_safely(js)
return wrap_in_onload(js)
#-----------------------------------------------------------------------------
# Private API
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Code
#-----------------------------------------------------------------------------