83 lines
3.0 KiB
Python
Executable File
83 lines
3.0 KiB
Python
Executable File
import os
|
|
import pypandoc
|
|
import re
|
|
|
|
root = ""
|
|
|
|
# Compiles a single slide by splitting it up into single metadata and data
|
|
# attributes, loading them into the corresponding template, and returning the
|
|
# result.
|
|
def compile_slide(slide, root_directory):
|
|
global root
|
|
root = root_directory
|
|
slide = slide.strip()
|
|
slide_metadata = get_slide_metadata(slide)
|
|
slide_data = get_slide_data(slide)
|
|
slide = get_slide_layout(slide_metadata['layout'])
|
|
|
|
if 'todo' in slide_data.keys():
|
|
# TODO: Move the css into a global onpoint.css file
|
|
slide = '<aside class="todo" style="position:absolute; z-index:100; display:block; background:rgba(255,0,0,.8); top:0; right:0; max-width:20%; margin:.5em; padding:.5em; border-radius:1em; font-family:sans-serif; font-size: .8em;">@todo</aside>' + slide
|
|
|
|
for key, value in slide_data.items():
|
|
placeholder = '@' + key
|
|
filler = convert_slide_content(value)
|
|
|
|
# very unelegant attempt at inline elements
|
|
inline_key = '@' + key + '(inline)'
|
|
if inline_key in slide:
|
|
filler_without_outer_paragraph = re.sub(r"<p>(.+)</p>", r"\1", filler, flags=re.DOTALL).strip()
|
|
slide = slide.replace(
|
|
inline_key,
|
|
filler_without_outer_paragraph
|
|
)
|
|
|
|
elif '@' + key in slide:
|
|
slide = slide.replace(placeholder, filler)
|
|
|
|
|
|
return slide
|
|
|
|
# Parses the metadata passage of a given slide and returns the metadata as a
|
|
# dictionary. For some items, default values are used if the slide does not
|
|
# contain them.
|
|
def get_slide_metadata(slide):
|
|
metadata = { 'layout': 'default' }
|
|
metadata_attributes = re.search('^@slide\((.+)\)', slide.splitlines()[0])
|
|
if metadata_attributes:
|
|
metadata_attributes = metadata_attributes.group(1).split(' ')
|
|
for attribute in metadata_attributes:
|
|
metadata[attribute.split('=')[0]] = attribute.split('=')[1]
|
|
return metadata
|
|
|
|
# Parses the data part of a given slide and returns dictionary of field names
|
|
# and corresponding raw values.
|
|
def get_slide_data(slide):
|
|
if slide.startswith('@slide'):
|
|
slide = slide[slide.find('\n')+1:] # cut off @slide declaration
|
|
slide_data = slide.strip().split('\n\n@')
|
|
slide_data = { item.split()[0].strip('@') : "\n".join(item.splitlines()[1:]) for item in slide_data }
|
|
return slide_data
|
|
|
|
# Reads the layout file for a given layout name and returns its content as a
|
|
# string.
|
|
def get_slide_layout(layout_name):
|
|
global root
|
|
try:
|
|
return open(os.path.join(root, 'layouts/' + layout_name + '.html'), 'r', encoding='utf8').read()
|
|
except FileNotFoundError:
|
|
raise Exception('Layout ' + layout_name + ' not found!')
|
|
|
|
# Calls the pandoc converter to convert a given Markdown string to HTML.
|
|
# Returns an HTML string.
|
|
def convert_slide_content(content):
|
|
filters = []
|
|
pdoc_args = [
|
|
'--mathjax' # Preparing formulas
|
|
]
|
|
return pypandoc.convert_text(
|
|
content, 'html',
|
|
format='md',
|
|
extra_args=pdoc_args,
|
|
filters=filters)
|