Skip to content
Draft
Show file tree
Hide file tree
Changes from 5 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
2 changes: 1 addition & 1 deletion panel/_templates/autoload_panel_js.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ calls it with the rendered model.
console.debug("Bokeh: injecting script tag for BokehJS library: ", url);
element.textContent = `
import ${name} from "${url}"
window.${name} = ${name}
window.${name.replace('* as ', '')} = ${name.replace('* as ', '')}
window._bokeh_on_load()
`
document.head.appendChild(element);
Expand Down
2 changes: 1 addition & 1 deletion panel/_templates/js_resources.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
{%- for name, file in js_module_exports.items() %}
<script type="module">
import {{ name }} from "{% if not file.startswith('http') %}./{% endif %}{{ file }}";
window.{{ name }} = {{ name }}
window.{{ name.replace('* as ', '') }} = {{ name.replace('* as ', '') }}
</script>
{%- endfor %}

Expand Down
2 changes: 2 additions & 0 deletions panel/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ class panel_extension(_pyviz_extension):
'jsoneditor': 'panel.models.jsoneditor',
'katex': 'panel.models.katex',
'mathjax': 'panel.models.mathjax',
'myst': 'panel.models.myst',
'perspective': 'panel.models.perspective',
'plotly': 'panel.models.plotly',
'tabulator': 'panel.models.tabulator',
Expand All @@ -689,6 +690,7 @@ class panel_extension(_pyviz_extension):
'gridstack': ['GridStack'],
'katex': ['katex'],
'mathjax': ['MathJax'],
'myst': ['mystjs'],
'perspective': ["customElements.get('perspective-viewer')"],
'plotly': ['Plotly'],
'tabulator': ['Tabulator'],
Expand Down
6 changes: 4 additions & 2 deletions panel/dist/css/markdown.css
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,8 @@ h2:hover a.header-anchor::before {
visibility: visible;
}

.codehilite {
.codehilite,
pre > code.hljs {
padding: 1rem 1.25rem;
margin-top: 1rem;
margin-bottom: 1rem;
Expand All @@ -341,6 +342,7 @@ pre {
}

.codehilite > pre > code,
.codehilite > code {
.codehilite > code,
pre > code.hljs {
white-space: break-spaces;
}
2 changes: 1 addition & 1 deletion panel/models/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export class HTMLView extends PanelMarkupView {
return processed_text.join("")
}

private contains_tex(html: string): boolean {
contains_tex(html: string): boolean {
if (!this.provider.MathJax) {
return false
}
Expand Down
1 change: 1 addition & 0 deletions panel/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export {JSONEditor} from "./jsoneditor"
export {KaTeX} from "./katex"
export {Location} from "./location"
export {MathJax} from "./mathjax"
export {MyST} from "./myst"
export {PDF} from "./pdf"
export {Perspective} from "./perspective"
export {Player} from "./player"
Expand Down
37 changes: 37 additions & 0 deletions panel/models/myst.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from ..config import config
from ..io.resources import bundled_files
from ..util import classproperty
from .markup import HTML


class MyST(HTML):
"""
A bokeh model to render MyST markdown on the client side
"""

__javascript_module_exports__ = ['* as mystparser', '* as myst2html']

__javascript_modules_raw__ = [
f"{config.npm_cdn}/[email protected]/+esm",
f"{config.npm_cdn}/[email protected]/+esm"
]

@classproperty
def __javascript_modules__(cls):
return bundled_files(cls, 'javascript_modules')

__javascript_raw__ = [
'https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/highlight.min.js'
]

@classproperty
def __javascript__(cls):
return bundled_files(cls)

__css_raw__ = [
'https://cdn.jsdelivr.net/gh/highlightjs/[email protected]/build/styles/github-dark.min.css'
]

@classproperty
def __css__(cls):
return bundled_files(cls, 'css')
60 changes: 60 additions & 0 deletions panel/models/myst.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import type * as p from "@bokehjs/core/properties"
import {HTMLView, HTML} from "./html"

export class MySTView extends HTMLView {
declare model: MyST

override set_html(html: string | null): void {
super.set_html(html)
for (const el of this.container.querySelectorAll("pre code")) {
(window as any).hljs.highlightElement(el)
}
}

override process_tex(): string {
const parsed = (window as any).mystparser.mystParse(this.model.text)
const text = (window as any).myst2html.mystToHtml(parsed)
if (this.model.disable_math || !this.contains_tex(text)) {
return text
}

const tex_parts = this.provider.MathJax.find_tex(text)
const processed_text: string[] = []

let last_index: number | undefined = 0
for (const part of tex_parts) {
processed_text.push(text.slice(last_index, part.start.n))
processed_text.push(this.provider.MathJax.tex2svg(part.math, {display: part.display}).outerHTML)

last_index = part.end.n
}

if (last_index! < text.length) {
processed_text.push(text.slice(last_index))
}

return processed_text.join("")
}
}

export namespace MyST {
export type Attrs = p.AttrsOf<Props>
export type Props = HTML.Props
}

export interface MyST extends MyST.Attrs {}

export class MyST extends HTML {
declare properties: MyST.Props

constructor(attrs?: Partial<MyST.Attrs>) {
super(attrs)
}

static override __module__ = "panel.models.myst"

static {
this.prototype.default_view = MySTView
this.define<MyST.Props>(({}) => ({}))
}
}
22 changes: 20 additions & 2 deletions panel/pane/markup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@

import param # type: ignore

from pyviz_comms import JupyterComm

from ..io.resources import CDN_DIST
from ..models.markup import HTML as _BkHTML, JSON as _BkJSON, HTMLStreamEvent
from ..util import HTML_SANITIZER, escape, prefix_length
from ..util import (
HTML_SANITIZER, escape, lazy_load, prefix_length,
)
from .base import ModelPane

if TYPE_CHECKING:
Expand Down Expand Up @@ -361,7 +365,7 @@ class Markdown(HTMLBasePane):
Additional markdown-it-py plugins to use.""")

renderer = param.Selector(default='markdown-it', objects=[
'markdown-it', 'myst', 'markdown'], doc="""
'markdown-it', 'myst', 'markdown', 'mystjs'], doc="""
Markdown renderer implementation.""")

renderer_options = param.Dict(default={}, nested_refs=True, doc="""
Expand Down Expand Up @@ -449,6 +453,8 @@ def hilite(token, langname, attrs):
return parser

def _transform_object(self, obj: Any) -> dict[str, Any]:
if self.renderer == 'mystjs':
return dict(object=obj)
import markdown
if obj is None:
obj = ''
Expand Down Expand Up @@ -482,6 +488,18 @@ def _process_param_change(self, params):
params['css_classes'] = ['markdown'] + params['css_classes']
return super()._process_param_change(params)

def _get_model(
self, doc: Document, root: Model | None = None,
parent: Model | None = None, comm: Comm | None = None
) -> Model:
if self.renderer == 'mystjs':
self._bokeh_model = lazy_load(
'panel.models.myst', 'MyST', isinstance(comm, JupyterComm), root
)
else:
self._bokeh_model = _BkHTML
model = super()._get_model(doc, root, parent, comm)
return model


class JSON(HTMLBasePane):
Expand Down