fastdeck
Fastdeck
|
|
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:
- Import the necessary classes:
from fastdeck import Presentation, Slide, Content
- Create a presentation:
presentation = Presentation()
- 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()])
- Add the slide to the presentation:
presentation.add_slide(slide)
- 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
- Reveal.js
- This python package is inspired by the respysive-slide wrapper.
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
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.