bridge = get_bridge(show_logger=True, wait=5)Bridge plugins
HTMX API
Method - htmx.swap()
Performs swapping (and settling) of HTML content
Parameters
target- the HTML element or string selector of swap targetcontent- string representation of content to be swappedswapSpec- swapping specification, representing parameters fromhx-swapswapStyle(required) - swapping style (innerHTML,outerHTML,beforebeginetc)swapDelay,settleDelay(number) - delays before swapping and settling respectivelytransition(bool) - whether to use HTML transitions for swapignoreTitle(bool) - disables page title updateshead(string) - specifiesheadtag handling strategy (mergeorappend). Leave empty to disable head handlingscroll,scrollTarget,show,showTarget,focusScroll- specifies scroll handling after swap
swapOptions- additional optional parameters for swappingselect- selector for the content to be swapped (equivalent ofhx-select)selectOOB- selector for the content to be swapped out-of-band (equivalent ofhx-select-oob)eventInfo- an object to be attached tohtmx:afterSwapandhtmx:afterSettleelementsanchor- an anchor element that triggered scroll, will be scrolled into view on settle. Provides simple alternative to full scroll handlingcontextElement- DOM element that serves as context to swapping operation. Currently used to find extensions enabled for specific elementafterSwapCallback,afterSettleCallback- callback functions called after swap and settle respectively. Take no arguments
Example
// swap #output element inner HTML with div element with "Swapped!" text
htmx.swap("#output", "<div>Swapped!</div>", {swapStyle: 'innerHTML'});HTMX Commander
Python wrapper of HTMX API.
Currently only implemented htmx.swap() manually. If useful, I’ll automate wrappers generation from htmx docs.
commander_esm = bundled(commander_js)(debugger=DEBUG(), ts=True)HTMXCommander
HTMXCommander (*args, **kwargs)
Main AnyWidget base class.
cleanupwidgets('cmdr')
cmdr = HTMXCommander.create(timeout=2)#DEBUG(2))Test swap
<div id="output-99">Original</div>cmdr.swap('#output-99', '<div>Swapped!</div>', swapStyle='innerHTML')cmdr.close()—-
First steps exploring automation. Skip it.
| # HTMXCommander plugin |
We can use HTMXCommander by itself. But probably, it’ll be more useful as a bridge plugin. |
HTMXCommanderPlugin
HTMXCommanderPlugin (ctx:str='', src:str|pathlib.Path='', bridge=None)
Inherit from this to have all attr accesses in self._xtra passed down to self.default
bridge.add_plugins((cmdr := HTMXCommanderPlugin()), wait=5)(d := Div(id='output-9999')('Original 2'))cmdr.swap(d, Div('Swapped 2'), swapStyle='innerHTML')def swap(self,*args, **kwargs):
bridge.commander.swap(self, *args, **kwargs)
FC.patch_to(FT)(swap)div = Div(id='output-99999')('Original 3')
divdiv.swap('<div>Swapped 3</div>', swapStyle='innerHTML')NBHooksPlugin
Python-only bridge plugin to help us inspect, control, and modify cell outputs.
Note: in VSCode output_capture is unreliable, unfortunately, and don’t play well with the debugger. Jeremy rules in almost everything programming-wise, but in this I’m more aligned with Carson: Grug Brained Developers need powerful (graphical, I double Grug) debuggers. How very much I would rather not use VSCode notebooks.
You can switch on/off the capturer. We’ll hopefully be able to develop alternatives down the road.
NBHooksPlugin
NBHooksPlugin (*args, **kwargs)
Inherit from this to have all attr accesses in self._xtra passed down to self.default
bridge_cfg.update(auto_id=True, auto_show=True){'auto_show': True, 'auto_mount': False, 'auto_id': True, 'bundle_cfg': {'out_dir': [Path('/Users/vic/dev/repo/project/bridget/bridget/js'), Path('/Users/vic/dev/repo/project/bridget/bridget')], 'rewrite_imports': True, 'import_name': 'brdimport'}, 'bootstrap': False, 'current_did': None}
bridge.add_plugins(NBHooksPlugin())cprint(bridge.nbhooks.brdd.dhs)deque(maxlen=100)
HTML(f"2, 3, 5, 7")test_eq(__nb__[__lastcellinfo__.cell_id].outputs[0].metadata['brd_did'], bridge.nbhooks.dh.display_id)
__nb__[__lastcellinfo__.cell_id]NBCell@1
- idx: 1
- source: HTML(f"2, 3, 5, 7")
- id: Y102sZmlsZQ==
- cell_type: code
- output_type: display_data
- text/plain: <bridget.helpers.HTML object>
- text/html: 2, 3, 5, 7 <brd-mark id="bb29686bf-936c32eb-f67649d1-ed04a9ab"></brd-mark>
- metadata: {'bridge': {'captured': True}, 'brd_did': 'bb29686bf-936c32eb-f67649d1-ed04a9ab'}
- output_type: execute_result
- execution_count: 36
- text/plain: <bridget.helpers.HTML object>
- text/html: 2, 3, 5, 7
- metadata: {}
- execution_count: 36
outputs
0
data
1
data
bridge.nbhooks.brdd.dhs[-2].update(HTML(f"11, 13, 17, 19, 23, 29"))
# cprint(__cellinfo__)ci = __cellinfo__
displaydh(HTML(f"It’s a fact everybody already knows,<br>Single rich man, man he gotta propose."))
HTML(' ')Single rich man, man he gotta propose.
Every mama scheming, whisperin’ prayers.
bridge.nbhooks.dh.update(HTML(f"New in town, what’s he thinking? Nobody cares,<br>Every mama scheming, whisperin’ prayers."))
cprint(__cellinfo__){ 'source': 'bridge.nbhooks.dh.update(HTML(f"New in town, what’s he thinking? Nobody cares,<br>Every mama scheming, whisperin’ prayers."))\ncprint(__cellinfo__)', 'cell_id': 'Y106sZmlsZQ==', 'exec_result': {'result': None} }
speech_Batty = """I've seen things you people wouldn't believe.
Attack ships on fire off the shoulder of Orion.
I watched C-beams glitter in the dark near the Tannhäuser Gate.
All those moments will be lost in time, like tears in rain.
Time to die.""".split('\n')
HTML('<br>'.join(speech_Batty[:-2]) + "<div class='what-follows' style='color: red;'>...</div>")Attack ships on fire off the shoulder of Orion.
I watched C-beams glitter in the dark near the Tannhäuser Gate.
All those moments will be lost in time, like tears in rain.
Time to die.
bridge.commander.swap(
f"div[data-brt-id={bridge.nbhooks.dh.display_id}]>.what-follows",
Div(style={'color':'darkgreen'})(speech_Batty[-2], Br(), speech_Batty[-1]),
swapStyle='outerHTML')bridge.nbhooks.dh.update(HTML('<br>'.join(speech_Batty)))<zero-md>
Ridiculously simple zero-config markdown displayer
md_samp = '''
# <zero-md>
> Ridiculously simple zero-config markdown displayer
A vanilla markdown-to-html web component based on
[Custom Elements V1 specs](https://www.w3.org/TR/custom-elements/) to load and display an external
MD file.
Featuring:
- [x] Math rendering via [`KaTeX`](https://github.com/KaTeX/KaTeX)
- [x] [`Mermaid`](https://github.com/mermaid-js/mermaid) diagrams
- [x] Syntax highlighting via [`highlight.js`](https://github.com/highlightjs/highlight.js)
```python
a = {'a': 'asdf', 'b': 10}
print("local server is listening on port 8080")
```
'''
Markdown(md_samp)<zero-md>
Ridiculously simple zero-config markdown displayer
A vanilla markdown-to-html web component based on Custom Elements V1 specs to load and display an external MD file.
Featuring:
a = {'a': 'asdf', 'b': 10}
print("local server is listening on port 8080")bridge.logger.show()bridge.loader.load_links({'zeromd':zeromd_scr})from fasthtml.components import Zero_md, Template
from bridget.bridge_widget import StyleVdef render_local_md(md, css=''):
css_template = Template(StyleV(css), data_append=True)
return Zero_md(css_template, Script(md, type="text/markdown"))md_ft = render_local_md(md_samp)
with bridge_cfg(auto_show=False): display(md_ft)<zero-md><template data-append> <style></style>
</template><script type="text/markdown">
# <zero-md>
> Ridiculously simple zero-config markdown displayer
A vanilla markdown-to-html web component based on
[Custom Elements V1 specs](https://www.w3.org/TR/custom-elements/) to load and display an external
MD file.
Featuring:
- [x] Math rendering via [`KaTeX`](https://github.com/KaTeX/KaTeX)
- [x] [`Mermaid`](https://github.com/mermaid-js/mermaid) diagrams
- [x] Syntax highlighting via [`highlight.js`](https://github.com/highlightjs/highlight.js)
```python
a = {'a': 'asdf', 'b': 10}
print("local server is listening on port 8080"):::
:::
::: {#0ac19a8b .cell}
``` {.python .cell-code}
md_ft
bridge.nbhooks.dh.update(render_local_md('## Hi again!'))Recap of NBHooks features:
As a bridge plugin, NBHooks provides:
- Wrapper of CellExecInfo to provide current and last cell info, including cell id.
- Add metadata to all displayed rich media
- Add metadata to cell output.
cleanupwidgets('bridge')
bridge = get_bridge(show_logger=True)
bridge.add_plugins(NBHooksPlugin())1. Capture cell info
with cell id if possible: Jupyter Notebook/Lab, VSCode-ish; nbclassic doesn’t gen cell ids.
Will be handy when we have access to notebook state.
cprint(ci := __cellinfo__)
test_eq(__cellinfo__['source'][:26], 'cprint(ci := __cellinfo__)')
# test_eq(brd.csi.dh['cell_id'], cid){ 'source': "cprint(ci := __cellinfo__)\ntest_eq(__cellinfo__['source'][:26], 'cprint(ci := __cellinfo__)')\n# test_eq(brd.csi.dh['cell_id'], cid)", 'cell_id': 'Y132sZmlsZQ==', 'exec_result': {'result': None} }
2. Every rich cell output, those made with display(…), or last cell expression, is captured and converted to transient
i.e., equivalent to display(…,display_id=True).
NBHooks stores the DisplayHandle, and cellinfo got the display_id in __cellinfo__.did
display(Markdown("""`The World in His Arms`"""))
bridge.nbhooks.dh.update(A(href='https://en.wikipedia.org/wiki/The_World_in_His_Arms')('The World in His Arms'))bridge.nbhooks.dh.update(Image(url='https://upload.wikimedia.org/wikipedia/commons/4/4b/WorldInHisArms-poster.jpg', height=150))Capture automatic cell output also
Div('asdf')# bridge.nbhooks.dh.update(HTML('<div>qwer</div>'))
bridge.nbhooks.dh.update(HTML(Div('qwer')))3. All HTML captured outputs have Bridge metadata (see Brd_Mark)
We use a custom element to mark the parent element in the front-end. HTML display objects allow us to add this custom element (brd_mark) easily. We’d also like to tag other rich outputs but we can’t do it with only IPython/Kernel mechanisms.
did = '23579111317'
HTML(Div(f"My parent element has a `data-brd-id` attribute with value '{did}'. Inspect me!"),
metadata={'brd_did': did})test_eq(__nb__[__lastcellinfo__.cell_id].outputs[0]['data']['text/html'].split('\n')[-1], f'<brd-mark id="{did}"></brd-mark>')4. HTMX API (WIP)
Besides DisplayHandler.update(…) you can modify the HTML outputs directly with HTMX API python wrapper (swap only for now).