Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch to make tabulator work offline in jupyter notebook in "pn.config.inline" mode #6607

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions panel/io/notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
from .embed import embed_state
from .model import add_to_doc, diff
from .resources import (
PANEL_DIR, Resources, _env, bundle_resources, patch_model_css,
CDN_DIST, DIST_DIR, PANEL_DIR, Resources, _env, bundle_resources,
patch_model_css,
)
from .state import state

Expand Down Expand Up @@ -184,6 +185,33 @@ def render_template(
)
return ({'text/html': html, EXEC_MIME: ''}, {EXEC_MIME: {'id': ref}})


def _visit_json_data(data, parent=None, key=None):
if parent is not None:
yield data, parent, key
typ = type(data)
if typ is dict:
for k, v in data.items():
yield from _visit_json_data(v, data, k)
elif typ in {list, tuple, set}:
for i, v in enumerate(data):
yield from _visit_json_data(v, data, i)


def patch_inline_css(doc_data):
for data, _, _ in _visit_json_data(doc_data):
typ = type(data)
if typ is dict:
if 'type' in data and 'name' in data and data['name'] == 'ImportedStyleSheet' and data['type'] == 'object':
url = data['attributes']['url']
if url.startswith(CDN_DIST):
path = DIST_DIR / url.replace(CDN_DIST, '')
if path.exists():
css = path.read_text(encoding='utf-8')
data['name'] = 'InlineStyleSheet'
data['attributes']['css'] = css
del data['attributes']['url']

def render_model(
model: 'Model', comm: Optional['Comm'] = None, resources: str = 'cdn'
) -> Tuple[Dict[str, str], Dict[str, Dict[str, str]]]:
Expand All @@ -200,6 +228,10 @@ def render_model(
model.document._template_variables['dist_url'] = dist_url

(docs_json, [render_item]) = standalone_docs_json_and_render_items([model], suppress_callback_warning=True)

if resources == 'inline':
patch_inline_css(docs_json)

div = div_for_render_item(render_item)
render_json = render_item.to_json()
requirements = [pnext._globals[ext] for ext in pnext._loaded_extensions
Expand Down Expand Up @@ -239,12 +271,15 @@ def render_mimebundle(
model: 'Model', doc: 'Document', comm: 'Comm',
manager: Optional['CommManager'] = None,
location: Optional['Location'] = None,
resources: str = 'cdn'
resources: str = None
) -> Tuple[Dict[str, str], Dict[str, Dict[str, str]]]:
"""
Displays bokeh output inside a notebook using the PyViz display
and comms machinery.
"""
if resources is None:
from ..config import config
resources = 'inline' if config.inline else 'cdn'
# WARNING: Patches the client comm created by some external library
# e.g. HoloViews, with an on_open handler that will initialize
# the server comm.
Expand Down
54 changes: 53 additions & 1 deletion panel/io/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -816,8 +816,60 @@ def js_raw(self):
# Inline local dist resources
js_files = self._collect_external_resources("__javascript__")
self.extra_resources(js_files, '__javascript__')
skip_import_map = None
inlined_requires = {}
def get_inlined_js(url):
nonlocal skip_import_map
if skip_import_map is None:
from .notebook import require_components
_, _, exports, skip_imports = require_components()
export_to_module_map = {v:k for k,v in exports.items()}
skip_import_map = {}
for k, js_files in skip_imports.items():
for js_file in js_files:
skip_import_map[js_file] = k, export_to_module_map.get(k, k)
path = DIST_DIR / url.replace(CDN_DIST, '')
js = path.read_text(encoding='utf-8')
if url in skip_import_map:
export, modname = skip_import_map[url]
inlined_requires[modname] = export
js = '''
//console.log('in inlined script');
let define_orig = this.define;
this.define_orig = define_orig;
const fnthis = this;
const fndefines = [];
this.define = function define(...args){
//console.log('define args:', args)
if (typeof args[0] == "string" ) {
return define_orig.apply(fnthis, args);
} else {
fndefines.push(%(modname)r);
//console.log('defining %(modname)s');
return define_orig.apply(fnthis, [%(modname)r].concat(args));
}
};
this.define.amd = define_orig && define_orig.amd;
try {
//console.log('loading ', %(modname)r, this, this.define);
%(js)s;
} finally {
fnthis.define = define_orig;
//console.log('fndefines:', fndefines);
for (var mod of fndefines) {
require([mod], function(exp){
if (mod == %(modname)r) {
fnthis[%(export)r] = exp;
}
})
}
}
''' % dict(js=js, export=export, modname=modname)
return js

raw_js += [
(DIST_DIR / js.replace(CDN_DIST, '')).read_text(encoding='utf-8')
get_inlined_js(js)
# (DIST_DIR / js.replace(CDN_DIST, '')).read_text(encoding='utf-8')
for js in js_files if is_cdn_url(js)
]

Expand Down
5 changes: 4 additions & 1 deletion panel/models/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class PanelMarkupView extends WidgetView {
}
}
if (Object.keys(this._initialized_stylesheets).length === 0) {
this.style_redraw()
setTimeout(() => { this.style_redraw() }, 1)
}
}

Expand Down Expand Up @@ -175,6 +175,9 @@ export abstract class HTMLBoxView extends LayoutDOMView {
})
}
}
if (Object.keys(this._initialized_stylesheets).length === 0) {
setTimeout(() => { this.style_redraw() }, 1)
}
}

style_redraw(): void {
Expand Down