diff --git a/chapters.py b/chapters.py new file mode 100644 index 0000000..fbbba45 --- /dev/null +++ b/chapters.py @@ -0,0 +1,38 @@ +import os + +import helper +import slides as slides_helper + +root = "" +lang = "" + +# Compiles a presentation's chapters (the content without the wrapper) +# according to slides.yml and returns them as one string of
s. +def compile_chapters(root_directory, language): + global root + root = root_directory + + global lang + lang = language + + structure = helper.read_yaml(root, 'slides.yml') + chapters = "" + for chapter in structure: + chapters += '
\n' + compile_chapter(chapter) + '\n
' + return chapters # string + +# Compiles a presentation's chapter (given its name) by splitting it into +# slides, compiling those, and returning them as a string of
s. +def compile_chapter(chapter): + global root + if type(chapter) != str: + raise Exception('Chapters with attributes are not supported yet.\n' + + str(chapter)) + chapter_file = open(os.path.join(root, 'slides/' + chapter + '.' + lang + '.md'), 'r') + delimiter = '\n@slide' + chapter_input = ('\n' + chapter_file.read()).split(delimiter) + slides = [delimiter + slide for slide in chapter_input][1:] + chapter = '' + for slide in slides: + chapter += '
\n' + slides_helper.compile_slide(slide, root) + '\n
\n' + return chapter \ No newline at end of file diff --git a/helper.py b/helper.py new file mode 100644 index 0000000..f708630 --- /dev/null +++ b/helper.py @@ -0,0 +1,27 @@ +import yaml +import os + +# Calls a YAML parser for the given relative path inside the presentation root +# directory. Returns a dictionary with the YAML content. +def read_yaml(root, path): + with open(os.path.join(root, path), 'r') as stream: + try: + return yaml.safe_load(stream) + except yaml.YAMLError as exc: + print(exc) + +# Retrieve the available languages as stated in the meta.yml (key: language). +def get_available_languages(root): + return read_yaml(root, 'meta.yml')['language'] + +# Replaces the placeholders in the given content with corresponding values in +# the given language from the meta.yml and returns the filled content. +def insert_metadata(content, root, lang): + metadata = read_yaml(root, 'meta.yml') + for key, value in metadata.items(): + placeholder = '@' + key + filler = value[lang] + # print('replace', placeholder, 'with', filler) + if '@' + key in content: + content = content.replace(placeholder, filler) + return content \ No newline at end of file diff --git a/main.py b/main.py index 402ec83..c84b9f9 100644 --- a/main.py +++ b/main.py @@ -2,142 +2,23 @@ import argparse import os -import pypandoc -import re import sys -import yaml -import fragments -root = "" -lang = "de" +import chapters +import fragments +import helper # Compiles a presentation in the given language from the given directory and # stores it in a corresponding slides.lang.html file inside the same directory. -def compile(directory, language='en'): - global root - root = directory - global lang - lang = language +def compile(root, language='en'): wrapper = open(os.path.join(root, 'layouts/root.html'), 'r').read() - wrapper = wrapper.replace('@slides', compile_chapters()) - wrapper = insert_metadata(wrapper, lang=lang) + wrapper = wrapper.replace('@slides', chapters.compile_chapters(root, language)) + wrapper = helper.insert_metadata(wrapper, root, language) wrapper = fragments.defragmentize(wrapper) - with open(os.path.join(root, 'slides.' + lang + '.html'), 'w+') as output: + with open(os.path.join(root, 'slides.' + language + '.html'), 'w+') as output: output.write(wrapper) print('done') -# Replaces the placeholders in the given content with corresponding values in -# the given language from the meta.yml and returns the filled content. -def insert_metadata(content, lang=None): - metadata = read_yaml('meta.yml') - for key, value in metadata.items(): - placeholder = '@' + key - filler = value[lang] - # print('replace', placeholder, 'with', filler) - if '@' + key in content: - content = content.replace(placeholder, filler) - return content - -# Compiles a presentation's chapters (the content without the wrapper) -# according to slides.yml and returns them as one string of
s. -def compile_chapters(): - structure = read_yaml('slides.yml') - chapters = "" - for chapter in structure: - chapters += '
\n' + compile_chapter(chapter) + '\n
' - return chapters # string - -# Compiles a presentation's chapter (given its name) by splitting it into -# slides, compiling those, and returning them as a string of
s. -def compile_chapter(chapter): - global root - if type(chapter) != str: - raise Exception('Chapters with attributes are not supported yet.\n' + - str(chapter)) - chapter_file = open(os.path.join(root, 'slides/' + chapter + '.' + lang + '.md'), 'r') - delimiter = '\n@slide' - chapter_input = ('\n' + chapter_file.read()).split(delimiter) - slides = [delimiter + slide for slide in chapter_input][1:] - chapter = '' - for slide in slides: - chapter += '
\n' + compile_slide(slide) + '\n
\n' - return chapter - -# 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): - slide = slide.strip() - slide_metadata = get_slide_metadata(slide) - slide_data = get_slide_data(slide) - slide = get_slide_layout(slide_metadata['layout']) - for key, value in slide_data.items(): - placeholder = '@' + key - filler = convert_slide_content(value) - # print('replace', placeholder, 'with', filler) - if '@' + key in slide: - slide = slide.replace(placeholder, filler) - # very unelegant attempt at inline elements - slide = re.sub(r"

(.+?)

\n\(inline\)", r"\1", slide) - 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').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) - -# Calls a YAML parser for the given relative path inside the presentation root -# directory. Returns a dictionary with the YAML content. -def read_yaml(path): - global root - with open(os.path.join(root, path), 'r') as stream: - try: - return yaml.safe_load(stream) - except yaml.YAMLError as exc: - print(exc) - -# Retrieve the available languages as stated in the meta.yml (key: language). -def get_available_languages(root): - return read_yaml(os.path.join(root, 'meta.yml'))['language'] - if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument("rootdirectory", help="your project's root directory") @@ -146,7 +27,7 @@ if __name__ == '__main__': args = parser.parse_args() if args.language == "all": - for language in get_available_languages(args.rootdirectory): + for language in helper.get_available_languages(args.rootdirectory): compile(args.rootdirectory, language=language) else: compile(args.rootdirectory, language=args.language) diff --git a/slides.py b/slides.py new file mode 100644 index 0000000..521d830 --- /dev/null +++ b/slides.py @@ -0,0 +1,68 @@ +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']) + for key, value in slide_data.items(): + placeholder = '@' + key + filler = convert_slide_content(value) + # print('replace', placeholder, 'with', filler) + if '@' + key in slide: + slide = slide.replace(placeholder, filler) + # very unelegant attempt at inline elements + slide = re.sub(r"

(.+?)

\n\(inline\)", r"\1", slide) + 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').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) \ No newline at end of file