-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathbuild.py
166 lines (119 loc) · 4.24 KB
/
build.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
This script builds the presentation by filling the boilerplate with content
"""
import codecs
import configparser
import glob
import re
from itertools import zip_longest
from math import ceil
IGNORED_DOCS = [
"CHANGELOG.md",
"README.md",
"README-remarkjs.md",
"handout.md",
"labs.md"
]
"""
IGNORED_DOCS: documents that will never be imported
"""
SLIDE_DIVIDER = '\n---\n'
POINTS_PER_AGENDA_SLIDE = 9
AGENDA_TEMPLATE = """
# Agenda {counter}
{points}
"""
def main():
"""
Main function, starts the logic based on parameters.
"""
config = read_config('settings.ini')
slides = render_slides(read_slides(), config)
template = read_template('template.html')
rendered_template = render_metadata(template, config)
rendered_template = rendered_template.replace('{{ content }}', slides)
write_file("presentation.html", rendered_template)
def read_config(filename):
config = configparser.ConfigParser()
config.read(filename, encoding='utf-8')
return config
def read_template(filename):
with open(filename) as file_:
return file_.read()
def read_slides():
slides = []
for file in sorted(glob.iglob("*.md")):
if file not in IGNORED_DOCS:
with open(file, 'r', encoding="utf-8") as slide_file:
content = slide_file.read()
slides.extend(
[slide.strip() for slide in content.split(SLIDE_DIVIDER)]
)
if not slides:
raise RuntimeError("No slides loaded. "
"Please add some slides or adjust IGNORED_DOCS.")
return slides
def render_slides(slides, config):
agenda = create_agenda(slides)
print("On our agenda: {}".format(', '.join(agenda)))
rendered_agenda = render_agenda(agenda)
combined_slides = SLIDE_DIVIDER.join(slides)
rendered_slides = render_metadata(combined_slides, config)
rendered_slides = rendered_slides.replace('{{ agenda }}', rendered_agenda)
return rendered_slides
def create_agenda(slides):
agenda = []
for slide in slides[1:]: # ignore title slide
title = get_title(slide)
if not title:
continue
if title not in agenda:
agenda.append(title)
return agenda
def get_title(slide):
match = re.match(r'^(class: .*\n+){0,1}#\s+(?P<title>.*)$', slide, flags=re.MULTILINE)
if match:
title = match.group('title').strip()
return title
def render_agenda(agenda):
if not agenda:
# Avoid having an empty slide.
return ("Unable to detect agenda. "
"Please add at least one first-level heading (`# Title`) "
"or remove the `{{ agenda }}` tag from your slides.")
slide_count = ceil(len(agenda) / POINTS_PER_AGENDA_SLIDE)
filled_agenda = []
for index, agenda_points in enumerate(chunks(agenda, POINTS_PER_AGENDA_SLIDE)):
if slide_count < 2:
count = ''
else:
count = '{index}/{count}'.format(index=index + 1,
count=slide_count)
topics = ['- %s' % t for t in agenda_points if t is not None]
points = '\n'.join(topics)
filled_agenda.append(AGENDA_TEMPLATE.format(counter=count,
points=points))
return SLIDE_DIVIDER.join(filled_agenda)
def chunks(iterable, count):
"Collect data into fixed-length chunks or blocks"
# chunks('ABCDEFG', 3) --> ABC DEF Gxx"
args = [iter(iterable)] * count
return zip_longest(*args)
def render_metadata(slides, metadata):
rendered = slides.replace('{{ title }}', metadata['meta']['title'])
customer = metadata['meta'].get('customer', '')
rendered = rendered.replace('{{ customer }}', customer)
rendered = rendered.replace('{{ ratio }}', metadata['layout']['ratio'])
if customer:
slideFormat = f"%current% | %total% - KOPIE: {customer}"
else:
slideFormat = "%current% | %total%"
rendered = rendered.replace('{{ slideNumberFormat }}', slideFormat)
return rendered
def write_file(filename, content):
with codecs.open(filename, "w", "utf-8") as file_:
file_.write(content)
if __name__ == "__main__":
main()