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