fastdeck

Fastdeck

PyPI Documentation

Fastdeck is a Python library for creating and managing slide decks.

Fastdeck Python library is maintained to support the app ⚡️Fastdeck AI.

Create and share minimal slides in seconds, on the go.

Installation

You can install fastdeck using pip:

pip install fastdeck==0.1.0

Usage

Here's a basic overview of how to use Fastdeck:

  1. Import the necessary classes:
from fastdeck import Presentation, Slide, Content
  1. Create a presentation:
presentation = Presentation()
  1. Create slides and add content:
slide = Slide()
content = Content()

content.add_heading("Welcome to FastDeck")
content.add_text("This is a simple demonstration of FastDeck capabilities.")

slide.add_content([content.render()])
  1. Add the slide to the presentation:
presentation.add_slide(slide)
  1. Generate and save the HTML:
presentation.save_html("my_presentation.html")

Example

from fastdeck import Presentation, Slide, Content
import plotly.express as px
import os

# Create output directory
output_dir = 'fastdeck_demo_output'
os.makedirs(output_dir, exist_ok=True)

# Create a new presentation
presentation = Presentation()

# Define a common style for centering
center_style = {'style': 'display: flex; flex-direction: column; justify-content: center; align-items: center; height: 100%; text-align: center;'}

# Create the title slide
title_slide = Slide(center=True)
title_content = Content()
title_content.add_heading("Fastdeck", tag="h1")
title_content.add_text("Create and manage slide decks in pure Python.")
title_slide.add_content([title_content.render()], styles=[center_style])
presentation.add_slide(title_slide)
# Save indiviual slides
# title_slide.save_slide_html(os.path.join(output_dir, 'title_slide.html'))

# Create a content slide
content_slide = Slide()
content = Content()
content.add_heading("Features of Fastdeck")
content.add_list([
    "Easy to use Python API",
    "Support for various content types",
    "Customizable styles",
    "Export to HTML"
])
content_slide.add_content([content.render()], styles=[center_style])
presentation.add_slide(content_slide)


# Create a slide advertising Fastdeck AI App
ai_app_slide = Slide()
ai_app_content = Content()
ai_app_content.add_heading("Try Fastdeck AI App", tag="h2")
ai_app_content.add_text("Create and share minimal slides in seconds, on the go")
ai_app_content.add_text("Powered by AI")
ai_app_content.add_text('<a href="https://fastdeckai.com" target="_blank">Try ⚡️ Fastdeck AI</a>')
ai_app_slide.add_content([ai_app_content.render()], styles=[center_style])
presentation.add_slide(ai_app_slide)


# Create a slide about what more you can do with Fastdeck
more_features_slide = Slide()
more_features_content = Content()
more_features_content.add_heading("What more you can do with Fastdeck", tag="h2")
more_features_content.add_list([
    "Create interactive charts and graphs",
    "Embed videos and images",
    "Customize themes and layouts",
    "Generate presentations programmatically",
    "Integrate with data analysis workflows",
    "and more ..."
])
more_features_slide.add_content([more_features_content.render()], styles=[center_style])
presentation.add_slide(more_features_slide)


# Create a slide with a Plotly graph
plotly_slide = Slide()
plotly_content = Content()
plotly_content.add_heading("Plotly Graph")
df = px.data.iris()
fig = px.scatter(df, x='sepal_width', y='sepal_length', color='species', size='petal_length', hover_data=['petal_width'])

# Make the plot transparent
fig.update_layout(
    paper_bgcolor='rgba(0,0,0,0)',  # Transparent background
    plot_bgcolor='rgba(0,0,0,0)',   # Transparent plot area
    autosize=True
)

json_fig = fig.to_json()
plotly_slide.add_content([json_fig], columns=[12], styles=[{'class': 'stretch'}])
presentation.add_slide(plotly_slide)
plotly_slide.save_slide_html('plotly_slide.html')  # Save individual slide


# Create a slide with an embedded video
video_slide = Slide()
video_content = Content()
video_content.add_heading("Embedded Video Support", tag="h2")
video_embed = '<iframe width="560" height="315" src="https://www.youtube.com/embed/d2JPEDpMiw8" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen style="max-width: 80%; max-height: 60vh;"></iframe>'
video_content.add_div(video_embed)
video_slide.add_content([video_content.render()], styles=[center_style])
presentation.add_slide(video_slide)


# Create a slide with a cat image
image_slide = Slide()
image_content = Content()
image_content.add_heading("Image Integration", tag="h2")
image_url = "https://images.unsplash.com/photo-1608848461950-0fe51dfc41cb?fm=jpg&q=60&w=3000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxleHBsb3JlLWZlZWR8MXx8fGVufDB8fHx8fA%3D%3D"
image_content.add_image(image_url, alt="Cute cat", **{'style': 'max-width: 80%; max-height: 60vh; object-fit: contain;'})
image_slide.add_content([image_content.render()], styles=[center_style])
presentation.add_slide(image_slide)


# Save the entire presentation
presentation.save_html(
    os.path.join(output_dir, "fastdeck_demo.html"),
    theme="night",  # 'black', 'white', 'league', 'beige', 'sky', 'night', 'serif', 'simple', 'solarized', 'blood', 'moon'
    width=1920,     # 16:9 width 
    height=1080,    # 16:9 height 
    margin=0.07,    # 7% margin
    minscale=0.3,   # Can shrink to 30% of original size
    maxscale=2.0    # Can grow to 200% of original size
)

print(f"Presentation and individual slides have been saved in the directory: {output_dir}")

# Returns the presentation as an HTML string
html_string = presentation.to_html(
    theme="blood",
    width=1920,
    height=1080,
    margin=0.07,
    minscale=0.3,
    maxscale=2.0
)

print("HTML string generated. You can paste it directly into any HTML viewer to render.")

After running this script, you'll have an HTML file named fastdeck_demo.html that you can open in a web browser to view your presentation.

Documentation

For more detailed information about Fastdeck's classes and methods, please refer to the documentation.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License.

Acknowledgements

Classes: Content: Utilities for creating and managing content in HTML presentations Slide: Tools for creating and managing individual slides Presentation: Tools for creating and managing full presentations

 1"""
 2{readme_content}
 3
 4Classes:
 5    Content: Utilities for creating and managing content in HTML presentations
 6    Slide: Tools for creating and managing individual slides
 7    Presentation: Tools for creating and managing full presentations
 8"""
 9
10import os
11
12from .content import Content
13from .slide import Slide
14from .presentation import Presentation
15
16__all__ = ["Content", "Slide", "Presentation"]
17
18# Read the README content
19readme_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'README.md')
20try:
21    with open(readme_path, 'r', encoding='utf-8') as readme_file:
22        readme_content = readme_file.read()
23    # Replace the placeholder in the module docstring with the README content
24    __doc__ = __doc__.format(readme_content=readme_content)
25except FileNotFoundError:
26    print("README.md not found. The documentation will not include the README content.")
27
28# Control what's shown in the documentation
29__pdoc__ = {}
30
31# Hide the __init__ methods
32__pdoc__["Content.__init__"] = False
33__pdoc__["Slide.__init__"] = False
34__pdoc__["Presentation.__init__"] = False
35
36# Ensure all public methods of each class are shown
37for cls in [Content, Slide, Presentation]:
38    for attr in dir(cls):
39        if not attr.startswith("_"):
40            __pdoc__[f"{cls.__name__}.{attr}"] = True
41
42# Hide any utility functions or implementation details
43__pdoc__["_parse_style_class"] = False
44__pdoc__["_check_content_type"] = False
45__pdoc__["_add_list_classes"] = False
46__pdoc__["_append_class"] = False
47__pdoc__["_append_style"] = False
48__pdoc__["_check_styles"] = False
49__pdoc__["create_slide_html"] = False
50
51# Hide module-level attributes
52__pdoc__["content"] = False
53__pdoc__["slide"] = False
54__pdoc__["presentation"] = False
class Content:
 60class Content:
 61    """
 62    A class to build and render HTML content.
 63
 64    Methods:
 65        clear(): Clears the current content.
 66        add_script(name: str, script: str): Adds a script with a given name.
 67        add_heading(text: str, tag: str = "h3", icon: str = None, **kwargs): Adds a heading with an optional icon.
 68        add_text(text: str, tag: str = "p", **kwargs): Adds a paragraph or span of text.
 69        add_list(items: list, ordered=False, **kwargs): Adds an ordered or unordered list.
 70        add_image(src: str, alt: str = "", **kwargs): Adds an image from a URL or local source.
 71        add_svg(svg: str, **kwargs): Adds an SVG element.
 72        add_plotly(json: str, **kwargs): Adds a Plotly chart.
 73        add_altair(json: str, **kwargs): Adds an Altair chart.
 74        add_div(div: str, **kwargs): Adds a div element.
 75        add_fig(src: Figure, alt: str = "", as_svg=True, **kwargs): Adds a Matplotlib figure.
 76        render(): Renders the content as a pretty-formatted HTML string.
 77    """
 78    def __init__(self):
 79        self.content = ""
 80        self.scripts = {}
 81        self.grid_cols = 0
 82
 83    def clear(self):
 84        """Clears the current content."""
 85        self.content = ""
 86
 87    def add_script(self, name: str, script: str):
 88        """
 89        Adds a script with a given name.
 90        
 91        Args:
 92            name (str): The name of the script.
 93            script (str): The script content.
 94        """
 95        self.scripts[name] = script
 96
 97    def add_heading(self, text: str, tag: str = "h3", icon: str = None, **kwargs):
 98        """
 99        Adds a heading with an optional icon.
100        
101        Args:
102            text (str): The heading text.
103            tag (str, optional): The HTML tag for the heading (default is "h3").
104            icon (str, optional): The icon class for the heading.
105            **kwargs: Additional style and class attributes.
106        
107        Raises:
108            ValueError: If the tag is not a valid heading tag.
109        """
110        if tag not in ["h1", "h2", "h3", "h4", "h5"]:
111            raise ValueError("Invalid tag, the tag must be one of h1, h2, h3, h4 or h5")
112
113        s = _parse_style_class(kwargs)
114        self.content += (
115            f"<{tag} {s}><i class='{icon}'></i> {text}</{tag}>"
116            if icon
117            else f"<{tag} {s}>{text}</{tag}>"
118        )
119
120    def add_text(self, text: str, tag: str = "p", **kwargs):
121        """
122        Adds a paragraph or span of text.
123        
124        Args:
125            text (str): The text content.
126            tag (str, optional): The HTML tag for the text (default is "p").
127            **kwargs: Additional style and class attributes.
128        
129        Raises:
130            ValueError: If the tag is not a valid text tag.
131        """
132        if tag not in ["p", "span"]:
133            raise ValueError("Invalid tag, the tag must be one of p or span")
134
135        s = _parse_style_class(kwargs)
136        self.content += f"""<{tag} {s}>{text}</{tag}>"""
137
138    def add_list(self, items: list, ordered=False, **kwargs):
139        """
140        Adds an ordered or unordered list.
141        
142        Args:
143            items (list): A list of items to be added to the list.
144            ordered (bool, optional): Whether the list should be ordered (default is False).
145            **kwargs: Additional style and class attributes.
146        """
147        list_tag = "ol" if ordered else "ul"
148        s = _parse_style_class(kwargs)
149        list_items = "\n".join([f"<li>{item}</li>" for item in items])
150        self.content += f"<{list_tag} {s}>\n{list_items}\n</{list_tag}>"
151
152    def add_image(self, src: str, alt: str = "", **kwargs):
153        """
154        Adds an image from a URL or local source.
155        
156        Args:
157            src (str): The source URL or local path of the image.
158            alt (str, optional): The alt text for the image (default is "").
159            **kwargs: Additional style and class attributes.
160        
161        Raises:
162            Exception: If the image cannot be fetched from the URL.
163        """
164        if 'class' not in kwargs:
165            kwargs['class'] = []
166        elif isinstance(kwargs['class'], str):
167            kwargs['class'] = [kwargs['class']]
168        kwargs['class'].append('img-fluid')
169
170        if src.startswith(('http://', 'https://')):
171            response = requests.get(src)
172            if response.status_code == 200:
173                image_data = response.content
174            else:
175                raise Exception(f"Failed to fetch image from URL: {src}")
176        else:
177            with open(src, "rb") as f:
178                image_data = f.read()
179
180        image_base64 = base64.b64encode(image_data).decode("utf-8")
181        image_src = f"data:image/png;base64,{image_base64}"
182
183        s = _parse_style_class(kwargs)
184        self.content += f"""<img src="{image_src}" alt="{alt}" {s}>"""
185
186    def add_svg(self, svg: str, **kwargs):
187        """
188        Adds an SVG element.
189        
190        Args:
191            svg (str): The SVG content.
192            **kwargs: Additional style and class attributes.
193        """
194        if 'class' not in kwargs:
195            kwargs['class'] = []
196        elif isinstance(kwargs['class'], str):
197            kwargs['class'] = [kwargs['class']]
198        kwargs['class'].append('img-fluid')
199
200        s = _parse_style_class(kwargs)
201        self.content += f"""<div {s}>{svg}</div>"""
202
203    def add_plotly(self, json: str, **kwargs):
204        """
205        Adds a Plotly chart.
206        
207        Args:
208            json (str): The Plotly chart data in JSON format.
209            **kwargs: Additional style and class attributes.
210        """
211        if 'class' not in kwargs:
212            kwargs['class'] = []
213        elif isinstance(kwargs['class'], str):
214            kwargs['class'] = [kwargs['class']]
215        kwargs['class'].append('img-fluid')
216
217        s = _parse_style_class(kwargs)
218
219        j = json.replace("'", "\u2019")
220        chart_id = "chart-" + str(uuid.uuid4())
221        self.content += f"""<div {s} id='{chart_id}'></div>
222            <script>var Plotjson = '{j}';
223            var figure = JSON.parse(Plotjson);
224            Plotly.newPlot('{chart_id}', figure.data, figure.layout);</script>"""
225
226    def add_altair(self, json: str, **kwargs):
227        """
228        Adds an Altair chart.
229        
230        Args:
231            json (str): The Altair chart data in JSON format.
232            **kwargs: Additional style and class attributes.
233        """
234        if 'class' not in kwargs:
235            kwargs['class'] = []
236        elif isinstance(kwargs['class'], str):
237            kwargs['class'] = [kwargs['class']]
238        kwargs['class'].append('img-fluid')
239
240        s = _parse_style_class(kwargs)
241
242        chart_id = "chart-" + str(uuid.uuid4())
243        self.content += f"""<div {s} id='{chart_id}'></div>
244        <script>var opt = {{renderer: "svg"}};
245        vegaEmbed("#{chart_id}", {json} , opt);</script>"""
246
247    def add_div(self, div: str, **kwargs):
248        """
249        Adds a div element.
250        
251        Args:
252            div (str): The div content.
253            **kwargs: Additional style and class attributes.
254        """
255        s = _parse_style_class(kwargs)
256        self.content += f"""<div {s}>{div}</div>"""
257
258    def add_fig(self, src: Figure, alt: str = "", as_svg=True, **kwargs):
259        """
260        Adds a Matplotlib figure.
261        
262        Args:
263            src (Figure): The Matplotlib figure object.
264            alt (str, optional): The alt text for the image (default is "").
265            as_svg (bool, optional): Whether to render the figure as SVG (default is True).
266            **kwargs: Additional style and class attributes.
267        """
268        if 'class' not in kwargs:
269            kwargs['class'] = []
270        elif isinstance(kwargs['class'], str):
271            kwargs['class'] = [kwargs['class']]
272        kwargs['class'].append('img-fluid')
273        s = _parse_style_class(kwargs)
274
275        buffer = BytesIO()
276        if as_svg:
277            src.savefig(buffer, format='svg')
278            svg = buffer.getvalue()
279            svg = svg.replace(b'\n', b'').decode('utf-8')
280            self.content += f"""<div {s}>{svg}</div>"""
281        else:
282            src.savefig(buffer, format='png')
283            image_data = buffer.getvalue()
284            image_base64 = base64.b64encode(image_data).decode("utf-8")
285            image_src = f"data:image/png;base64,{image_base64}"
286            self.content += f"""<img src="{image_src}" alt="{alt}" {s}>"""
287        buffer.close()
288
289    def render(self):
290        """
291        Renders the content as a pretty-formatted HTML string.
292        
293        Returns:
294            str: The rendered HTML content.
295        """
296        html = f"""<div>{self.content}</div>"""
297        soup = BeautifulSoup(html, "html.parser")
298        ident_content = soup.prettify()
299        return ident_content

A class to build and render HTML content.

Methods: clear(): Clears the current content. add_script(name: str, script: str): Adds a script with a given name. add_heading(text: str, tag: str = "h3", icon: str = None, *kwargs): Adds a heading with an optional icon. add_text(text: str, tag: str = "p", *kwargs): Adds a paragraph or span of text. add_list(items: list, ordered=False, *kwargs): Adds an ordered or unordered list. add_image(src: str, alt: str = "", *kwargs): Adds an image from a URL or local source. add_svg(svg: str, *kwargs): Adds an SVG element. add_plotly(json: str, *kwargs): Adds a Plotly chart. add_altair(json: str, *kwargs): Adds an Altair chart. add_div(div: str, *kwargs): Adds a div element. add_fig(src: Figure, alt: str = "", as_svg=True, **kwargs): Adds a Matplotlib figure. render(): Renders the content as a pretty-formatted HTML string.

content
scripts
grid_cols
def clear(self):
83    def clear(self):
84        """Clears the current content."""
85        self.content = ""

Clears the current content.

def add_script(self, name: str, script: str):
87    def add_script(self, name: str, script: str):
88        """
89        Adds a script with a given name.
90        
91        Args:
92            name (str): The name of the script.
93            script (str): The script content.
94        """
95        self.scripts[name] = script

Adds a script with a given name.

Args: name (str): The name of the script. script (str): The script content.

def add_heading(self, text: str, tag: str = 'h3', icon: str = None, **kwargs):
 97    def add_heading(self, text: str, tag: str = "h3", icon: str = None, **kwargs):
 98        """
 99        Adds a heading with an optional icon.
100        
101        Args:
102            text (str): The heading text.
103            tag (str, optional): The HTML tag for the heading (default is "h3").
104            icon (str, optional): The icon class for the heading.
105            **kwargs: Additional style and class attributes.
106        
107        Raises:
108            ValueError: If the tag is not a valid heading tag.
109        """
110        if tag not in ["h1", "h2", "h3", "h4", "h5"]:
111            raise ValueError("Invalid tag, the tag must be one of h1, h2, h3, h4 or h5")
112
113        s = _parse_style_class(kwargs)
114        self.content += (
115            f"<{tag} {s}><i class='{icon}'></i> {text}</{tag}>"
116            if icon
117            else f"<{tag} {s}>{text}</{tag}>"
118        )

Adds a heading with an optional icon.

Args: text (str): The heading text. tag (str, optional): The HTML tag for the heading (default is "h3"). icon (str, optional): The icon class for the heading. **kwargs: Additional style and class attributes.

Raises: ValueError: If the tag is not a valid heading tag.

def add_text(self, text: str, tag: str = 'p', **kwargs):
120    def add_text(self, text: str, tag: str = "p", **kwargs):
121        """
122        Adds a paragraph or span of text.
123        
124        Args:
125            text (str): The text content.
126            tag (str, optional): The HTML tag for the text (default is "p").
127            **kwargs: Additional style and class attributes.
128        
129        Raises:
130            ValueError: If the tag is not a valid text tag.
131        """
132        if tag not in ["p", "span"]:
133            raise ValueError("Invalid tag, the tag must be one of p or span")
134
135        s = _parse_style_class(kwargs)
136        self.content += f"""<{tag} {s}>{text}</{tag}>"""

Adds a paragraph or span of text.

Args: text (str): The text content. tag (str, optional): The HTML tag for the text (default is "p"). **kwargs: Additional style and class attributes.

Raises: ValueError: If the tag is not a valid text tag.

def add_list(self, items: list, ordered=False, **kwargs):
138    def add_list(self, items: list, ordered=False, **kwargs):
139        """
140        Adds an ordered or unordered list.
141        
142        Args:
143            items (list): A list of items to be added to the list.
144            ordered (bool, optional): Whether the list should be ordered (default is False).
145            **kwargs: Additional style and class attributes.
146        """
147        list_tag = "ol" if ordered else "ul"
148        s = _parse_style_class(kwargs)
149        list_items = "\n".join([f"<li>{item}</li>" for item in items])
150        self.content += f"<{list_tag} {s}>\n{list_items}\n</{list_tag}>"

Adds an ordered or unordered list.

Args: items (list): A list of items to be added to the list. ordered (bool, optional): Whether the list should be ordered (default is False). **kwargs: Additional style and class attributes.

def add_image(self, src: str, alt: str = '', **kwargs):
152    def add_image(self, src: str, alt: str = "", **kwargs):
153        """
154        Adds an image from a URL or local source.
155        
156        Args:
157            src (str): The source URL or local path of the image.
158            alt (str, optional): The alt text for the image (default is "").
159            **kwargs: Additional style and class attributes.
160        
161        Raises:
162            Exception: If the image cannot be fetched from the URL.
163        """
164        if 'class' not in kwargs:
165            kwargs['class'] = []
166        elif isinstance(kwargs['class'], str):
167            kwargs['class'] = [kwargs['class']]
168        kwargs['class'].append('img-fluid')
169
170        if src.startswith(('http://', 'https://')):
171            response = requests.get(src)
172            if response.status_code == 200:
173                image_data = response.content
174            else:
175                raise Exception(f"Failed to fetch image from URL: {src}")
176        else:
177            with open(src, "rb") as f:
178                image_data = f.read()
179
180        image_base64 = base64.b64encode(image_data).decode("utf-8")
181        image_src = f"data:image/png;base64,{image_base64}"
182
183        s = _parse_style_class(kwargs)
184        self.content += f"""<img src="{image_src}" alt="{alt}" {s}>"""

Adds an image from a URL or local source.

Args: src (str): The source URL or local path of the image. alt (str, optional): The alt text for the image (default is ""). **kwargs: Additional style and class attributes.

Raises: Exception: If the image cannot be fetched from the URL.

def add_svg(self, svg: str, **kwargs):
186    def add_svg(self, svg: str, **kwargs):
187        """
188        Adds an SVG element.
189        
190        Args:
191            svg (str): The SVG content.
192            **kwargs: Additional style and class attributes.
193        """
194        if 'class' not in kwargs:
195            kwargs['class'] = []
196        elif isinstance(kwargs['class'], str):
197            kwargs['class'] = [kwargs['class']]
198        kwargs['class'].append('img-fluid')
199
200        s = _parse_style_class(kwargs)
201        self.content += f"""<div {s}>{svg}</div>"""

Adds an SVG element.

Args: svg (str): The SVG content. **kwargs: Additional style and class attributes.

def add_plotly(self, json: str, **kwargs):
203    def add_plotly(self, json: str, **kwargs):
204        """
205        Adds a Plotly chart.
206        
207        Args:
208            json (str): The Plotly chart data in JSON format.
209            **kwargs: Additional style and class attributes.
210        """
211        if 'class' not in kwargs:
212            kwargs['class'] = []
213        elif isinstance(kwargs['class'], str):
214            kwargs['class'] = [kwargs['class']]
215        kwargs['class'].append('img-fluid')
216
217        s = _parse_style_class(kwargs)
218
219        j = json.replace("'", "\u2019")
220        chart_id = "chart-" + str(uuid.uuid4())
221        self.content += f"""<div {s} id='{chart_id}'></div>
222            <script>var Plotjson = '{j}';
223            var figure = JSON.parse(Plotjson);
224            Plotly.newPlot('{chart_id}', figure.data, figure.layout);</script>"""

Adds a Plotly chart.

Args: json (str): The Plotly chart data in JSON format. **kwargs: Additional style and class attributes.

def add_altair(self, json: str, **kwargs):
226    def add_altair(self, json: str, **kwargs):
227        """
228        Adds an Altair chart.
229        
230        Args:
231            json (str): The Altair chart data in JSON format.
232            **kwargs: Additional style and class attributes.
233        """
234        if 'class' not in kwargs:
235            kwargs['class'] = []
236        elif isinstance(kwargs['class'], str):
237            kwargs['class'] = [kwargs['class']]
238        kwargs['class'].append('img-fluid')
239
240        s = _parse_style_class(kwargs)
241
242        chart_id = "chart-" + str(uuid.uuid4())
243        self.content += f"""<div {s} id='{chart_id}'></div>
244        <script>var opt = {{renderer: "svg"}};
245        vegaEmbed("#{chart_id}", {json} , opt);</script>"""

Adds an Altair chart.

Args: json (str): The Altair chart data in JSON format. **kwargs: Additional style and class attributes.

def add_div(self, div: str, **kwargs):
247    def add_div(self, div: str, **kwargs):
248        """
249        Adds a div element.
250        
251        Args:
252            div (str): The div content.
253            **kwargs: Additional style and class attributes.
254        """
255        s = _parse_style_class(kwargs)
256        self.content += f"""<div {s}>{div}</div>"""

Adds a div element.

Args: div (str): The div content. **kwargs: Additional style and class attributes.

def add_fig( self, src: matplotlib.figure.Figure, alt: str = '', as_svg=True, **kwargs):
258    def add_fig(self, src: Figure, alt: str = "", as_svg=True, **kwargs):
259        """
260        Adds a Matplotlib figure.
261        
262        Args:
263            src (Figure): The Matplotlib figure object.
264            alt (str, optional): The alt text for the image (default is "").
265            as_svg (bool, optional): Whether to render the figure as SVG (default is True).
266            **kwargs: Additional style and class attributes.
267        """
268        if 'class' not in kwargs:
269            kwargs['class'] = []
270        elif isinstance(kwargs['class'], str):
271            kwargs['class'] = [kwargs['class']]
272        kwargs['class'].append('img-fluid')
273        s = _parse_style_class(kwargs)
274
275        buffer = BytesIO()
276        if as_svg:
277            src.savefig(buffer, format='svg')
278            svg = buffer.getvalue()
279            svg = svg.replace(b'\n', b'').decode('utf-8')
280            self.content += f"""<div {s}>{svg}</div>"""
281        else:
282            src.savefig(buffer, format='png')
283            image_data = buffer.getvalue()
284            image_base64 = base64.b64encode(image_data).decode("utf-8")
285            image_src = f"data:image/png;base64,{image_base64}"
286            self.content += f"""<img src="{image_src}" alt="{alt}" {s}>"""
287        buffer.close()

Adds a Matplotlib figure.

Args: src (Figure): The Matplotlib figure object. alt (str, optional): The alt text for the image (default is ""). as_svg (bool, optional): Whether to render the figure as SVG (default is True). **kwargs: Additional style and class attributes.

def render(self):
289    def render(self):
290        """
291        Renders the content as a pretty-formatted HTML string.
292        
293        Returns:
294            str: The rendered HTML content.
295        """
296        html = f"""<div>{self.content}</div>"""
297        soup = BeautifulSoup(html, "html.parser")
298        ident_content = soup.prettify()
299        return ident_content

Renders the content as a pretty-formatted HTML string.

Returns: str: The rendered HTML content.

class Slide:
 37class Slide:
 38    """
 39    A class representing a slide in the presentation.
 40
 41    Attributes:
 42        content (str): The HTML content of the slide.
 43        center (bool): Whether the slide content should be centered.
 44        kwargs (dict): Additional attributes for the slide element.
 45    """
 46    def __init__(self, center=False, **kwargs):
 47        """
 48        Initializes a new Slide object.
 49
 50        Args:
 51            center (bool): Whether the slide content should be centered (default is False).
 52            **kwargs: Additional attributes for the slide element.
 53        """
 54        self.content = ""
 55        self.center = center
 56        self.kwargs = kwargs
 57
 58    def add_title(self, text: str, tag: str = "h3", icon: str = None, **kwargs):
 59        """
 60        Adds a title to the slide.
 61
 62        Args:
 63            text (str): The title text.
 64            tag (str, optional): The HTML tag for the title (default is "h3").
 65            icon (str, optional): The icon class for the title.
 66            **kwargs: Additional style and class attributes.
 67        """
 68        c = Content()
 69        c.add_heading(text, tag, icon, **kwargs)
 70        row = "<div class='row'><div class='col-12 mx-auto'>"
 71        self.content += row + c.render() + "</div></div>"
 72
 73    def add_content(self, content: list, columns=None, styles: list = None):
 74        """
 75        Adds content to the slide.
 76
 77        Args:
 78            content (list): A list of content elements (str or Figure).
 79            columns (list, optional): A list of column sizes for the content elements (default is [12]).
 80            styles (list, optional): A list of style dictionaries for the content elements.
 81        """
 82        if columns is None:
 83            columns = [12]
 84
 85        _check_styles(styles, content, columns)
 86
 87        row = "<div class='row'>"
 88        for i in range(len(content)):
 89            col = content[i]
 90            if isinstance(col, (str, Figure)):
 91                col = _check_content_type(col)
 92                if styles and len(styles) > i:
 93                    col = f"<div class='col-md-{columns[i]}' {_parse_style_class(styles[i])}>{col}</div>"
 94                else:
 95                    col = f"<div class='col-md-{columns[i]}'>{col}</div>"
 96            row += col
 97        self.content += row + "</div>"
 98
 99    def add_card(self, cards: list, styles: list = None):
100        """
101        Adds cards to the slide.
102
103        Args:
104            cards (list): A list of card dictionaries with 'image', 'title', and 'text' keys.
105            styles (list, optional): A list of style dictionaries for the cards.
106        """
107        _check_styles(styles, cards)
108
109        if styles is None:
110            styles = [{'class': 'bg-info'}] * len(cards)
111
112        cards_html = ""
113        for card, style in zip(cards, styles):
114            if 'class' not in style:
115                style['class'] = []
116            elif isinstance(style['class'], str):
117                style['class'] = [style['class']]
118            style['class'].append('card h-100')
119
120            s = _parse_style_class(style)
121            card_html = ""
122            for key in card.keys():
123                if key == 'image':
124                    card_html += f'<img src="{card[key]}" class="card-img-top mx-auto" alt="">'
125                elif key == 'title':
126                    card_html += f'<h4 class="card-title">{card[key]}</h4>'
127                elif key == 'text':
128                    card[key] = _add_list_classes(card[key])
129                    card_html += f'<p class="card-text" style="font-size:60%">{card[key]}</p>'
130            cards_html += f"""
131            <div class="col">
132                <div {s}> 
133                    {card_html}
134                </div>
135            </div>"""
136        self.content += f"<div class='row'>{cards_html}</div>"
137
138    def add_title_page(self, title_page_content: dict, styles: list = None):
139        """
140        Adds a title page to the slide.
141
142        Args:
143            title_page_content (dict): A dictionary with 'title', 'subtitle', 'authors', and 'logo' keys.
144            styles (list, optional): A list of style dictionaries for the title, subtitle, authors, and logo.
145        """
146        title = title_page_content.get('title', '')
147        subtitle = title_page_content.get('subtitle', '')
148        authors = title_page_content.get('authors', '')
149        logo = title_page_content.get('logo', '')
150
151        _check_styles(styles, title_page_content)
152
153        if styles is None:
154            styles = []
155
156        title_s = _parse_style_class(styles[0]) if styles else ""
157        subtitle_s = _parse_style_class(styles[1]) if styles else ""
158        authors_s = _parse_style_class(styles[2]) if styles else ""
159        logo_s = _parse_style_class(styles[3]) if styles else ""
160
161        title_html = f'<div class="row"><div class="col-12"><h2 {title_s}>{title}</h2></div></div>' if title else ''
162        subtitle_html = f'<div class="row"><div class="col-12"><h3 {subtitle_s}>{subtitle}</h3></div></div>' if subtitle else ''
163        authors_html = f'<div class="col-9"><h4 {authors_s}>{authors}</h4></div>' if authors else ''
164        logo_html = f'<div class="col-3"><img src="{logo}" {logo_s}></div>' if logo else ''
165        authors_logo_html = f'<div class="row align-items-center">{authors_html}{logo_html}</div>'
166
167
168        title_page_html = f'<div class="title-page">{title_html}{subtitle_html}{authors_logo_html}</div>'
169        self.content += title_page_html
170
171    def render_slide_html(self):
172        """
173        Renders the slide as an HTML string.
174
175        Returns:
176            str: The HTML representation of the slide.
177        """
178        css_links = """
179        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.4.0/reveal.min.css">
180        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.4.0/theme/moon.min.css">
181        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
182        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css">
183        """
184        js_links = """
185        <script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.4.0/reveal.js"></script>
186        <script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.4.0/plugin/notes/notes.js"></script>
187        <script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
188        <script src="https://cdn.jsdelivr.net/npm/vega-lite@4.8"></script>
189        <script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
190        <script src="https://cdn.plot.ly/plotly-2.17.1.min.js"></script>
191        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
192        <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
193        """
194
195        kwargs_str = ' '.join([f'{k}="{v}"' for k, v in self.kwargs.items()])
196        slide_html = f"""
197        <!DOCTYPE html>
198        <html lang="en">
199        <head>
200            <meta charset="UTF-8">
201            <meta name="viewport" content="width=device-width, initial-scale=1.0">
202            <title>Slide</title>
203            {css_links}
204            <style>
205                .reveal .slides section {{
206                    top: 0 !important;
207                }}
208            </style>
209        </head>
210        <body>
211            <div class="reveal">
212                <div class="slides">
213                    <section {kwargs_str} class='{'center' if self.center else ''}'>
214                        <div class='container' style='text-align: left;' >
215                            {self.content}
216                        </div>
217                    </section>
218                </div>
219            </div>
220            {js_links}
221            <script>
222                Reveal.initialize({{
223                    center: false,
224                    controls: true,
225                    progress: true,
226                    history: true,
227                    transition: 'slide',
228                    plugins: [RevealNotes]
229                }});
230            </script>
231        </body>
232        </html>
233        """
234        return slide_html
235
236    def save_slide_html(self, file_name):
237        """
238        Saves the slide as an HTML file.
239
240        Args:
241            file_name (str): The name of the file to save the slide as.
242        """
243        slide_html = self.render_slide_html()
244        with open(file_name, "w") as f:
245            f.write(slide_html)

A class representing a slide in the presentation.

Attributes: content (str): The HTML content of the slide. center (bool): Whether the slide content should be centered. kwargs (dict): Additional attributes for the slide element.

Slide(center=False, **kwargs)
46    def __init__(self, center=False, **kwargs):
47        """
48        Initializes a new Slide object.
49
50        Args:
51            center (bool): Whether the slide content should be centered (default is False).
52            **kwargs: Additional attributes for the slide element.
53        """
54        self.content = ""
55        self.center = center
56        self.kwargs = kwargs

Initializes a new Slide object.

Args: center (bool): Whether the slide content should be centered (default is False). **kwargs: Additional attributes for the slide element.

content
center
kwargs
def add_title(self, text: str, tag: str = 'h3', icon: str = None, **kwargs):
58    def add_title(self, text: str, tag: str = "h3", icon: str = None, **kwargs):
59        """
60        Adds a title to the slide.
61
62        Args:
63            text (str): The title text.
64            tag (str, optional): The HTML tag for the title (default is "h3").
65            icon (str, optional): The icon class for the title.
66            **kwargs: Additional style and class attributes.
67        """
68        c = Content()
69        c.add_heading(text, tag, icon, **kwargs)
70        row = "<div class='row'><div class='col-12 mx-auto'>"
71        self.content += row + c.render() + "</div></div>"

Adds a title to the slide.

Args: text (str): The title text. tag (str, optional): The HTML tag for the title (default is "h3"). icon (str, optional): The icon class for the title. **kwargs: Additional style and class attributes.

def add_content(self, content: list, columns=None, styles: list = None):
73    def add_content(self, content: list, columns=None, styles: list = None):
74        """
75        Adds content to the slide.
76
77        Args:
78            content (list): A list of content elements (str or Figure).
79            columns (list, optional): A list of column sizes for the content elements (default is [12]).
80            styles (list, optional): A list of style dictionaries for the content elements.
81        """
82        if columns is None:
83            columns = [12]
84
85        _check_styles(styles, content, columns)
86
87        row = "<div class='row'>"
88        for i in range(len(content)):
89            col = content[i]
90            if isinstance(col, (str, Figure)):
91                col = _check_content_type(col)
92                if styles and len(styles) > i:
93                    col = f"<div class='col-md-{columns[i]}' {_parse_style_class(styles[i])}>{col}</div>"
94                else:
95                    col = f"<div class='col-md-{columns[i]}'>{col}</div>"
96            row += col
97        self.content += row + "</div>"

Adds content to the slide.

Args: content (list): A list of content elements (str or Figure). columns (list, optional): A list of column sizes for the content elements (default is [12]). styles (list, optional): A list of style dictionaries for the content elements.

def add_card(self, cards: list, styles: list = None):
 99    def add_card(self, cards: list, styles: list = None):
100        """
101        Adds cards to the slide.
102
103        Args:
104            cards (list): A list of card dictionaries with 'image', 'title', and 'text' keys.
105            styles (list, optional): A list of style dictionaries for the cards.
106        """
107        _check_styles(styles, cards)
108
109        if styles is None:
110            styles = [{'class': 'bg-info'}] * len(cards)
111
112        cards_html = ""
113        for card, style in zip(cards, styles):
114            if 'class' not in style:
115                style['class'] = []
116            elif isinstance(style['class'], str):
117                style['class'] = [style['class']]
118            style['class'].append('card h-100')
119
120            s = _parse_style_class(style)
121            card_html = ""
122            for key in card.keys():
123                if key == 'image':
124                    card_html += f'<img src="{card[key]}" class="card-img-top mx-auto" alt="">'
125                elif key == 'title':
126                    card_html += f'<h4 class="card-title">{card[key]}</h4>'
127                elif key == 'text':
128                    card[key] = _add_list_classes(card[key])
129                    card_html += f'<p class="card-text" style="font-size:60%">{card[key]}</p>'
130            cards_html += f"""
131            <div class="col">
132                <div {s}> 
133                    {card_html}
134                </div>
135            </div>"""
136        self.content += f"<div class='row'>{cards_html}</div>"

Adds cards to the slide.

Args: cards (list): A list of card dictionaries with 'image', 'title', and 'text' keys. styles (list, optional): A list of style dictionaries for the cards.

def add_title_page(self, title_page_content: dict, styles: list = None):
138    def add_title_page(self, title_page_content: dict, styles: list = None):
139        """
140        Adds a title page to the slide.
141
142        Args:
143            title_page_content (dict): A dictionary with 'title', 'subtitle', 'authors', and 'logo' keys.
144            styles (list, optional): A list of style dictionaries for the title, subtitle, authors, and logo.
145        """
146        title = title_page_content.get('title', '')
147        subtitle = title_page_content.get('subtitle', '')
148        authors = title_page_content.get('authors', '')
149        logo = title_page_content.get('logo', '')
150
151        _check_styles(styles, title_page_content)
152
153        if styles is None:
154            styles = []
155
156        title_s = _parse_style_class(styles[0]) if styles else ""
157        subtitle_s = _parse_style_class(styles[1]) if styles else ""
158        authors_s = _parse_style_class(styles[2]) if styles else ""
159        logo_s = _parse_style_class(styles[3]) if styles else ""
160
161        title_html = f'<div class="row"><div class="col-12"><h2 {title_s}>{title}</h2></div></div>' if title else ''
162        subtitle_html = f'<div class="row"><div class="col-12"><h3 {subtitle_s}>{subtitle}</h3></div></div>' if subtitle else ''
163        authors_html = f'<div class="col-9"><h4 {authors_s}>{authors}</h4></div>' if authors else ''
164        logo_html = f'<div class="col-3"><img src="{logo}" {logo_s}></div>' if logo else ''
165        authors_logo_html = f'<div class="row align-items-center">{authors_html}{logo_html}</div>'
166
167
168        title_page_html = f'<div class="title-page">{title_html}{subtitle_html}{authors_logo_html}</div>'
169        self.content += title_page_html

Adds a title page to the slide.

Args: title_page_content (dict): A dictionary with 'title', 'subtitle', 'authors', and 'logo' keys. styles (list, optional): A list of style dictionaries for the title, subtitle, authors, and logo.

def render_slide_html(self):
171    def render_slide_html(self):
172        """
173        Renders the slide as an HTML string.
174
175        Returns:
176            str: The HTML representation of the slide.
177        """
178        css_links = """
179        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.4.0/reveal.min.css">
180        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.4.0/theme/moon.min.css">
181        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
182        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css">
183        """
184        js_links = """
185        <script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.4.0/reveal.js"></script>
186        <script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.4.0/plugin/notes/notes.js"></script>
187        <script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
188        <script src="https://cdn.jsdelivr.net/npm/vega-lite@4.8"></script>
189        <script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
190        <script src="https://cdn.plot.ly/plotly-2.17.1.min.js"></script>
191        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
192        <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
193        """
194
195        kwargs_str = ' '.join([f'{k}="{v}"' for k, v in self.kwargs.items()])
196        slide_html = f"""
197        <!DOCTYPE html>
198        <html lang="en">
199        <head>
200            <meta charset="UTF-8">
201            <meta name="viewport" content="width=device-width, initial-scale=1.0">
202            <title>Slide</title>
203            {css_links}
204            <style>
205                .reveal .slides section {{
206                    top: 0 !important;
207                }}
208            </style>
209        </head>
210        <body>
211            <div class="reveal">
212                <div class="slides">
213                    <section {kwargs_str} class='{'center' if self.center else ''}'>
214                        <div class='container' style='text-align: left;' >
215                            {self.content}
216                        </div>
217                    </section>
218                </div>
219            </div>
220            {js_links}
221            <script>
222                Reveal.initialize({{
223                    center: false,
224                    controls: true,
225                    progress: true,
226                    history: true,
227                    transition: 'slide',
228                    plugins: [RevealNotes]
229                }});
230            </script>
231        </body>
232        </html>
233        """
234        return slide_html

Renders the slide as an HTML string.

Returns: str: The HTML representation of the slide.

def save_slide_html(self, file_name):
236    def save_slide_html(self, file_name):
237        """
238        Saves the slide as an HTML file.
239
240        Args:
241            file_name (str): The name of the file to save the slide as.
242        """
243        slide_html = self.render_slide_html()
244        with open(file_name, "w") as f:
245            f.write(slide_html)

Saves the slide as an HTML file.

Args: file_name (str): The name of the file to save the slide as.

class Presentation:
 14class Presentation:
 15    """
 16    A class representing a presentation.
 17
 18    Attributes:
 19        slides (list): A list of slides in the presentation.
 20    """
 21
 22    def __init__(self):
 23        """Initializes a new Presentation object."""
 24        self.slides = []
 25
 26    def add_slide(self, slide):
 27        """
 28        Adds a slide or list of slides to the presentation.
 29
 30        Args:
 31            slide (Slide or list): The slide or list of slides to add to the presentation.
 32        """
 33        if isinstance(slide, list):
 34            for sl in slide:
 35                self.slides.append(sl)
 36        else:
 37            self.slides.append(slide)
 38
 39    def to_html(self, theme="moon", width=960, height=600, minscale=0.2, maxscale=1.5, margin=0.1, custom_theme=None):
 40        """
 41        Returns the presentation as an HTML string.
 42
 43        Args:
 44            theme (str): The name of the reveal.js theme to use (default is 'moon').
 45            width (int): The width of the presentation (default is 960).
 46            height (int): The height of the presentation (default is 600).
 47            minscale (float): The minimum scale of the presentation (default is 0.2).
 48            maxscale (float): The maximum scale of the presentation (default is 1.5).
 49            margin (float): The margin of the presentation (default is 0.1).
 50            custom_theme (str, optional): A link to a custom theme CSS file if theme is set to 'custom'.
 51
 52        Returns:
 53            str: The presentation in HTML format.
 54
 55        Raises:
 56            ValueError: If the theme is set to 'custom' but no custom_theme link is provided.
 57        """
 58        if theme == "custom" and custom_theme is None:
 59            raise ValueError("If the theme is set to 'custom', a URL for the custom theme must be provided.")
 60
 61        if custom_theme:
 62            theme_link = custom_theme
 63        else:
 64            theme_link = f"https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.4.0/theme/{theme}.min.css"
 65
 66        css_links = [
 67            "https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.4.0/reveal.min.css",
 68            theme_link,
 69            "https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css",
 70            "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css"
 71        ]
 72        js_links = [
 73            "https://cdn.jsdelivr.net/npm/vega@5",
 74            "https://cdn.jsdelivr.net/npm/vega-lite@4.8",
 75            "https://cdn.jsdelivr.net/npm/vega-embed@6",
 76            "https://cdn.plot.ly/plotly-2.17.1.min.js",
 77            "https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js",
 78            "https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js",
 79            "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"
 80        ]
 81
 82        css_links = "\n".join([f"<link type='text/css' href='{link}' rel='stylesheet'>" for link in css_links])
 83        js_links = "\n".join([f"<script src='{link}' type='text/javascript'></script>" for link in js_links])
 84
 85        slides_html = "\n".join([create_slide_html(slide) for slide in self.slides])
 86
 87        presentation_html = f"""
 88        <html>
 89         <head>
 90          <meta charset="UTF-8">
 91          {css_links}
 92          <style type='text/css'>svg{{max-width: 100%;}}</style>
 93          {js_links}
 94         </head>
 95         <body>
 96            <div class='reveal'>
 97                <div class='slides'>
 98                    {slides_html}
 99                </div>
100            </div>
101            <!--Correction to allow transition between slides-->
102            <style type='text/css'>[hidden] {{display: inherit !important;}}</style>
103            
104            <script>
105            // from nbconvert
106            require(
107            {{
108              // it makes sense to wait a little bit when you are loading
109              // reveal from a cdn in a slow connection environment
110              waitSeconds: 15
111            }},
112            [
113              "https://unpkg.com/reveal.js@4.4.0/dist/reveal.js",
114              "https://unpkg.com/reveal.js@4.4.0/plugin/notes/notes.js"
115            ],
116        
117            function(Reveal, RevealNotes){{
118                Reveal.initialize({{
119                    center: false,
120                    pdfMaxPagesPerSlide: 1,
121                    pdfSeparateFragments: false,
122                    display:'block',
123                    slideNumber: 'c/t',  
124                    controls: true,
125                    
126                    progress: true,
127                    history: true,
128                    transition: "slide",
129        
130                    plugins: [RevealNotes],
131                    width: {width},
132                    height: {height},
133                    center: true,
134                    margin: {margin},
135                        
136                    minScale: {minscale},
137                    maxScale: {maxscale},
138            }});
139              
140                var update = function(event){{
141                  if(MathJax.Hub.getAllJax(Reveal.getCurrentSlide())){{
142                    MathJax.Hub.Rerender(Reveal.getCurrentSlide());
143                  }}
144                }};
145        
146                Reveal.addEventListener('slidechanged', update);
147        
148                function setScrollingSlide() {{
149                    var scroll = false
150                    if (scroll === true) {{
151                      var h = $('.reveal').height() * 0.95;
152                      $('section.present').find('section')
153                        .filter(function() {{
154                          return $(this).height() > h;
155                        }})
156                        .css('height', 'calc(95vh)')
157                        .css('overflow-y', 'scroll')
158                        .css('margin-top', '20px');
159                    }}
160                }}
161        
162                // check and set the scrolling slide every time the slide change
163                Reveal.addEventListener('slidechanged', setScrollingSlide);
164            }}
165            );
166            </script>
167             </body>
168        </html>
169        """
170        soup = BeautifulSoup(presentation_html, "html.parser")
171        return presentation_html
172
173    def save_html(self, file_name, theme="moon", width=960, height=600, minscale=0.2, maxscale=1.5, margin=0.1,
174                  custom_theme=None):
175        """
176        Saves the presentation as an HTML file.
177
178        Args:
179            file_name (str): The name of the file to save the presentation as.
180            theme (str, optional): The name of the reveal.js theme to use (default is 'moon').
181            width (int, optional): The width of the presentation (default is 960).
182            height (int, optional): The height of the presentation (default is 600).
183            minscale (float, optional): The minimum scale of the presentation (default is 0.2).
184            maxscale (float, optional): The maximum scale of the presentation (default is 1.5).
185            margin (float, optional): The margin of the presentation (default is 0.1).
186            custom_theme (str, optional): A link to a custom theme CSS file if theme is set to 'custom'.
187
188        Raises:
189            ValueError: If the theme is set to 'custom' but no custom_theme link is provided.
190        """
191        if theme == "custom" and custom_theme is None:
192            raise ValueError("If the theme is set to 'custom', a URL for the custom theme must be provided.")
193
194        if custom_theme:
195            theme_link = custom_theme
196        else:
197            theme_link = theme
198
199        presentation_html = self.to_html(theme=theme_link, width=width, height=height, minscale=minscale,
200                                         maxscale=maxscale, margin=margin, custom_theme=custom_theme)
201
202        with open(file_name, "w") as f:
203            f.write(presentation_html)
204
205    # def save_slide_html(self, slide, file_name, theme="moon"):
206    #     """
207    #     Saves a single slide as an HTML file.
208
209    #     Args:
210    #         slide (Slide): The slide to save.
211    #         file_name (str): The name of the file to save the slide as.
212    #         theme (str, optional): The name of the reveal.js theme to use (default is 'moon').
213    #     """
214    #     css_links = [
215    #         "https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.4.0/reveal.min.css",
216    #         f"https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.4.0/theme/{theme}.min.css",
217    #         "https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css",
218    #         "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css"
219    #     ]
220    #     js_links = [
221    #         "https://cdn.jsdelivr.net/npm/vega@5",
222    #         "https://cdn.jsdelivr.net/npm/vega-lite@4.8",
223    #         "https://cdn.jsdelivr.net/npm/vega-embed@6",
224    #         "https://cdn.plot.ly/plotly-2.17.1.min.js",
225    #         "https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js",
226    #         "https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js",
227    #         "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"
228    #     ]
229
230    #     css_links = "\n".join([f"<link type='text/css' href='{link}' rel='stylesheet'>" for link in css_links])
231    #     js_links = "\n".join([f"<script src='{link}' type='text/javascript'></script>" for link in js_links])
232
233    #     slide_html = f"""
234    #     <html>
235    #     <head>
236    #     <meta charset="UTF-8">
237    #     {css_links}
238    #     </head>
239    #     <body>
240    #     <div class='reveal'>
241    #         <div class='slides'>
242    #             {create_slide_html(slide)}
243    #         </div>
244    #     </div>
245    #     {js_links}
246    #     <script>
247    #     document.addEventListener('DOMContentLoaded', function() {{
248    #         Reveal.initialize({{
249    #             center: false,
250    #             controls: true,
251    #             progress: true,
252    #             history: true,
253    #             transition: 'slide',
254    #             plugins: [RevealNotes]
255    #         }});
256    #     }});
257    #     </script>
258    #     </body>
259    #     </html>
260    #     """
261    #     with open(file_name, "w") as f:
262    #         f.write(slide_html)

A class representing a presentation.

Attributes: slides (list): A list of slides in the presentation.

Presentation()
22    def __init__(self):
23        """Initializes a new Presentation object."""
24        self.slides = []

Initializes a new Presentation object.

slides
def add_slide(self, slide):
26    def add_slide(self, slide):
27        """
28        Adds a slide or list of slides to the presentation.
29
30        Args:
31            slide (Slide or list): The slide or list of slides to add to the presentation.
32        """
33        if isinstance(slide, list):
34            for sl in slide:
35                self.slides.append(sl)
36        else:
37            self.slides.append(slide)

Adds a slide or list of slides to the presentation.

Args: slide (Slide or list): The slide or list of slides to add to the presentation.

def to_html( self, theme='moon', width=960, height=600, minscale=0.2, maxscale=1.5, margin=0.1, custom_theme=None):
 39    def to_html(self, theme="moon", width=960, height=600, minscale=0.2, maxscale=1.5, margin=0.1, custom_theme=None):
 40        """
 41        Returns the presentation as an HTML string.
 42
 43        Args:
 44            theme (str): The name of the reveal.js theme to use (default is 'moon').
 45            width (int): The width of the presentation (default is 960).
 46            height (int): The height of the presentation (default is 600).
 47            minscale (float): The minimum scale of the presentation (default is 0.2).
 48            maxscale (float): The maximum scale of the presentation (default is 1.5).
 49            margin (float): The margin of the presentation (default is 0.1).
 50            custom_theme (str, optional): A link to a custom theme CSS file if theme is set to 'custom'.
 51
 52        Returns:
 53            str: The presentation in HTML format.
 54
 55        Raises:
 56            ValueError: If the theme is set to 'custom' but no custom_theme link is provided.
 57        """
 58        if theme == "custom" and custom_theme is None:
 59            raise ValueError("If the theme is set to 'custom', a URL for the custom theme must be provided.")
 60
 61        if custom_theme:
 62            theme_link = custom_theme
 63        else:
 64            theme_link = f"https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.4.0/theme/{theme}.min.css"
 65
 66        css_links = [
 67            "https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.4.0/reveal.min.css",
 68            theme_link,
 69            "https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css",
 70            "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css"
 71        ]
 72        js_links = [
 73            "https://cdn.jsdelivr.net/npm/vega@5",
 74            "https://cdn.jsdelivr.net/npm/vega-lite@4.8",
 75            "https://cdn.jsdelivr.net/npm/vega-embed@6",
 76            "https://cdn.plot.ly/plotly-2.17.1.min.js",
 77            "https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js",
 78            "https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js",
 79            "https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"
 80        ]
 81
 82        css_links = "\n".join([f"<link type='text/css' href='{link}' rel='stylesheet'>" for link in css_links])
 83        js_links = "\n".join([f"<script src='{link}' type='text/javascript'></script>" for link in js_links])
 84
 85        slides_html = "\n".join([create_slide_html(slide) for slide in self.slides])
 86
 87        presentation_html = f"""
 88        <html>
 89         <head>
 90          <meta charset="UTF-8">
 91          {css_links}
 92          <style type='text/css'>svg{{max-width: 100%;}}</style>
 93          {js_links}
 94         </head>
 95         <body>
 96            <div class='reveal'>
 97                <div class='slides'>
 98                    {slides_html}
 99                </div>
100            </div>
101            <!--Correction to allow transition between slides-->
102            <style type='text/css'>[hidden] {{display: inherit !important;}}</style>
103            
104            <script>
105            // from nbconvert
106            require(
107            {{
108              // it makes sense to wait a little bit when you are loading
109              // reveal from a cdn in a slow connection environment
110              waitSeconds: 15
111            }},
112            [
113              "https://unpkg.com/reveal.js@4.4.0/dist/reveal.js",
114              "https://unpkg.com/reveal.js@4.4.0/plugin/notes/notes.js"
115            ],
116        
117            function(Reveal, RevealNotes){{
118                Reveal.initialize({{
119                    center: false,
120                    pdfMaxPagesPerSlide: 1,
121                    pdfSeparateFragments: false,
122                    display:'block',
123                    slideNumber: 'c/t',  
124                    controls: true,
125                    
126                    progress: true,
127                    history: true,
128                    transition: "slide",
129        
130                    plugins: [RevealNotes],
131                    width: {width},
132                    height: {height},
133                    center: true,
134                    margin: {margin},
135                        
136                    minScale: {minscale},
137                    maxScale: {maxscale},
138            }});
139              
140                var update = function(event){{
141                  if(MathJax.Hub.getAllJax(Reveal.getCurrentSlide())){{
142                    MathJax.Hub.Rerender(Reveal.getCurrentSlide());
143                  }}
144                }};
145        
146                Reveal.addEventListener('slidechanged', update);
147        
148                function setScrollingSlide() {{
149                    var scroll = false
150                    if (scroll === true) {{
151                      var h = $('.reveal').height() * 0.95;
152                      $('section.present').find('section')
153                        .filter(function() {{
154                          return $(this).height() > h;
155                        }})
156                        .css('height', 'calc(95vh)')
157                        .css('overflow-y', 'scroll')
158                        .css('margin-top', '20px');
159                    }}
160                }}
161        
162                // check and set the scrolling slide every time the slide change
163                Reveal.addEventListener('slidechanged', setScrollingSlide);
164            }}
165            );
166            </script>
167             </body>
168        </html>
169        """
170        soup = BeautifulSoup(presentation_html, "html.parser")
171        return presentation_html

Returns the presentation as an HTML string.

Args: theme (str): The name of the reveal.js theme to use (default is 'moon'). width (int): The width of the presentation (default is 960). height (int): The height of the presentation (default is 600). minscale (float): The minimum scale of the presentation (default is 0.2). maxscale (float): The maximum scale of the presentation (default is 1.5). margin (float): The margin of the presentation (default is 0.1). custom_theme (str, optional): A link to a custom theme CSS file if theme is set to 'custom'.

Returns: str: The presentation in HTML format.

Raises: ValueError: If the theme is set to 'custom' but no custom_theme link is provided.

def save_html( self, file_name, theme='moon', width=960, height=600, minscale=0.2, maxscale=1.5, margin=0.1, custom_theme=None):
173    def save_html(self, file_name, theme="moon", width=960, height=600, minscale=0.2, maxscale=1.5, margin=0.1,
174                  custom_theme=None):
175        """
176        Saves the presentation as an HTML file.
177
178        Args:
179            file_name (str): The name of the file to save the presentation as.
180            theme (str, optional): The name of the reveal.js theme to use (default is 'moon').
181            width (int, optional): The width of the presentation (default is 960).
182            height (int, optional): The height of the presentation (default is 600).
183            minscale (float, optional): The minimum scale of the presentation (default is 0.2).
184            maxscale (float, optional): The maximum scale of the presentation (default is 1.5).
185            margin (float, optional): The margin of the presentation (default is 0.1).
186            custom_theme (str, optional): A link to a custom theme CSS file if theme is set to 'custom'.
187
188        Raises:
189            ValueError: If the theme is set to 'custom' but no custom_theme link is provided.
190        """
191        if theme == "custom" and custom_theme is None:
192            raise ValueError("If the theme is set to 'custom', a URL for the custom theme must be provided.")
193
194        if custom_theme:
195            theme_link = custom_theme
196        else:
197            theme_link = theme
198
199        presentation_html = self.to_html(theme=theme_link, width=width, height=height, minscale=minscale,
200                                         maxscale=maxscale, margin=margin, custom_theme=custom_theme)
201
202        with open(file_name, "w") as f:
203            f.write(presentation_html)

Saves the presentation as an HTML file.

Args: file_name (str): The name of the file to save the presentation as. theme (str, optional): The name of the reveal.js theme to use (default is 'moon'). width (int, optional): The width of the presentation (default is 960). height (int, optional): The height of the presentation (default is 600). minscale (float, optional): The minimum scale of the presentation (default is 0.2). maxscale (float, optional): The maximum scale of the presentation (default is 1.5). margin (float, optional): The margin of the presentation (default is 0.1). custom_theme (str, optional): A link to a custom theme CSS file if theme is set to 'custom'.

Raises: ValueError: If the theme is set to 'custom' but no custom_theme link is provided.