A mirror of my website's source code.

By using this site, you agree to have cookies stored on your device, strictly for functional purposes, such as storing your session and preferences.

Dismiss

 build.py

View raw Download
text/x-script.python • 10.59 kiB
Python script, Unicode text, UTF-8 text executable
        
            
1
from Renderers import RenderTemplate, RenderMarkdown
2
from sys import argv
3
from shutil import rmtree as DeleteDirectory
4
from os import mkdir as CreateDirectory, listdir as ListDirectory, unlink as DeleteFile
5
from os.path import isfile as IsFile, exists as PathExists
6
from distutils.dir_util import copy_tree as CopyDirectory
7
from datetime import datetime
8
from json import dump as DumpJSON
9
from yaml import safe_load as LoadYML
10
from re import sub as RegReplace
11
from typing import Literal
12
13
DEPLOY_BUILD_DIR = {
14
"gh-pages-deploy": "build",
15
"gl-pages-deploy": "public",
16
"cb-pages": "build",
17
} # Separate because this site is built with an action that won't work if they aren't
18
LOCAL_BUILD_DIR = "build"
19
20
PAGES_DEPLOY = argv[1] if len(argv) > 1 else None
21
BUILD_DIRECTORY = DEPLOY_BUILD_DIR[PAGES_DEPLOY] if PAGES_DEPLOY is not None else LOCAL_BUILD_DIR
22
23
PAGES = {
24
"index.html": "index.html",
25
"blog-list.html": "blog/index.html",
26
"blog-feed.rss": "blog/feed.rss",
27
"blog-feed.atom": "blog/feed.atom",
28
"404.html": "404.html",
29
"404.html": "not_found.html",
30
}
31
32
DISALLOWED_SITEMAP = {
33
"404.html",
34
"blog-feed.rss",
35
"blog-feed.atom",
36
"blog-list.html",
37
"index.html",
38
"not_found.html",
39
}
40
41
REDIRECTS = {
42
"link-tree.html": "list/link-tree.html", # Old location -> new location
43
}
44
45
SITEMAP_HREF = "https://steve0greatness.github.io/"
46
sitemap = [
47
SITEMAP_HREF + "blog/",
48
SITEMAP_HREF,
49
]
50
51
def EscapeHTMLForRSS(HTML: str) -> str:
52
values = {
53
"&": "&", # this is here for a reason, do not change order.
54
"<": "&lt;",
55
">": "&gt;",
56
"§": "&#xa7;",
57
}
58
RssHtml = HTML
59
for old, new in values.items():
60
RssHtml = RssHtml.replace(old, new)
61
return RssHtml
62
63
def WipeFinalDir():
64
if not PathExists(BUILD_DIRECTORY):
65
print("Directory didn't existing, creating it...")
66
CreateDirectory(BUILD_DIRECTORY)
67
return
68
print("Directory exists, wiping it...")
69
for item in ListDirectory(BUILD_DIRECTORY):
70
path = BUILD_DIRECTORY + "/" + item
71
if IsFile(path):
72
DeleteFile(path)
73
continue
74
DeleteDirectory(path)
75
76
def PostDateToDateObj(Date):
77
return datetime.strptime(Date, "%Y %b %d")
78
79
def PostSortHelper(Post):
80
return PostDateToDateObj(Post["date"])
81
82
def GetBlogList():
83
print("Grabbing post list")
84
PostSlugs: tuple[tuple[Literal["blog-posts", "drafts"], str], ...] = tuple( ("blog-posts", file) for file in ListDirectory("blog-posts") )
85
if not PAGES_DEPLOY and PathExists("drafts"):
86
PostSlugs = PostSlugs + tuple( ("drafts", file) for file in ListDirectory("drafts") )
87
Posts = []
88
for dir, slug in PostSlugs:
89
if not slug.endswith(".md"):
90
continue
91
print("Grabbing post list blog-posts/%s" % (slug))
92
with open(dir + "/" + slug, encoding="utf-8") as MDFile:
93
RawMD = MDFile.read()
94
PostHTML = RenderMarkdown(RawMD)
95
Item = PostHTML.metadata
96
Item["content"] = PostHTML
97
Item["raw-content"] = RawMD
98
Item["rss-content"] = EscapeHTMLForRSS(PostHTML)
99
Item["rss-post-time"] = PostDateToDateObj(Item["date"]).strftime("%a, %d %b %Y") + " 00:00:00 GMT"
100
Item["atom-post-time"] = PostDateToDateObj(Item["date"]).strftime("%Y-%m-%d") + "T00:00:00Z"
101
Item["opengraph-date"] = PostDateToDateObj(Item["date"]).strftime("%Y-%m-%d")
102
Item["opengraph-update"] = Item["opengraph-date"]
103
Item["atom-update-time"] = Item["atom-post-time"]
104
if "updated" in Item:
105
Item["atom-update-time"] = PostDateToDateObj(Item["updated"]).strftime("%Y-%m-%d") + "T00:00:00Z"
106
Item["opengraph-update"] = PostDateToDateObj(Item["updated"]).strftime("%Y-%m-%d")
107
Item["pathname"] = slug.replace(".md", ".html")
108
Item["plaintext"] = slug.replace(".md", ".txt")
109
Item["origin"] = slug
110
Item["is-draft"] = dir == "drafts"
111
Posts.append(Item)
112
PostsByDate = sorted(Posts, key=PostSortHelper, reverse=True)
113
return PostsByDate
114
115
PostList = []
116
117
118
def ListParseCategory(Obj, depth):
119
html = "<h%d id=\"%s\">%s</h%d>" % (2+depth, Obj["id"], Obj["title"], 2+depth)
120
if "paragraph" in Obj:
121
html += "<p>%s</p>" % Obj["paragraph"]
122
listType = "ul"
123
if "list-type" in Obj and Obj["list-type"] == "ordered":
124
listType = "ol"
125
html += "<%s>" % listType
126
for item in Obj["list"]:
127
html += "<li>" + LIST_PARSER_DICT[item["type"]](item, depth + 1) + "</li>"
128
html += "</%s>" % listType
129
return html
130
131
def ListParseLink(Obj, depth):
132
html = "<a href=\"%s\">" % Obj["href"]
133
text = Obj["text"]
134
if "text-type" in Obj and Obj["text-type"] == "text/markdown":
135
text = RenderMarkdown(text).replace("<p>", "").replace("</p>", "")
136
html += text + "</a>"
137
if "comment" in Obj:
138
html += "(%s)" % Obj["comment"]
139
return html
140
141
def ListParseText(Obj, depth):
142
text = Obj["text"]
143
# if "text-type" in Obj and Obj["text-type"] == "text/markdown":
144
# print(RenderMarkdown(text))
145
# text = RenderMarkdown(text) # this doesn't work???
146
if "comment" in Obj:
147
text += "(%s)" % Obj["comment"]
148
return text
149
150
LIST_PARSER_DICT = {
151
"category": ListParseCategory,
152
"link": ListParseLink,
153
"text": ListParseText,
154
}
155
156
def GetLists():
157
ListSlugs = ListDirectory("lists")
158
Lists = []
159
for slug in ListSlugs:
160
List = {
161
"title": "",
162
"content": "",
163
"filename": slug
164
}
165
with open("lists/" + slug, encoding="utf-8") as ListYML:
166
ListDict = LoadYML(ListYML.read())
167
List["title"] = ListDict["title"]
168
if "paragraph" in ListDict:
169
List["content"] += "<p>%s</p>" % ListDict["paragraph"]
170
List["content"] += "<ul>"
171
for item in ListDict["list"]:
172
List["content"] += "<li>" + LIST_PARSER_DICT[item["type"]](item, 0) + "</li>"
173
List["content"] += "</ul>"
174
Lists.append(List)
175
sitemap.append(SITEMAP_HREF + "list/" + slug)
176
sitemap.append(SITEMAP_HREF + "list/")
177
return Lists
178
179
def RenderPosts():
180
global PostList
181
for post in PostList:
182
Revised = post["updated"] if "updated" in post else False
183
RenderedHTML = RenderTemplate(
184
"blog-post.html",
185
Revised=Revised,
186
Title=post["title"],
187
PostDate=post["date"],
188
Content=post["content"],
189
PostPath=post["pathname"],
190
PlaintextPath=post["plaintext"],
191
IsDraft=post["is-draft"],
192
OpenGraphDate=post["opengraph-date"],
193
post=post
194
)
195
print("Building blog-posts/%s to %s/blog/%s" % (post["origin"], BUILD_DIRECTORY, post["pathname"]))
196
with open(BUILD_DIRECTORY + "/blog/" + post["pathname"], "w", encoding="utf-8") as PostHTMLFile:
197
PostHTMLFile.write(RenderedHTML)
198
print("Copying blog-posts/%s to %s/blog/%s" % (post["origin"], BUILD_DIRECTORY, post["plaintext"]))
199
with open(BUILD_DIRECTORY + "/blog/" + post["plaintext"], "w", encoding="utf-8") as PostHTMLFile:
200
PostHTMLFile.write(post["raw-content"])
201
sitemap.append(SITEMAP_HREF + "blog/" + post["pathname"])
202
203
def RenderPage(PageInput: str, ContentDest: str, AllowSitemap: bool = True, **kwargs):
204
print("Building views/%s to %s/%s" % (PageInput, BUILD_DIRECTORY, ContentDest))
205
if AllowSitemap:
206
sitemap.append(SITEMAP_HREF + ContentDest)
207
with open(BUILD_DIRECTORY + "/" + ContentDest, "w", encoding="utf-8") as DestLocation:
208
DestLocation.write(RenderTemplate(PageInput, **kwargs))
209
210
def CreateJSONFeed():
211
global PostList
212
CreatedJSON = {
213
"version": "https://jsonfeed.org/version/1",
214
"title": "Steve0Greatness' Blog",
215
"home_page_url": "https://steve0greatness.github.io",
216
"feed_url": "https://steve0greatness.github.io/blog/feed.rss",
217
"language": "en-US",
218
"favicon": "https://steve0greatness.github.io/favicon.ico",
219
"description": "A blog by a human being.",
220
"authors": [
221
{
222
"name": "Steve0Greatness",
223
"url": "https://steve0greatness.github.io"
224
}
225
],
226
"items": []
227
}
228
for post in PostList:
229
CreatedJSON["items"].append({
230
"id": "https://steve0greatness.github.io/blog/" + post["pathname"],
231
"title": "JSON Feed version 1.1",
232
"icon": "https://steve0greatness.github.io/favicon.ico",
233
"content_html": post["content"],
234
"date_published": post["atom-post-time"],
235
"date_modified": post["atom-update-time"],
236
"url": "https://steve0greatness.github.io/blog/" + post["pathname"]
237
})
238
with open(BUILD_DIRECTORY + "/blog/feed.json", "w") as JSONFeedFile:
239
DumpJSON(CreatedJSON, JSONFeedFile)
240
241
def RenderLists():
242
Lists = GetLists()
243
CreateDirectory(BUILD_DIRECTORY + "/list/")
244
ListIndex = "<ul>"
245
for List in Lists:
246
FileLocation = "/list/" + List["filename"].replace(".yml", ".html")
247
Title = List["title"]
248
print("%s -> %s" % ("lists/" + List["filename"], BUILD_DIRECTORY + FileLocation))
249
with open(BUILD_DIRECTORY + FileLocation, "w") as file:
250
file.write(RenderTemplate("list.html", Content=List["content"], Title=Title, Location=FileLocation))
251
ListIndex += "<li><a href=\"%s\">%s</a></li>" % (FileLocation, Title)
252
ListIndex += "</ul>"
253
print("Building list index")
254
with open(BUILD_DIRECTORY + "/list/index.html", "w") as file:
255
file.write(RenderTemplate("list-index.html", Content=ListIndex))
256
257
def main():
258
global PostList
259
PostList = GetBlogList()
260
print("Wiping directory")
261
WipeFinalDir()
262
print("Creating blog holder")
263
CreateDirectory(BUILD_DIRECTORY + "/blog")
264
print("Rendering posts")
265
RenderPosts()
266
CreateJSONFeed()
267
print("Copying static directory")
268
CopyDirectory("static", BUILD_DIRECTORY)
269
print("Creating lists")
270
RenderLists()
271
272
print("Building pages")
273
for file, path in PAGES.items():
274
AllowSitemap = file not in DISALLOWED_SITEMAP
275
RenderPage(file, path, AllowSitemap, PostList=PostList)
276
277
print("Building redirects")
278
for OldLocation, NewLocation in REDIRECTS.items():
279
RenderPage("redirect.html", OldLocation, False, redirect=NewLocation, old=OldLocation)
280
281
with open(BUILD_DIRECTORY + "/sitemap.txt", "w") as SitemapFile:
282
SitemapFile.write("\n".join(sitemap))
283
284
if __name__ == "__main__":
285
main()
286
287