Abdul Saboor1
Nov 25, 2025
1My University is somewhere in the middle of nowhere
Right click (or click on footer) to open context menu for accessing settings, table of contents etc.
Oh we can use inline columns
Column A
Column B
section`Introduction`
```multicol .block-green
toc[True]`## Table of contents`
+++
### This is summary of current section
Oh we can use inline columns stack`Column A || Column B` here and what not!
%{btn}
```
(extensions=[], **settings)Interactive Slides in IPython Notebook. Only one instance can exist. settings
are passed to Slides.settings() if you like to set during initialization. You
can also edit file .ipyslides-assets/settings.json to make settings persistent across sessions
and load/sync them via GUI in sidepanel.
To suppress unwanted print from other libraries/functions, use:
with slides.suppress_stdout():
some_function_that_prints() # This will not be printed
print('This will not be printed either')
display('Something') # This will be printed
The traitlets callables under settings returns settings back to enable chaining
without extra typing, like Slides.settings.logo().layout()... .
Slides.instance() class method to keep older settings. Slides() apply default settings every time.slides.demo() to see a demo of some features.slides.docs() to see documentation.Slides.create is much faster than adding them one by one.Create New View for Output for optimized display.Windowing mode in Notebook settings to defer or none.Slides.xmd.syntax for extended markdown syntax, especially variables formatting.Slides.fmt to pick variables from local scope.Slides can be indexed same way as list for sorted final indices. Slides[number,] → Slide Slides[[n1,n2,..]] → SlideGroup or slice as Slides[start:stop:step] → SlideGroup.SlideGroup can be used to apply batch operations on many slides at once, e.g. Slides[[1,3,5]].vars.update(name='Alice') or Slides[2:5].set_css(...).Slides.s0, Slides.s1 etc. for existing slides, so Slides.s10 == Slides[10,] if slide with number 10 exists.(label, back_label=None, icon=None, back_icon=None)Create a link to jump to another slide. Use label for link text
and back_label for the optional text on the target slide if need to jump back.
link.origin to create a link to jump to target slide where link.target is placed.link.target will be able to jump back to the link.origin.%{link.origin} and %{link.target} to display links.<link:[unique id here]:origin label> and <link:[unique id here same as origin]:target [back_label,optional]>.
skipper = self.link('Skip to dynamic content', 'Back to link info', icon='arrow', back_icon='arrowl')
skipper.origin.display() # skipper.target is set later somewhere, can do backward jump too
Besides function below, you can add slides with %%slide number [-m] magic as well.
(slide_number, content=None, /, **vars)Build slides with a single unified command in three ways:
slides.build(number, callable) to create a slide from a callable(slide) immediately, e.g. lambda s: slides.write(1,2,3) or as a decorator.with slides.build(number): creates single slide. Equivalent to %%slide number magic.PAGE() from top import or Slides.PAGE() to split content into pages/sub slides.for item in PAGE.iter(iterable): block to automatically add page separator.PAGE() / PAGE.iter(...) to display content on each page incrementally in parts.write function can be split into parts if write is called after PART() adjacently.slides.build(number, str, **vars) creates many slides with markdown content. Equivalent to %%slide number -m magic in case of one slide.-- and slides separator is triple dashes ---. Same applies to Slides.sync_with_file too.++ to separted content into parts for incremental display on ites own line with optionally adding content after one space.multicol/columns can be displayed incrementally if ++ is used (alone on line) before these blocks as a trigger.slides.xmd.syntax for extended markdown usage.Slides.sync_with_file too.**vars (or left during build) and later updated in notebook using rebuild method on slide handle or overall slides.Slides.esc.number could be used as -1.integer in percent in markdown or Slides.this.yoffset(integer) to make all frames align vertically to avoid jumps in increments.build_(...) (with underscore at end) in python file instead of build(-1,...).**vars are ignored silently if build is used as contextmanager or decorator.(start_slide_number, /, path, interval=500)Auto update slides when content of markdown file changes. You can stop syncing using Slides.unsync function.
interval is in milliseconds, 500 ms default. Read Slides.build docs about content of file.
The variables inserted in file content are used from top scope.
You can add files inside linked file using include\`file_path.md\` syntax, which are also watched for changes.
This helps modularity of content, and even you can link a citation file in markdown format as shown below. Read more in Slides.xmd.syntax about it.
```citations
@key1: Saboor et. al., 2025
@key2: A citations can span multiple lines, but key should start on new line
<!-- Or put this content in a file 'bib.md' and then inside citations block use include`bib.md` -->
```
To debug the linked file or included file, use EOF on its own line to keep editing and clearing errors.
Slides[number,] to apply these methods becuase index can change on new builds.Slides[start:stop:step] to apply operations on many slides at once such as Slides[2:5].vars.update(...).(value)Set yoffset (in percent) for frames to have equal height in incremental content. Set global yoffset in layout settings.
Container for markdown slide variables, to see and update variables set on a slide or a group of slides.
slides.s1.vars.update(name="New") updates variable 'name' on slide 1 onlyslides.s2.vars.pop('age') removes variable 'age' from slide 2 only, so it is picked from notebook scopeslides.s3.vars.clear() clears all variables set on slide 3 only, so they are picked from notebook scopeslides[:].vars.update(theme='dark') updates variable 'theme' on all slidesslides[1:3].vars.pop('title') removes variable 'title' from slide 1 and 2 onlyslides[0].vars.scope see variables with scope set on slide 0If variables are not set on slide, they are picked from notebook scope if Auto Rebuild is enabled in side panel.
(this=None, main=None, page=None)Set animation of this slide. Provide None if need to stop animation. Use main and page to set animation to all slides and pages.
(src=None, opacity=1, filter=None, contain=False)Adds background image to this slide. src can be a url or a local image path or an svg str.
filter is a CSS filter like blur(5px), grayscale() etc.
opacity=1 and contain = True.(go_there=True)Update display of this slides including reloading citations, widgets etc.
(name=None, height='400px', **kwargs)Return source code of this slide, markdwon or python or None if no source exists. kwargs are passed to Slides.code.from_string.
()Show this slide in cell.
(this: dict = None, overall: dict = None, **theme_colors)Set CSS on this slide or overall or both cases.
Each call will reset previous call if props given explicitly, otherwise not.
Slides.css_syntax for information on how to write CSS dictionary.fg1, fg2, fg3, bg1, bg2, bg3, accent and pointer.
This does not affect overall theme colors, for that use Slides.settings.theme.colors.CSS is formatted using a props nested dictionary to simplify the process.
There are few special rules in props:
'.A': {'.B': ... } becomes .A .B {...} in CSS.'.A': {'^:hover': ...} becomes .A:hover {...} in CSS. You can also use '.A:hover' directly but it will restrict other nested keys to hover only.'.A': {'font-size': ('20px','2em')} becomes .A {font-size: 20px; font-size: 2em;} in CSS.Read about specificity of CSS selectors here.
props = {
".A": {
"z-index": "2",
".B": {
"font-size": [
"24px",
"2em"
],
"^:hover": {
"opacity": "1"
}
},
"> h1": {
"padding": "0",
"@media screen and (min-width: 650px)": {
"padding": "2em"
}
},
".C p": {
"font-size": "14px"
}
},
".D": {
"transform": "translate(-2px,1px)",
"^, h1": {
"background": "red",
"span, i": {
"color": "whitemoke",
"@keyframes animation-name": {
"from": {
"opacity": 0
},
"to": {
"opacity": 1
}
}
}
}
}
}
Output of html('style',props), set_css(props) etc. functions. Top selector would be different based on where it is called.
<style>
.SlideArea .A {
z-index : 2;
}
.SlideArea .A .B {
font-size : 24px;
font-size : 2em;
}
.SlideArea .A .B:hover {
opacity : 1;
}
.SlideArea .A > h1 {
padding : 0;
}
@media screen and (min-width: 650px) {
.SlideArea .A > h1 {
padding : 2em;
}
}
.SlideArea .A .C p {
font-size : 14px;
}
.SlideArea .D {
transform : translate(-2px,1px);
}
.SlideArea .D,
.SlideArea .D h1 {
background : red;
}
.SlideArea .D span,
.SlideArea .D i,
.SlideArea .D h1 span,
.SlideArea .D h1 i {
color : whitemoke;
}
@keyframes animation-name from {
opacity : 0;
}
to {
opacity : 1;
}
</style>
Extended syntax on top of Python-Markdown supports almost full presentation from Markdown.
Presentation Structure
--- is used to split text in slides inside markdown content of Slides.build function or markdown file.
Double dashes -- (PAGE in Python) is used to split text in pages. Double plus ++ (PART in Python) can be used to increment objects in parts on slide/page.
A ++ on its own line before columns/multicol block will make it reveal content incrementally, provided that columns are separated by +++.
The combinations of pages and parts create frames on slides. Note that only ++ allows content on same line after it and following lines.Slides.docs() for creating a TOC accompanied by section summary.Slides.sync_with_file.Slides.set_citations function (or see below).Slides.refs to add citations anywhere on slide. If `ncol_refs` is not given, it will be picked from layout settings.
Using refs`ncol_refs, key1, key2,...` will show only citations for given keys on that place. It is useful on slides with frames to show relevant citations on each frame.
Unused citations will be added automatically at end of slide.Slides.sync_with_file, you can add citations with block sytnax: ::: citations @key1: Saboor et. al., 2025 @key2: A citations can span multiple lines, but key should start on new lineContent Blocks
The general block syntax is ::: type-or-classes [args] attributes.
/ to divide css properties from node attributes such as ::: note-info border="1px solid red" / id="mynote" dir="ltr". Node attributes come after /.| in header (only takes effect if body is empty), such as ::: block-red | text will create a block with red background and text inside.| and / can be escaped in header by backslah to interpret them as literal characters instead of block body and attributes splitters respectively. : at start of each line. This multiline header is not available in ``` blocks.fg1=red bg2=black upto 3, can be assigned for each block to tweak look and feel of content.::: at start of line, such as ::: block-red will not be parsed as block.::: block nested inside ``` block at same indentation level but otherwise must be correctly indented.| Block Syntax | Description |
|---|---|
::: raw/pre |
Raw text or preformatted text, no markdown parsing. Use raw or pre as first word in block. |
::: code [focused lines] |
Code block with syntax highlighting, parameters are passed to highlight function. |
::: tag or classes |
tags are block level elements such as p, details, summary, table, center, etc. |
::: columns/multicol [widths] |
Create columns with relative widths, e.g. columns 4 6 for 40% and 60% width. Use +++ separator to reveal content incrementally/make display columns. |
::: md-[before,after,var_name] [focused lines] |
Parse markdown in the block, with showing source code at before or after or assign a variable name and use as <md-var_name/>. |
::: table [col widths] |
Create a table with optional column widths, e.g. ::: table 1 2 for 33% and 66% width. Use caption-side=top/bottom to place caption on top/bottom. |
::: citations |
Add citations in the block (only in sync_with_file context) instead of Slides.set_citations. Use @key: value syntax on its own line to add citations in block. |
::: display css_classes |
Create a block with specific CSS classes forcing display mode, it can break dom flow, but usefull to embed widget variables under blocks. |
md- and code blocksmd-var_name can be used anywhere in markdown using <md-var_name/> to display source code.md-[position or variable] accepts same parameters as code block for syntax highlighting and get deleted on first use.code and md-var blocks support attribute access such as ::: code.collapsed or ::: md-var.inline to show selected view.
You can also use ::: code 1 3 to focus on specific lines based on index 1 in markdown unlike Python.Layouts
| with | to use it as text inside stack. See at end how to nest such stacking.::: columns or ::: multicol syntax.
Column separator is triple plus +++ if intended in display mode and should be a ++ before block to make it incremental.
::: columns 6 1 4 block-blue
: border="1px dashed red"
::: block-red
- `::: columns/muticol` with a +++ separator act like `write` command and reveal content incrementally when `++` is used before block.
- children inside `columns` picks relative width from parent's `columns` block evem if '+++' is not used.
In thise children should be visually blocks themselves like headings, paragraphs, lists etc or wrapped in `::: block` to make them obvious blocks like this one.
- CSS classes and attributes can be used to style columns besides relative widths.
::: block-blue border="1px solid red" | alert`inline` color`block` text
::: block-yellow border="2px solid orange" padding="10px"
- Top level `columns` is necessary to create columns or use simple block with `display=flex`.
and frame speactor is used at end of block.
- Indentation is important, so use tabs or spaces consistently.
::: columns/muticol with a +++ separator act like write command and reveal content incrementally when ++ is used before block.columns picks relative width from parent's columns block evem if '+++' is not used.
In thise children should be visually blocks themselves like headings, paragraphs, lists etc or wrapped in ::: block to make them obvious blocks like this one.inline block text
columns is necessary to create columns or use simple block with display=flex.
and frame speactor is used at end of block.Code Display
print('Hello').::: code blocks for syntax highlighting.
::: columns
<md-src/>
+++
```python
print('Hello, I was highlighted from a code block!')
```
::: code 2 language=bash name=Shell lineno=False style=vim
echo "Hello, I was highlighted from a code block!"
ls -l | grep ".py" | wc -l
print('Hello, I was highlighted from a code block!')
echo "Hello, I was highlighted from a code block!"
ls -l | grep ".py" | wc -l
::: code block, you need to set parameters that are passed to code function, such as language, name, lineno, css_class, etc.::: code block and supports same parameters.::: code 2 4 5 to focus on lines 2, 4 and 5 visually. ::: code.collapsed or ::: code.inline to show collapsed or inline view of code block respectively.
::: details
::: summary | Click to see important notes on code blocks
- In ` ::: code ` block, you need to set parameters that are passed to `code` function, such as `language`, `name`, `lineno`, `css_class`, etc.
- The \`\`\` code block does act like `::: code ` block and supports same parameters.
- You can focus on specific lines in code blocks using line numbers (1-based) such as `::: code 2 4 5` to focus on lines 2, 4 and 5 visually.
- You can also use `::: code.collapsed` or `::: code.inline` to show collapsed or inline view of code block respectively.
<md-src/>
Variables Substitution
Variables from Python code can be embedded directly into Markdown.
str.format method.Slides.serializer to define their HTML representation, which allows them to be displayed correctly in place with such as %{fig}.
Using %{fig:nb} might show the object at the end of the slide.Slide[number,].vars deepest scope.build or Slide.vars.update), then from the notebook's global scope if a slide is built purely from markdown.
In functions which take markdown string such as write, html, variables are taken from notebook's global scope only. Use fmt to encapsulate variables from local scopes.Slide[number,].vars.update(**kwargs). This is also useful for setting unique variable values on different slides.%{var.attr} or %{var['key']}, the output will only update if the base variable var itself is reassigned.:nb are only displayed correctly in the first level of nested blocks.:nb format spec. str.format method, so f-string like literal expressions are not supported.Inline Python Functions
Functions (that can also take extra args [python code as strings] as func[arg1,x=2,y=A]`arg0`) include:
You can also use Slides.esc/isd.esc class to lazily escape variables/expressions/output of functions from being parsed inside f-strings.
This should be rarely used when your markdown contains a lot of $ \LaTeX $ equations to avoid excessively escaping them with curly braces in favor of few escaped variables.
Upto 4 level nesting is parsed in inline functions using (level + 1) number of / (at least two) within backticks in functions given below.
::: columns
<md-src_var/>
+++
stack[(6,4),css_class="block-blue"]`////
This always parse markdown in `returns=True` mode. ||
stack[css_class="info"]`/// B ||
color["skyblue"]`//alert`Alerted Text` Colored Text //`
///`
////`
This always parse markdown in returns=True mode.
B
Alerted Text Colored Text
General Syntax
Slides.link for more details.| cell text \{: rowspan="2" colspan="1"}| inside a cell, should be a space bewteen text and attributes._`sub` and ^`sup` for subscript and superscript respectively, e.g. H2O, E = mc2.Slides.css_styles for available CSS classes to use in markdown blocks and other places.::: columns <md-src/> +++ Item 1 Header : Item 1 details ^`1` Item 1 Header : Item 1 details _`2`
Extending Syntax
Slides.xmd.extensions to extend additional syntax using Markdown extensions such as
markdown extensions and
PyMdown-Extensions.['tables', 'footnotes', 'attr_list', 'md_in_html', 'def_list'].Slides.serializer function. Having a
__format__ method in your class enables to use {obj} syntax in python formatting and %{obj} in extended Markdown.,
Besides functions below, you can add content to slides with %%xmd,%xmd as well.
(*objs, widths=None, css_class=None)Write objs to slides in columns. To create rows in a column, wrap objects in a list or tuple.
You can optionally specify widths as a list of percentages for each column.
css_class can have multiple classes separated by space, works only for multiple columns.
Write any object that can be displayed in a cell with some additional features:
Slides.hold(func,...). Only body of the function will be displayed/printed. Return value will be ignored.ipywidgets or ipyvolume by passing them directly.matplotlib, plotly altair, bokeh etc. by passing them directly.Slides.code API.Slides.alt function to display obj/widget on slides and alternative content/screenshot of widgets in exported slides.ipywidgets.[HTML, Output, Box] and their subclasses will be displayed as Slides.alt(html_converter_func, widget). The value of exported HTML will be most recent.ipyslides.utils module that are also linked to Slides object._repr_html_ method, you can create one for your own objects/third party objects by:Slides.serializer API. IPython's display automatically takes care of such objects on export to html.IPython.core.formatters API for third party libraries.Slides.frozen to avoid display formatting and markdown parsing over objects in write and for some kind of objects in display too.write is a robust command that can handle most of the cases. If nothing works, repr(obj) will be displayed.repr(obj) by Slides.hold(func, ...) e.g. Slides.hold(plt.show). This can also be used to delay display until it is captured in a column.display(obj, metadata = {'text/html': 'html repr by user'}) for any object to display object as it is and export its HTML representation in metadata.Slides.stack, but content type is limited in that case.multicol/columns block syntax is similar to write command if +++ separartor is used there.To make a group of rows as single item visually for incremental display purpose, wrap them in a nested list/tuple.
A single column is flattened up to 2 levels, so [[obj1], row2, [item1, item2]] will be displayed as 3 rows.
Incremental display is triggered only when you place Slides.PART() delimiter before the write command:
slides.PART() # Trigger incremental display, equivalent to ++ before `multicol/columns` in markdown
slides.write([row1, [item1, item2], row3], column2) # Shows rows one by one (item1 and item2 together), then column2
slides.PART() # Another trigger for next write
slides.write([row1, row2]) # Shows both rows incrementally , no additional columns here
(content: Union[str, ipyslides.xmd.fmt], returns: bool = False) -> Optional[str]Extended markdown parser for ipyslides. You can use %%xmd and %xmd cell and line magics in Jupyter Notebook as well.
Besides the base Python-Markdown syntax, it supports additional syntax which you can read about by executing following code a notebook cell:
import ipyslides as isd
display(isd.xmd.syntax)
By default, the extensions tables, footattr_list, md_in_html, def_list are enabled.
You can add extra markdown extensions using Slides.xmd.extensions or ipyslides.xmd.extensions.
See markdown extensions for details.
Returns: A direct call or xmd.parse method returns a string with HTML content if returns=True (default), otherwise display rich output objects.
(obj)Convert supported (almost any) obj to html format.
(obj='')Convert supported (almost any) obj to html format and return widget.
(tag, children=None, css_class=None, **node_attrs)Returns html node with given children and node attributes like style, id etc. If an ttribute needs '-' in its name, replace it with '_'.
tag can be any valid html tag name. A tag that ends with / will be self closing e.g. hr/ will be <hr/>. Empty tag gives unwrapped children.
children expects:
html('image',alt='Image') → <img alt='Image'></img> and html('image/',alt='Image') → <img alt='Image' />slides[number,].set_css otherwise. See Slides.css_syntax to learn about requirements of styles in dict.Example:
html('img',src='ir_uv.jpg') #Returns IPython.display.HTML("<img src='ir_uv.jpg'></img>") and displas image if last line in notebook's cell.
To keep an image persistently embeded, use ipyslides.utils.imge function instead of just an html tag.
You can use alert
in markdown.This is experimental feature, and may not work as expected.
()(content)Add notes to current slide. Content could be any object except javascript and interactive widgets.
Note that notes are not shown inside slides during presentation. They can be viewed in popup window by
enabling Notes Popup option in settings panel. Notes can also be printed in PDF (after export too) by
enabling Inline Notes option in settings panel, useful for sharing slides with notes or for personal reference.
In markdown, the block md-[before,after,var_name] parses and displays source as well.
(obj, language='python', name=None, css_class=None, style='default', color=None, background=None, hover_color='var(--bg3-color)', lineno=True, height='400px')Create highlighted source code object from text, file or callable.
Use code(obj) or code.cast(obj) to get source code from any object that has a source or str of code.
Explicitly use:
Returns: SourceCode object with show and focus methods to show selective lines, as well as .inline and .collapsed properties.
(returns=False, **kwargs)Execute and displays source code in the context manager. kwargs are passed to Slides.code function.
Useful when source is written inside context manager itself.
If returns is False (by default), then source is displayed before the output of code. Otherwise you can assign the source to a variable and display it later anywhere.
Usage:
with source.context(returns = True) as s:
do_something()
write(s) # or s.display(), write(s)
#s.raw, s.value are accesible attributes.
#s.focus, s.show are methods that are used to focus/show selective lines.
(file, language=None, name=None, **kwargs)Returns source object with show and focus methods. name is alternate used name for language.
kwargs are passed to Slides.code.
It tries to auto detect lanaguage from filename extension, if language is not given.
(obj, **kwargs)Returns source code from a given obj [class,function,module,method etc.] with show and focus methods. kwargs are passed to Slides.code
(text, language='python', name=None, **kwargs)Creates source object from string. name is alternate used name for language. kwargs are passed to Slides.code.
Apply settings to slides programatically. Fewer settings are available as widgets.
Settings can be nested or individual attributes as set as well. For example:
Slides.settings(layout = {"aspect": 16/10}) # Top
Slides.settings.layout(aspect = 16/10) # Individual
Slides.settings.layout.aspect = 16/10 # Attribute
All settings calls including top level returns settings instance to apply method chaining.
e.g. Slides.settings.layout(aspect = 16/10).footer(text="ABC").logo(...).
Set code block styles. background and color may be needed for some styles.
(path)Dump the settings state to a json file. Use it once you have finalized a settings setup of slides.
Set fonts of text and code and size.
Set footer attributes of slides.
Set layout of slides.
(path)Load settings from a json file. You may need to dump settings and then edit for correct usage.
Set logo for all slides. left and bottom take precedence over right and top respectively.
Set theme value. colors and code have their own nested traits.
Toggle ON/OFF checks in settings panel.
(exportable_data, obj)Display obj for slides and output of exportable_data will be and displayed only in exported formats as HTML.
exportable_data should be an html str or a callable to receive obj as its only argument.obj.
import ipywidgets as ipw
slides.alt(lambda w: f'<input type="range" min="{w.min}" max="{w.max}" value="{w.value}">', ipw.IntSlider()).display()
alt many times for same type, you can use Slides.serializer.register and then pass that type of widget without alt.ipywidgets's HTML, Box and Output widgets and their subclasses directly give html representation if used inside write command.(*, continuous_update=<traitlets.traitlets.Bool object at 0x000001CEE0964520>, cyclic=<traitlets.traitlets.Bool object at 0x000001CEE0964550>, description=<traitlets.traitlets.Unicode object at 0x000001CEE0964430>, interval=<traitlets.traitlets.Float object at 0x000001CEE09644C0>, loop=<traitlets.traitlets.Bool object at 0x000001CEE0964460>, nframes=<traitlets.traitlets.CInt object at 0x000001CEE0964490>, playing=<traitlets.traitlets.Bool object at 0x000001CEE09644F0>, value=<traitlets.traitlets.CInt object at 0x000001CEE0964310>, **kwargs)This is a simple slider widget that can be used to control the animation with an observer function.
You need to provide parameters like nframes and interval (milliseconds) to control the animation.
The value trait can be observed to get the current frame index.
The cyclic trait can be set to True to make the animation cyclic and only works when loop mode is ON.
from plotly.graph_objects import FigureWidget
from dashlab.widgets import AnimationSlider
fig = FigureWidget()
fig.add_scatter(y=[1, 2, 3, 4, 5])
widget = AnimationSlider()
def on_change(change):
value = change['new']
fig.data[0].color = f'rgb({int(value/widget.nframes*100)}, 100, 100)' # change color based on frame index
widget.observe(on_change, names='value')
display(widget, fig) # display it in the notebook
This widget can be passed to ipywidgets.interactive as keyword argument to create a dynamic control for the animation.
from ipywidgets import interact
@interact(frame=widget)
def show_frame(frame):
print(frame)
(text)Alerts text!
(bokeh_fig, title='')Write bokeh figure as HTML string to use in ipyslide.utils.write.
Parameters
(iterable, ordered=False, marker=None, css_class=None)A powerful bullet list. iterable could be list of anything that you can pass to write command.
marker could be a unicode charcter or string, only effects unordered list.
(obj, language='python', name=None, css_class=None, style='default', color=None, background=None, hover_color='var(--bg3-color)', lineno=True, height='400px')Create highlighted source code object from text, file or callable.
Use code(obj) or code.cast(obj) to get source code from any object that has a source or str of code.
Explicitly use:
Returns: SourceCode object with show and focus methods to show selective lines, as well as .inline and .collapsed properties.
(text, fg='var(--accent-color, blue)', bg=None)Colors text, fg and bg should be valid CSS colors
(obj, summary='Click to show content')Show/Hide Content in collapsed html.
(obj, prepend_str=None, members=None, itself=True)Returns documentation of an obj. You can prepend a class/module name. members is True/List of attributes to show doc of.
(name, msg)Add error without breaking execution.
(obj, display=False)Lazy escape of variables in markdown using python formatted strings, to be resolved later and safe from markdown parsing.
Use as xmd(f"This is an escaped variable: {esc(var or expression)}
or xmd("This is an escaped variable: {}".format(esc(var or expression)).
This is in par with %{var} syntax, but more flexible as it can take any expression.
You are advised to use formatting strings rarely, instead use fmt class to pick variables
and avoid clashes with $ \LaTeX $ syntax.
(*args, **kwargs)Markdown string wrapper that will be parsed with given kwargs lazily. If markdown contains variables not in kwargs, it will try to resolve them from local/global namespace and raise error if name is nowhere. Use inside python scripts when creating slides. In notebook, variables are automatically resolved, although you can still use it there.
Being as last expression of notebook cell or using self.parse() will parse markdown content.
If you intend to use formatting strings, use esc class to lazily escape variables/expressions from being parsed.
(obj)Wraps a given obj in a parent with 'focus-child' class or add 'focus-self' to widget, whether a widget or html/IPYthon object, to focus/exit on double click.
(obj, metadata=None)Display object as it it and export metadata if not str. A frozen object may not appear in exported html if metadata is not given.
Returned object has a display method, or can be directly passed to display/write commands.
(tag, children=None, css_class=None, **node_attrs)Returns html node with given children and node attributes like style, id etc. If an ttribute needs '-' in its name, replace it with '_'.
tag can be any valid html tag name. A tag that ends with / will be self closing e.g. hr/ will be <hr/>. Empty tag gives unwrapped children.
children expects:
html('image',alt='Image') → <img alt='Image'></img> and html('image/',alt='Image') → <img alt='Image' />slides[number,].set_css otherwise. See Slides.css_syntax to learn about requirements of styles in dict.Example:
html('img',src='ir_uv.jpg') #Returns IPython.display.HTML("<img src='ir_uv.jpg'></img>") and displas image if last line in notebook's cell.
To keep an image persistently embeded, use ipyslides.utils.imge function instead of just an html tag.
(src, width='100%', height='auto', **kwargs)Display src in an iframe. kwrags are passed to IPython.display.IFrame
(data=None, width='95%', caption=None, crop=None, css_props={}, **kwargs)Displays PNG/JPEG files or image data etc, kwrags are passed to IPython.display.Image.
crop is a tuple of (left, top, right, bottom) in percentage of image size to crop the image.
css_props are applied to figure element, so you can control top layout and nested img tag.
You can provide following to data parameter:
Slides.clips_dir if not found.
Use 'clip:image.png' to pick image from Slides.clips_dir directly if another file 'image.png' also exists in current directory.Returns an IMG object which can be exported to other formats (if possible):
IMG.to_pil() returns PIL.Image or None.IMG.to_numpy() returns image data as numpy array for use in plotting libraries or None.(content, timeout=5)Send inside notifications for user to know whats happened on some button click. Send 'x' in content to clear previous notification immediately.
(plt_fig=None, transparent=True, width=None, caption=None, crop=None)Write matplotib figure as HTML string to use in ipyslide.utils.write.
Parameters
(text, css_class=None)Keep shape of text as it is (but apply dedent), preserving whitespaces as well.
(path)Context manager to set working directory to given path and return to previous working directory when done.
(callable, prepend_str=None)Returns signature of a callable. You can prepend a class/module name.
(objs, sizes=None, vertical=False, css_class=None, **css_props)Stacks given objects in a column or row with given sizes.
(obj, css_class=None, **css_props)Add a class to a given object, whether a widget or html/IPYthon object. CSS inline style properties should be given with names including '-' replaced with '_' but values should not. Only a subset of inline properties take effect if obj is a widget.
Objects other than widgets will be wrapped in a 'div' tag. Use html function if you need more flexibility.
(stdout=True)Suppress output of a block of code. If stdout is False, only display data is suppressed.
()Suppress stdout in a block of code, especially unwanted print from functions in other modules.
(data=None, width=None, caption=None, crop=None, css_props={}, **kwargs)Display svg file or svg string/bytes with additional customizations.
crop is a tuple of (left, top, right, bottom) in percentage of image size to crop the image.
css_props are applied to figure element, so you can control top layout and nested svg tag.
kwrags are passed to IPython.display.SVG. You can provide url/string/bytes/filepath for svg.
(data, headers=None, widths=None)Creates a table of given data like DataFrame, but with rich elements.
data should be a 2D matrix-like. headers is a list of column names. widths is a list of widths for each column.
Example:
import pandas as pd
df = pd.DataFrame({'A': [1,2,3], 'B': [4,5,6]})
slides.table(df.values, headers=df.columns, widths=[1,2])
slides.table([[1,2,3],[4,5,6]], headers=['A','B','C'], widths=[1,2,3])
(text, **css_props)Formats text in a box for writing e.g. inline refrences. css_props are applied to box and - should be _ like font-size → font_size.
text is not parsed to general markdown i.e. only bold italic etc. applied, so if need markdown, parse it to html before. You can have common CSS for all textboxes using class text-box.
(fmt='%b %d, %Y', fg='inherit')Returns today's date in given format.
(em=1)Returns html node with given height in em.
Use syntax cite`key` / @key to add citations which should be already set by Slides.set_citations(data) method.
Any key that ends with ! is displayed inplace. Number of columns in displayed citations are determined by
Slides.settings.layout(..., ncol_refs = int) or locally by Slides.refs(ncol). 1
Add sections in slides to separate content by section`text`. Corresponding table of contents can be added with toc`title`.
(data)Set citations from dictionary or string with content like @key: citation value on their own lines,
key should be cited in markdown as cite`key` / @key, optionally comma separated keys.
Number of columns in displayed citations are determined by Slides.settings.layout(..., ncol_refs=N) or markdown refs`N`/Slides.refs(N).
set_citations({"key1":"value1","key2":"value2"})
set_citations('''
@key1: citation for key1
@key2: citation for key2
''')
with open("citations_file.md","r") as f:
set_citations(f.read()) # same content as string above
with open("citations_file.json","r") as f:
set_citations(json.load(f))
Slides.sync_with_file's context.Citation A
(*funcs: list[callable], post_init: <built-in function callable> = None, **kwargs) -> NoneEnhanced interactive widget with multiple callbacks, grid layout and fullscreen support.
This function is used for quick dashboards. Subclass DashboardBase for complex applications.
Features:
Basic Usage:
from dashlab import interactive, callback, monitor
import ipywidgets as ipw
import plotly.graph_objects as go
fig = go.FigureWidget()
@callback('out-plot', timeit=True) # check execution time
def update_plot(x, y, fig):
fig.data = []
fig.add_scatter(x=[0, x], y=[0, y])
def resize_fig(fig, fs):
fig.layout.autosize = False # double trigger
fig.layout.autosize = True # plotly's figurewidget always make trouble with sizing
# Above two functions can be merged since we can use changed detection
@monitor # check execution time
def respond(x, y, fig , fs, changed):
if 'fs' in changed: # or changed('fs')
fig.layout.autosize = False # double trigger
fig.layout.autosize = True
else:
fig.data = []
fig.add_scatter(x=[0, x], y=[0, y])
dashboard = interactive(
update_plot,
resize_fig, # responds to fullscreen change
# respond, instead of two functions
x = ipw.IntSlider(0, 0, 100),
y = ipw.FloatSlider(0, 1),
fig = ipw.fixed(fig),
changed = '.changed', # detect a change in parameter
fs = '.isfullscreen', # detect fullscreen change on instance itself
)
Parameters:
*funcs: One or more callback functionsDashboardBase to enable IDE hints and auto-completion e.g. def post_init(self:DashboardBase): ...**kwargs: Widget parametersWidget Parameters:
x = (fig, 'selected') for plotly FigureWidget. Other traits of same widget can be observed by separate parameters with y = 'x.trait' pattern.P = '.params' to access all parameters in a callback, e.g. P.x.value = 10 will set x's value to 10 and trigger dependent callbacks.f(fig, v) where v='fig.selected'.param = var(obj, match) to use it as a parameter with custom equality check like match(a, b) -> bool for dataframes or other objects. Assigning param.value = new_value will update the widget and trigger callbacksdashlab.button/ipywidgets.Button for manual updates on heavy callbacks besides. Add tooltip for info on button when not synced.btn.clicked attribute to run code based on which button was clicked.Callbacks:
@callback. Run in the order of definition.@callback('out-myclass')@callback.Attributes and Traits:
changed = '.changed' in parameters and later in callback by checking changed('param') -> Bool.self.changed in a subclass and use changed('param') -> Bool / 'param' in self.changed. Useful to merge callback.P = '.params'
alongwith some x = True -> Checkbox, and then inside a callback P.x.value = False will uncheck the Checkbox and trigger depnendent callbacks.Notes:
Python dictionary to CSS
CSS is formatted using a props nested dictionary to simplify the process.
There are few special rules in props:
'.A': {'.B': ... } becomes .A .B {...} in CSS.'.A': {'^:hover': ...} becomes .A:hover {...} in CSS. You can also use '.A:hover' directly but it will restrict other nested keys to hover only.'.A': {'font-size': ('20px','2em')} becomes .A {font-size: 20px; font-size: 2em;} in CSS.Read about specificity of CSS selectors here.
Tips:
write('First column', C2) where C2 = Slides.hold(Slides.ei.interact, f, x = 5) or Slides.ei.interactive(f, x = 5).Slides.capture_content to display later in a specific place.
import time
@self.dl.interact(post_init = lambda self: self.set_css(dict({'.out-main': dict(height='2em')},background='var(--bg2-color)')), date = False, btn = self.dl.button()) # self is Slides here
def update_time(date, btn):
local_time = time.localtime()
objs = ['Time: {3}:{4}:{5}'.format(*local_time)] # Print time in HH:MM:SS format
if date:
objs.append('Date: {0}/{1}/{2}'.format(*local_time))
self.stack(objs).display()
import datetime
@self.on_load # self is Slides here
def push_toast(slide):
t = datetime.datetime.now()
time = t.strftime('%H:%M:%S')
self.notify(f'Notification at {time} form slide {slide.index} and frame {slide.indexf}', timeout=5)
return lambda s: self.notify('x') # clear notification immediately on exit by sending 'x'
(func)Decorator for running a func(slide) when slide is loaded into view.
Use this to e.g. notify during running presentation. func accepts single arguemnet, slide.
Return value could a cleanup function (which also accepts slide as single argument) executed when slide exits.
See Slides.docs() for few examples.
KeyError: Set value for cited key 'monitor' and build slide again!You can style or colorize your content and text.
Provide CSS for that using Slides.html("style",...) or use some of the available styles.
See these styles with Slides.css_styles property as shown on right.
Use any or combination of these styles in markdown blocks or css_class argument of writing functions:
| css_class | Formatting Style |
|---|---|
text-[value] |
[value] should be one of tiny, small, big, large, huge. |
align-[value] |
[value] should be one of center, left, right. |
rtl |
اردو، فارسی، عربی، ۔۔۔ |
info |
Blue text. Icon ℹ️ for note-info class. |
tip |
Blue text. Icon💡 for note-tip class. |
warning |
Orange text. Icon ⚠️ for note-warning class. |
success |
Green text. Icon ✅ for note-success class. |
error |
Red text. Icon⚡ for note-error class. |
note |
Text with note icon, can combine other classes as shown above. |
export-only |
Hidden on main slides, but will appear in exported slides. |
jupyter-only |
Hidden on exported slides, but will appear on main slides. |
block |
Block of text/objects |
block-[color] |
Block of text/objects with specific background color from red, green, blue, yellow, cyan, magenta and gray. |
raw-text |
Text will be shown as printed style. |
focus-self |
Double-click on element to zoom into popup view. Double-click again or press close button to exit. |
focus-child |
Focus on child objects of node with this class. Same double-click to zoom in/out behavior. |
no-, Slides.html('style',...) functions at your disposal. |
Show Code
stack[(3,7)]`//
## Content Styling
You can **style**{.error} or **color["teal"]`colorize`** your *content*{: style="color:hotpink;"} and *color["hotpink","yellow"]`text`*.
Provide **CSS**{.info} for that using code`Slides.html("style",...)` or use some of the available styles.
See these **styles**{.success} with `Slides.css_styles` property as shown on right.
|| %{self.css_styles}
//`
pygments is used for syntax highlighting 1.
You can highlight code using Slides.code 2 or within markdown using named code blocks:
import ipyslides as isd
import React, { Component } from "react";
Source code of slide can be embeded via variable too:
## Highlighting Code
[pygments](https://pygments.org/) is used for syntax highlighting cite`A`.
You can **highlight**{.error} code using `Slides.code` cite`B` or within markdown using named code blocks:
```python
import ipyslides as isd
```
```javascript
import React, { Component } from "react";
```
Source code of slide can be embeded via variable too: %{self.this.source}
You can parse and view a markdown file. The output you can save by exporting notebook in other formats.
(start_slide_number, /, path, interval=500)Auto update slides when content of markdown file changes. You can stop syncing using Slides.unsync function.
interval is in milliseconds, 500 ms default. Read Slides.build docs about content of file.
The variables inserted in file content are used from top scope.
You can add files inside linked file using include\`file_path.md\` syntax, which are also watched for changes.
This helps modularity of content, and even you can link a citation file in markdown format as shown below. Read more in Slides.xmd.syntax about it.
```citations
@key1: Saboor et. al., 2025
@key2: A citations can span multiple lines, but key should start on new line
<!-- Or put this content in a file 'bib.md' and then inside citations block use include`bib.md` -->
```
To debug the linked file or included file, use EOF on its own line to keep editing and clearing errors.
()Demo slides with a variety of content.
()Create presentation from docs of IPySlides.
(path='Slides.html', overwrite=False)Build html slides that you can print.
Save as PDF option instead of Print PDF in browser to make links work in output PDF. Alsp enable background graphics in print dialog.
self.write("## Adding content on frames incrementally yoffset`0`")
self.frozen(widget := (code := s.get_source()).as_widget()).display()
# frozen in above line get oldest metadata for export
def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
self.on_load(highlight_code)
for ws, cols in self.PART.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)])):
cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
self.write(*cols, widths=ws)
self.write("## Adding content on frames incrementally yoffset`0`")
self.frozen(widget := (code := s.get_source()).as_widget()).display()
# frozen in above line get oldest metadata for export
def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
self.on_load(highlight_code)
for ws, cols in self.PART.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)])):
cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
self.write(*cols, widths=ws)
self.write("## Adding content on frames incrementally yoffset`0`")
self.frozen(widget := (code := s.get_source()).as_widget()).display()
# frozen in above line get oldest metadata for export
def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
self.on_load(highlight_code)
for ws, cols in self.PART.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)])):
cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
self.write(*cols, widths=ws)
self.write("## Adding content on frames incrementally yoffset`0`")
self.frozen(widget := (code := s.get_source()).as_widget()).display()
# frozen in above line get oldest metadata for export
def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
self.on_load(highlight_code)
for ws, cols in self.PART.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)])):
cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
self.write(*cols, widths=ws)
self.write("## Adding content on frames incrementally yoffset`0`")
self.frozen(widget := (code := s.get_source()).as_widget()).display()
# frozen in above line get oldest metadata for export
def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
self.on_load(highlight_code)
for ws, cols in self.PART.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)])):
cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
self.write(*cols, widths=ws)
self.write("## Adding content on frames incrementally yoffset`0`")
self.frozen(widget := (code := s.get_source()).as_widget()).display()
# frozen in above line get oldest metadata for export
def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
self.on_load(highlight_code)
for ws, cols in self.PART.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)])):
cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
self.write(*cols, widths=ws)
self.write("## Adding content on frames incrementally yoffset`0`")
self.frozen(widget := (code := s.get_source()).as_widget()).display()
# frozen in above line get oldest metadata for export
def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
self.on_load(highlight_code)
for ws, cols in self.PART.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)])):
cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
self.write(*cols, widths=ws)
self.write("## Adding content on frames incrementally yoffset`0`")
self.frozen(widget := (code := s.get_source()).as_widget()).display()
# frozen in above line get oldest metadata for export
def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
self.on_load(highlight_code)
for ws, cols in self.PART.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)])):
cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
self.write(*cols, widths=ws)
self.write("## Adding content on frames incrementally yoffset`0`")
self.frozen(widget := (code := s.get_source()).as_widget()).display()
# frozen in above line get oldest metadata for export
def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
self.on_load(highlight_code)
for ws, cols in self.PART.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)])):
cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
self.write(*cols, widths=ws)
self.write('## Adding User defined Objects/Markdown Extensions')
self.write(
self.hold(display, self.html('h3','I will be on main slides',css_class='warning'),
metadata = {'text/html': '<h3 class="warning">I will be on exported slides</h3>'}
), # Can also do 'Slides.serilaizer.get_metadata(obj)' if registered
s.get_source(), widths = [1,3]
)
self.write(r'If you need to serialize your own or third party objects not serialized by this module, you can use `\@Slides.serializer.register` to serialize them to html.\n{.note .info}')
self.doc(self.serializer,'Slides.serializer', members = True, itself = False).display()
self.write('**You can also extend markdown syntax** using `markdown extensions`, ([See here](https://python-markdown.github.io/extensions/) and others to install, then use as below):')
self.doc(self.xmd.extensions,'Slides.xmd.extensions', members = True, itself = False).display()
If you need to serialize your own or third party objects not serialized by this module, you can use @Slides.serializer.register to serialize them to html.\n{.note .info}
(obj_type)Get serializer function for a type. Returns None if not found.
(obj_type)Get html str of a registerd obj_type.
(obj_type)Get metadata for a type to use in display(obj, metadata) for export purpose. This take precedence over object's own html representation. Returns {} if not found.
(obj_type, verbose=True)Decorator to register html serializer for an object type.
obj_type and should return HTML string.Usage
class MyObject:
def __repr__(self):
return 'My object is awesome'
slides = ipyslides.Slides()
@slides.serializer.register(MyObject)
def make_h1(obj):
return f'<h1>{obj!r}</h1>'
my_object = MyObject()
slides.write(my_object) #This will write "My object is awesome" as main heading
make_h1(my_object) #This will return "<h1>My object is awesome</h1>"
#This is equivalent to above for custom objects(builtin objects can't be modified)
class MyObject:
def _repr_html_(self):
return '<h1>My object is awesome</h1>'
my_object = MyObject()
slides.write(my_object)
_repr_html_ method which works as expected.Slides.alt(func, widget) inside write command for export purpose. Other commands such as Slides.[cols,rows,...] will pick oldest value only.display function automatically take care of serialized objects.(obj_type)Unregister all serializer handlers for a type.
()Unregister all serializer handlers.
You can also extend markdown syntax using markdown extensions, (See here and others to install, then use as below):
()Clear all extensions and their configurations added by user.
(configs_dict)Add configurations to the Markdown extensions. configs_dict is a dictionary like {'extension_name': config_dict}
(extensions_list)Add list of extensions to the Markdown parser.
focus-self, focus-child classes to an element. To prevent focus under as focus-child class, use no-focus class.Double click to focus on this block. Click at top right button or double click to exit.
Icons that apprear on buttons inslides (and their rotations) available to use in your slides as well besides standard ipywidgets icons.
import ipywidgets as ipw
btn = ipw.Button(description='Chevron-Down Icon',icon='chevrond')
self.write(btn)
Source code of this slide
with self.capture_content() as c:
with self.code.context():
import ipywidgets as ipw
btn = ipw.Button(description='Chevron-Down Icon',icon='chevrond')
self.write(btn)
group = zip(self.icon.available[::2], self.icon.available[1::2]) # make 4 columns table
self.write(['''
## SVG Icons
Icons that apprear on buttons inslides (and their rotations) available to use in your slides as well
besides standard ipywidgets icons.
''', *c.outputs, 'line`200`**Source code of this slide**',self.this.get_source()],
self.table([(f'`{j}`', self.icon(j,color='crimson').svg,f'`{k}`', self.icon(k,color='crimson').svg) for j, k in group],headers=['Name','Icon','Name','Icon']),
widths=[3,2])
Name
Icon
Name
Icon
arrow
arrowb
arrowbd
arrowbl
arrowbr
arrowbu
arrowd
arrowl
arrowr
arrowu
bars
camera
chevron
chevrond
chevronl
chevronr
chevronu
circle
close
code
columns
compress
dots
edit
expand
info
keyboard
laser
loading
panel
pause
pencil
play
refresh
rows
search
settings
stop
win-maximize
win-restore
zoom-in
zoom-out
Use -1 as placeholder to update slide number automatically.
-1.Slides.build_ instead of using -1.Some kernels may not support auto slide numbering inside notebook.
def docs(self):
"Create presentation from docs of IPySlides."
self.close_view() # Close any previous view to speed up loading 10x faster on average
self.clear() # Clear previous content
self.create(range(31)) # Create slides faster
from ..core import Slides
self.set_citations({'A': 'Citation A', 'B': 'Citation B'})
self.settings.footer(text=self.get_logo("1em") + "IPySlides Documentation", date=None)
with self.build(0): # Title page
self.this.set_bg_image(self.get_logo(),0.25, filter='blur(10px)', contain=True)
self.write(f'## IPySlides {self.version} Documentation\n### Creating slides with IPySlides')
self.center(self.fmt('''
alert`Abdul Saboor` ^`1`
today``
{.text-small}
%{logo}
::: text-box
^`1`My University is somewhere in the middle of nowhere
::: info
Right click (or click on footer) to open context menu for accessing settings, table of contents etc.
''', logo = self.get_logo("4em"))).display()
self.build(-1, '''
```md-after
section`Introduction`
```multicol .block-green
toc[True]`## Table of contents`
+++
### This is summary of current section
Oh we can use inline columns stack`Column A || Column B` here and what not!
%{btn}
```
```''', btn = self.draw_button)
with self.build(-1):
self.write('# Main App')
self.doc(Slides).display()
with self.build(-1):
self.write('# Jump between slides')
self.doc(self.link, 'Slides').display()
with self.code.context(returns=True) as c:
skipper = self.link('Skip to dynamic content', 'Back to link info', icon='arrow', back_icon='arrowl')
skipper.origin.display() # skipper.target is set later somewhere, can do backward jump too
c.display()
with self.build(-1):
self.write('## Adding Slides section`Adding Slides and Content`')
self.write('Besides function below, you can add slides with `%%slide number [-m]` magic as well.\n{.note .info}')
self.write([self.doc(self.build,'Slides'), self.doc(self.sync_with_file,'Slides')])
with self.build_():
self.write('''
## Important Methods on Slide
::: note-warning
- Use slide handle or `Slides[number,]` to apply these methods becuase index can change on new builds.
- Use `Slides[start:stop:step]` to apply operations on many slides at once such as code`Slides[2:5].vars.update(...)`.
''')
self.doc(self[0], members='yoffset vars set_animation set_bg_image update_display get_source show set_css'.split(), itself = False).display()
self.css_syntax.display()
self.build(-1, re.sub(r'^---\s*$', '---\n## Extended Markdown' ,_syntax.xmd_syntax, flags=re.MULTILINE))
with self.build(-1):
self.write('## Adding Content')
self.write('Besides functions below, you can add content to slides with `%%xmd`,`%xmd` as well.\n{.note .info}')
self.write(self.doc(self.write,'Slides'), [self.doc(self.xmd,'Slides'),self.doc(self.as_html,'Slides'),self.doc(self.as_html_widget,'Slides'),self.doc(self.html,'Slides')])
with self.build(-1):
self.write('## Adding Speaker Notes')
self.write([rf'styled["note success"]`You can use alert`notes\`notes content\`` in markdown.`',
'This is experimental feature, and may not work as expected.\n{.note-error .error}'])
self.doc(self.notes,'Slides.notes', members = True, itself = False).display()
with self.build(-1):
self.write('## Displaying Source Code')
self.write('In markdown, the block `md-[before,after,var_name]` parses and displays source as well.')
self.doc(self.code,'Slides', members = True, itself = True).display()
self.build(-1, r'section`//Layout and color["yellow","black"]`Theme` Settings//` toc`### Contents`')
with self.build(-1) as s:
s.set_css({
'.highlight': {'background':'#8984'}
}, bg1 = 'linear-gradient(45deg, var(--bg3-color), var(--bg2-color), var(--bg3-color))')
self.styled('## Layout and Theme Settings', 'info', border='1px solid red').display()
self.doc(self.settings,'Slides', members=True,itself = True).display()
with self.build(-1):
self.write('## Useful Functions for Rich Content section`//Useful Functions for alert`Rich Content`//`')
self.doc(self.alt,'Slides').display()
members = sorted((
'AnimationSlider alert bokeh2html bullets esc styled fmt code color details doc '
'today error focus html iframe image frozen notify plt2html '
'raw set_dir sig stack table textbox suppress_output suppress_stdout svg vspace'
).split())
self.doc(self, 'Slides', members = members, itself = False).display()
with self.build(-1):
self.write(r'''
## Citations and Sections
Use syntax alert`cite\`key\`` / alert`\@key` to add citations which should be already set by code`Slides.set_citations(data)` method.
Any key that ends with `!` is displayed inplace. Number of columns in displayed citations are determined by
code`Slides.settings.layout(..., ncol_refs = int)` or locally by code`Slides.refs(ncol)`. @A
Add sections in slides to separate content by alert`section\`text\``. Corresponding table of contents
can be added with alert`toc\`title\``.
''')
self.doc(self, 'Slides', members = ['set_citations'], itself = False).display()
with self.build(-1):
skipper.target.display() # Set target for skip button
self.write('## Dynamic Content')
with self.capture_content() as cap, self.code.context():
import time
@self.dl.interact(post_init = lambda self: self.set_css(dict({'.out-main': dict(height='2em')},background='var(--bg2-color)')), date = False, btn = self.dl.button()) # self is Slides here
def update_time(date, btn):
local_time = time.localtime()
objs = ['Time: {3}:{4}:{5}'.format(*local_time)] # Print time in HH:MM:SS format
if date:
objs.append('Date: {0}/{1}/{2}'.format(*local_time))
self.stack(objs).display()
with self.code.context(returns=True) as c:
import datetime
@self.on_load # self is Slides here
def push_toast(slide):
t = datetime.datetime.now()
time = t.strftime('%H:%M:%S')
self.notify(f'Notification at {time} form slide {slide.index} and frame {slide.indexf}', timeout=5)
return lambda s: self.notify('x') # clear notification immediately on exit by sending 'x'
self.write(
[self.doc(self.dl.interact,'ipyslides.dashlab')],
[*cap.outputs, c, self.doc(self.on_load,'Slides')],
)
self.build(-1, """
```md-src.collapsed
stack[(3,7)]`//
## Content Styling
You can **style**{.error} or **color["teal"]`colorize`** your *content*{: style="color:hotpink;"} and *color["hotpink","yellow"]`text`*.
Provide **CSS**{.info} for that using code`Slides.html("style",...)` or use some of the available styles.
See these **styles**{.success} with `Slides.css_styles` property as shown on right.
|| %{self.css_styles}
//`
```
<md-src/>
""", self=self)
self.build(-1, '''
## Highlighting Code
[pygments](https://pygments.org/) is used for syntax highlighting cite`A`.
You can **highlight**{.error} code using `Slides.code` cite`B` or within markdown using named code blocks:
```python
import ipyslides as isd
```
```javascript
import React, { Component } from "react";
```
Source code of slide can be embeded via variable too: %{self.this.source}
''', self=self)
with self.build(-1):
self.write('## Loading from File/Exporting to HTML section`Loading from File/Exporting to HTML`')
self.write('You can parse and view a markdown file. The output you can save by exporting notebook in other formats.\n{.note .info}')
self.write([self.doc(attr,'Slides') for attr in (self.sync_with_file,self.demo,self.docs,self.export_html)])
self.build(-1, 'section`Advanced Functionality` toc`### Contents`')
with self.build_() as s:
self.write("## Adding content on frames incrementally yoffset`0`")
self.frozen(widget := (code := s.get_source()).as_widget()).display()
# frozen in above line get oldest metadata for export
def highlight_code(slide): widget.value = code.focus(range(slide.indexf + 1)).value
self.on_load(highlight_code)
for ws, cols in self.PART.iter(zip([None, (2,3),None], [(0,1),(2,3),(4,5,6,7)])):
cols = [self.html('h1', f"{c}",style="background:var(--bg3-color);margin-block:0.05em !important;") for c in cols]
self.write(*cols, widths=ws)
with self.build(-1) as s:
self.write('## Adding User defined Objects/Markdown Extensions')
self.write(
self.hold(display, self.html('h3','I will be on main slides',css_class='warning'),
metadata = {'text/html': '<h3 class="warning">I will be on exported slides</h3>'}
), # Can also do 'Slides.serilaizer.get_metadata(obj)' if registered
s.get_source(), widths = [1,3]
)
self.write(r'If you need to serialize your own or third party objects not serialized by this module, you can use `\@Slides.serializer.register` to serialize them to html.\n{.note .info}')
self.doc(self.serializer,'Slides.serializer', members = True, itself = False).display()
self.write('**You can also extend markdown syntax** using `markdown extensions`, ([See here](https://python-markdown.github.io/extensions/) and others to install, then use as below):')
self.doc(self.xmd.extensions,'Slides.xmd.extensions', members = True, itself = False).display()
with self.build(-1):
self.write(r'''
## Focus on what matters
- Most of supported elements can be focused by default like images, matplotlib, bokeh, PIL image, altair plotly, dataframe, etc.
- You can also enable focus on an object/widget by wrapping it inside \`Slide.focus\` function conveniently.
- You can also enable focus by manully adding `focus-self`, `focus-child` classes to an element. To prevent focus under as `focus-child` class, use `no-focus` class.
::: focus-self block-red
### Focus on Me 😎
Double click to focus on this block. Click at top right button or double click to exit.
''')
with self.build(-1):
with self.capture_content() as c:
with self.code.context():
import ipywidgets as ipw
btn = ipw.Button(description='Chevron-Down Icon',icon='chevrond')
self.write(btn)
group = zip(self.icon.available[::2], self.icon.available[1::2]) # make 4 columns table
self.write(['''
## SVG Icons
Icons that apprear on buttons inslides (and their rotations) available to use in your slides as well
besides standard ipywidgets icons.
''', *c.outputs, 'line`200`**Source code of this slide**',self.this.get_source()],
self.table([(f'`{j}`', self.icon(j,color='crimson').svg,f'`{k}`', self.icon(k,color='crimson').svg) for j, k in group],headers=['Name','Icon','Name','Icon']),
widths=[3,2])
with self.build_():
self.write("""
# Auto Slide Numbering
Use alert`-1` as placeholder to update slide number automatically.
- In Jupyter notebook, this will be updated to current slide number.
- In python file, it stays same.
- You need to run cell twice if creating slides inside a for loop while using `-1`.
- Additionally, in python file, you can use ` Slides.build_ ` instead of using `-1`.
::: note-warning
Some kernels may not support auto slide numbering inside notebook.
""")
self.build(-1, lambda s: self.write(['## Presentation Code section`Presentation Code`',self.docs]))
self.navigate_to(0) # Go to title
return self