forked from alexbfree/thesis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild.py
executable file
·338 lines (247 loc) · 12.5 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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
#!/usr/bin/env python3
import sys
import subprocess
from bs4 import BeautifulSoup
from datetime import datetime
from jinja2 import Environment, FileSystemLoader
from shutil import copy
from distutils import dir_util
import frontmatter
import glob
import argparse
WEBSITE_PATH = "./out/website"
OUT_PATH = "./out"
SRC_PATH = "./src"
# Builds the entire thesis
def buildThesis(format):
print("Building Thesis in {}".format(format))
# Output path
outputPath = "{}/{}/".format(OUT_PATH, format)
# Check for and create the folder
subprocess.run(["mkdir", "-p", outputPath])
# Create the file name now so it's easier to output to args
filename = "thesis.{}".format(format)
# define args now
args = ["pandoc", "src/index.md", "src/frontmatter.md"]
# Add chapters dynamically based on a pattern, count the chapters and them add in sequence based on number (not on filename order in the list)
for i in range(getChapterCount()):
args.append("src/chapter-{}.md".format(i+1))
# Finish the bulk of arguments
args.append("src/bibliography.md") # this always comes last after the chapters
args.extend(["-s", "--toc", "--toc-depth=3", "--self-contained", "--number-sections", "--citeproc", "--output={}{}".format(outputPath, filename)])
# Add for pdf (avoid latex pdfs)
if format == "pdf":
#args.append("-t")
#args.append("html5")
args.append("--pdf-engine=pdflatex")
#print('command is:')
#print(args)
args.append("src/appendices.md")
# Build
subprocess.run(args)
print("\tThesis built under " + outputPath+filename)
# Builds filename.md into filename.format; numberOffset may be set to change the section numbers
def buildFile(filename, format, chapterNumber=None):
print("Building {} in {}".format(filename, format))
# Define the output path where the file will be built, using the format argument and make the directory if it doesn't exist
outputPath = "{}/{}/".format(OUT_PATH, format)
subprocess.run(["mkdir", "-p", outputPath])
# Define the output filename
outputFile = "{}.{}".format(filename,format)
# Build the initial pandoc command to build the file
args = ["pandoc", "src/index.md", "src/{}.md".format(filename), "src/bibliography.md" , "--citeproc", "--output={}{}".format(outputPath,outputFile), "-s", "--toc", "--toc-depth=3", "--self-contained", "--number-sections"]
# Append the pdf args for if they try to build a PDF file
if format == "pdf":
#args.append("-t")
#args.append("html5")
args.append("--pdf-engine=pdflatex")
# Append the args for offsetting the section number (chapter number minus 1)
if not chapterNumber == None:
args.append("--number-offset={}".format(int(chapterNumber) - 1))
# Run the pandoc command
subprocess.run(args)
print("\tBuilt {}{}".format(outputPath, outputFile))
# Builds a single chapter
def buildChapter(chapterNumber, format):
# Get the filename to pass down
filename = "chapter-{}".format(chapterNumber)
# Run the buildFile command, pass down the chapterNumber to offset properly
buildFile(filename, format, chapterNumber)
# Iterates and builds all individual chapters as separate files.
def buildChapters(format):
# Add chapters dynamically based on a pattern, count the chapters and them add in sequence based on number (not on filename order in the list)
for i in range(getChapterCount()):
# print("Building Chapter %s" % str(i+1))
buildChapter(str(i+1), format)
# Builds the HTML coversheet for the thesis
def buildCoversheet(outputPath):
print("Building Coversheet")
# Load the template
env = Environment(loader=FileSystemLoader('templates'))
template = env.get_template("index.html")
# Load index.md frontmatter and parse it to get title and author info
config = frontmatter.load('./src/index.md')
thesis_title = config['title']
thesis_author = config['author']
thesis_source = config['thesis-source']
build_formats = config['website-build-formats']
download_button_format = config['download-button-format']
# Get the last updated
date = datetime.now()
last_updated = date.strftime("%A %d %B %Y at %H:%M")
# Get a list of items to include in the table row
items = []
# To find the title the best way forward is to nab the title from the HTML file as that's easier to parse than Markdown
# Open the thesis file, it's cheaper to parse the file once and nab the title in the loop
html_file = open('./out/html/thesis.html')
html_content = html_file.read()
html_file.close()
soup = BeautifulSoup(html_content, 'html.parser') # Parse it
for i in range(getChapterCount()):
chap = i+1
item = {}
item["file"] = "chapter-{}".format(chap)
if chap==1:
item["title"]="1 Introduction"
elif chap==2:
item["title"]="2 Literature Review"
elif chap==3:
item["title"]="3 Methodology"
elif chap==4:
item["title"]="4 Case Study One: Accessing and Using Civic Data in Early Help"
elif chap==5:
item["title"]="5 Case Study Two: The Human Experience of GDPR"
elif chap==6:
item["title"]="6 Discussion I: An Understanding of Human Data Relations"
elif chap==7:
item["title"]="7 Discussion II: Designing and Pursuing Better Human Data Relations"
else:
item["title"] = "Chapter {}".format(chap)
#foundh1 = soup.find("h1", id="chapter-{}".format(i+1))
#if foundh1 is not None:
# title = foundh1.contents # Nab the h1 element with the chapter title
# item["title"] = "{}{}".format(title[0]+1,title[1])
items.append(item)
#print("\tItems array is:")
#print(items)
#biblio = {}
#biblio["file"] = "bibliography"
#biblio["title"] = soup.find("h1", id="bibliography").contents[]
#items.append(biblio)
# Write the file
output = open(outputPath + "index.html", "w")
output.write(template.render(thesis_title=thesis_title, thesis_author=thesis_author,last_updated=last_updated, thesis_source=thesis_source, items=items, build_formats=build_formats, download_button_format=download_button_format))
output.close()
print("\tCoversheet built under ./out/website/index.html")
# Builds the website along with cover page
def buildWebsite():
# Check for and create the folder
subprocess.run(["mkdir", "-p", WEBSITE_PATH])
# Load the config file
config = frontmatter.load('./src/index.md')
# Copy the styles file
copy("./src/styles.css", WEBSITE_PATH)
# First build in HTML for the web, then loop over the format list and build for that
buildThesis("html")
buildChapters("html")
buildFile("frontmatter", "html")
buildFile("appendices", "html")
dir_util.copy_tree("{}/{}/".format(OUT_PATH, "html"), "{}/{}/".format(WEBSITE_PATH, "html") )
for format in config['website-build-formats']:
# Build the thesis + the individual chapters separately
buildThesis(format)
buildChapters(format)
buildFile("frontmatter", format)
buildFile("appendices", format)
# Move the new files over to the website directory
dir_util.copy_tree("{}/{}/".format(OUT_PATH, format), "{}/{}/".format(WEBSITE_PATH, format) )
# Generate cover sheet
buildCoversheet("{}/".format(WEBSITE_PATH))
# Builds the website HtmlOnly along with cover page
def buildWebsiteHtmlOnly():
# Check for and create the folder
subprocess.run(["mkdir", "-p", WEBSITE_PATH])
# Load the config file
config = frontmatter.load('./src/index.md')
# Copy the styles file
copy("./src/styles.css", WEBSITE_PATH)
# First build in HTML for the web, then loop over the format list and build for that
buildThesis("html")
buildChapters("html")
buildFile("frontmatter", "html")
buildFile("appendices", "html")
dir_util.copy_tree("{}/{}/".format(OUT_PATH, "html"), "{}/{}/".format(WEBSITE_PATH, "html") )
# Generate cover sheet
buildCoversheet("{}/".format(WEBSITE_PATH))
# Returns a count of all chapters, used in loops to manipulate chapters dynamically
def getChapterCount():
pattern = "chapter-[0-9]*.md"
return len(glob.glob("{}/{}".format(SRC_PATH, pattern)))
# deploy it to github pages
#print("\nStashing any changes so we don't commit them...");
#subprocess.run(["git","stash"]);
#print("\nAuto-deploying to github pages...")
#subprocess.run(["git","add","out/website/html/*.*"]);
#subprocess.run(["git","add","out/website/odt/*.*"]);
#subprocess.run(["git","add","out/website/docx/*.*"]);
#subprocess.run(["git","add","out/website/*.*"]);
#subprocess.run(["git","commit","-m","Auto-deploying website to github pages"]);
#subprocess.run(["git","subtree","push","--prefix","out/website","origin","gh-pages"]);
#print("\nUnstashing any changes we stashed before commit...");
#subprocess.run(["git","stash","pop"]);
# Main function to check arguments
def main(argv):
# Define a top level parser for commands
parser = argparse.ArgumentParser(description="Markdown Thesis: Write your thesis in markdown and manage conversions into other formats")
# The command line options differ for each command so we create subparsers for each
subparsers = parser.add_subparsers(dest="subparser",help="Sub-command help")
# Parser for building individual chapters
chapter_parser = subparsers.add_parser("chapter", help="Builds an individual chapter in [format]")
chapter_parser.add_argument("chapter_number", type=int, help="The number of the chapter you want to build")
chapter_parser.add_argument("format", type=str, help="The format you want to build into e.g. html or docx")
# Parser for building the frontmatter
frontmatter_parser = subparsers.add_parser("frontmatter", help="Builds only frontmatter.md in [format]")
frontmatter_parser.add_argument("format", type=str, help="The format you want to build into e.g. html or docx")
# Parser for building the entire thesis or all chapters simultaneously
thesis_parser = subparsers.add_parser("thesis", help="Builds the entire thesis in an appropriate format")
thesis_parser.add_argument("format", type=str, help="The format you want to build into e.g. html or docx")
# Parser for building all chapters at once
chapters_parser = subparsers.add_parser("chapters", help="Builds all chapters in [format]")
chapters_parser.add_argument("format", type=str, help="The format you want to build into e.g. html or docx")
# Parser for building the appendices
appendices_parser = subparsers.add_parser("appendices", help="Builds only appendices.md in [format]")
appendices_parser.add_argument("format", type=str, help="The format you want to build into e.g. html or docx")
# Parser for building an entire website
website_parser = subparsers.add_parser("website", help="Generates a website including a frontpage and html, docx, epub and pdf versions of each chapter and entire thesis")
# Parser for building an entire website, html only
website_html_onlyparser = subparsers.add_parser("htmlwebsite", help="Generates a website in HTML only including a frontpage and html versions of each chapter and entire thesis")
# Run
args = parser.parse_args()
markdown_thesis(args)
# Takes the result of args and passes it down to the relevant function
def markdown_thesis(args):
if args.subparser == "thesis":
print("Building Thesis in {}\n======\n".format(args.format))
buildThesis(args.format)
elif args.subparser == "chapters":
print("Building all chapters in {}\n======\n".format(args.format))
buildChapters(args.format)
elif args.subparser == "website":
print ("Building website \n======\n")
buildWebsite()
elif args.subparser == "htmlwebsite":
print ("Building website (HTML only) \n======\n")
buildWebsiteHtmlOnly()
elif args.subparser == "chapter":
print("Building Chapter in {}\n======\n".format(args.format))
buildChapter(args.chapter_number, args.format)
elif args.subparser == "frontmatter":
print("Building frontmatter in {}\n======\n".format(args.format))
# buildFrontmatter(args.format)
buildFile("frontmatter", args.format)
elif args.subparser == "appendices":
print("Building appendices in {}\n======\n".format(args.format))
# buildFrontmatter(args.format)
buildFile("appendices", args.format)
main(sys.argv)
print("\n=====\nEnd")