A mirror of my website's source code.

Important information: Google announced that, from September 2026, Android devices will require ALL apps to be signed by Google, effectively leading to an iOS situation. Value your right to a computer that does what you want; do not tolerate this monopolistic practice! Contact me if you don't understand why it is bad. Click to learn more.

 build.py

View raw Download
text/x-script.python • 7.69 kiB
Python script, ASCII 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
11
GITHUB_BUILD_DIR = "docs" # Separate because this site is built with an action that won't work if they aren't
12
LOCAL_BUILD_DIR = "build"
13
14
BUILD_DIRECTORY = GITHUB_BUILD_DIR if len(argv) > 1 and argv[1] == "gh-pages-deploy" else LOCAL_BUILD_DIR
15
16
PAGES = {
17
"index.html": "index.html",
18
"blog-list.html": "blog/index.html",
19
"blog-feed.rss": "blog/feed.rss",
20
"blog-feed.atom": "blog/feed.atom",
21
"link-tree.html": "link-tree.html",
22
"404.html": "404.html"
23
}
24
25
DISALLOWED_SITEMAP = [
26
"404.html",
27
"blog-feed.rss"
28
]
29
30
SITEMAP_HREF = "https://steve0greatness.github.io/"
31
sitemap = []
32
33
def WipeFinalDir():
34
if not PathExists(BUILD_DIRECTORY):
35
print("Directory didn't existing, creating it...")
36
CreateDirectory(BUILD_DIRECTORY)
37
return
38
print("Directory exists, wiping it...")
39
for item in ListDirectory(BUILD_DIRECTORY):
40
path = BUILD_DIRECTORY + "/" + item
41
if IsFile(path):
42
DeleteFile(path)
43
continue
44
DeleteDirectory(path)
45
46
def PostSortHelper(Post):
47
return datetime.strptime(Post["date"], "%Y %b %d")
48
49
def GetBlogList():
50
print("Grabbing post list")
51
PostSlugs = ListDirectory("blog-posts")
52
Posts = []
53
for slug in PostSlugs:
54
print("Grabbing post list blog-posts/%s" % (slug))
55
with open("blog-posts/" + slug, encoding="utf-8") as MDFile:
56
PostHTML = RenderMarkdown(MDFile.read())
57
Item = PostHTML.metadata
58
Item["content"] = PostHTML
59
Item["pathname"] = slug.replace(".md", ".html")
60
Posts.append(Item)
61
PostsByDate = sorted(Posts, key=PostSortHelper, reverse=True)
62
return PostsByDate
63
64
PostList = GetBlogList()
65
66
def ListParseCategory(Obj):
67
html = "<h1 id=\"%s\">%s</h1>" % (Obj["id"], Obj["title"])
68
if "paragraph" in Obj:
69
html += "<p>%s</p>" % Obj["paragraph"]
70
listType = "ul"
71
if "list-type" in Obj and Obj["list-type"] == "ordered":
72
listType = "ol"
73
html += "<%s>" % listType
74
for item in Obj["list"]:
75
html += "<li>" + LIST_PARSER_DICT[item["type"]](item) + "</li>"
76
html += "</%s>" % listType
77
return html
78
79
def ListParseLink(Obj):
80
html = "<a href=\"%s\">" % Obj["href"]
81
text = Obj["text"]
82
if "text-type" in Obj and Obj["text-type"] == "text/markdown":
83
text = RenderMarkdown(text).replace("<p>", "").replace("</p>", "")
84
html += text + "</a>"
85
if "comment" in Obj:
86
html += "(%s)" % Obj["comment"]
87
return html
88
89
def ListParseText(Obj):
90
text = Obj["text"]
91
# if "text-type" in Obj and Obj["text-type"] == "text/markdown":
92
# print(RenderMarkdown(text))
93
# text = RenderMarkdown(text) # this doesn't work???
94
if "comment" in Obj:
95
text += "(%s)" % Obj["comment"]
96
return text
97
98
LIST_PARSER_DICT = {
99
"category": ListParseCategory,
100
"link": ListParseLink,
101
"text": ListParseText,
102
}
103
104
def GetLists():
105
ListSlugs = ListDirectory("lists")
106
Lists = []
107
for slug in ListSlugs:
108
List = {
109
"title": "",
110
"content": "",
111
"filename": slug
112
}
113
with open("lists/" + slug) as ListYML:
114
ListDict = LoadYML(ListYML.read())
115
List["title"] = ListDict["title"]
116
if "paragraph" in ListDict:
117
List["content"] += "<p>%s</p>" % ListDict["paragraph"]
118
for item in ListDict["list"]:
119
List["content"] += LIST_PARSER_DICT[item["type"]](item)
120
Lists.append(List)
121
return Lists
122
123
def RenderPosts():
124
for post in ListDirectory("blog-posts"):
125
path = "blog-posts/" + post
126
RenderedHTML: str
127
PostMD: str
128
PostPath = post.replace(".md", ".html")
129
PlaintextPath = post.replace(".md", ".txt")
130
with open(path, "r", encoding="utf-8") as PostContent:
131
PostMD = PostContent.read()
132
PostHTML = RenderMarkdown(PostMD)
133
Title = PostHTML.metadata["title"]
134
PostDate = PostHTML.metadata["date"]
135
Revised = False
136
if "updated" in PostHTML.metadata:
137
Revised = PostHTML.metadata["updated"]
138
RenderedHTML = RenderTemplate("blog-post.html", Revised=Revised, Title=Title, PostDate=PostDate, Content=PostHTML, PostPath=PostPath, PlaintextPath=PlaintextPath)
139
print("Building blog/%s to %s/blog/%s" % (post, BUILD_DIRECTORY, PostPath))
140
with open(BUILD_DIRECTORY + "/blog/" + PostPath, "w", encoding="utf-8") as PostHTMLFile:
141
PostHTMLFile.write(RenderedHTML)
142
print("Copying blog/%s to %s/blog/%s" % (post, BUILD_DIRECTORY, PlaintextPath))
143
with open(BUILD_DIRECTORY + "/blog/" + PlaintextPath, "w", encoding="utf-8") as PostPlaintext:
144
PostPlaintext.write(PostMD)
145
sitemap.append(SITEMAP_HREF + "/blog/" + PostPath)
146
147
def RenderPage(PageInput: str, ContentDest: str, AllowSitemap: bool = True, **kwargs):
148
print("Building views/%s to %s/%s" % (PageInput, BUILD_DIRECTORY, ContentDest))
149
if AllowSitemap:
150
sitemap.append(SITEMAP_HREF + ContentDest)
151
with open(BUILD_DIRECTORY + "/" + ContentDest, "w", encoding="utf-8") as DestLocation:
152
DestLocation.write(RenderTemplate(PageInput, **kwargs))
153
154
def CreateJSONFeed():
155
CreatedJSON = {
156
"version": "https://jsonfeed.org/version/1",
157
"title": "Steve0Greatness' Blog",
158
"home_page_url": "https://steve0greatness.github.io",
159
"feed_url": "https://steve0greatness.github.io/blog/feed.rss",
160
"language": "en-US",
161
"favicon": "https://steve0greatness.github.io/favicon.ico",
162
"description": "A blog by a human being.",
163
"authors": [
164
{
165
"name": "Steve0Greatness",
166
"url": "https://steve0greatness.github.io"
167
}
168
],
169
"items": []
170
}
171
for post in PostList:
172
CreatedJSON["items"].append({
173
"id": "https://steve0greatness.github.io/blog/" + post["pathname"],
174
"title": "JSON Feed version 1.1",
175
"content_html": post["content"],
176
"date_published": post["date"],
177
"url": "https://steve0greatness.github.io/blog/" + post["pathname"]
178
})
179
with open(BUILD_DIRECTORY + "/blog/feed.json", "w") as JSONFeedFile:
180
DumpJSON(CreatedJSON, JSONFeedFile)
181
182
def RenderLists():
183
Lists = GetLists()
184
CreateDirectory(BUILD_DIRECTORY + "/list/")
185
for List in Lists:
186
print("%s -> %s" % ("lists/" + List["filename"], BUILD_DIRECTORY + "/list/" + List["filename"].replace(".yml", ".html")))
187
with open(BUILD_DIRECTORY + "/list/" + List["filename"].replace(".yml", ".html"), "w") as file:
188
file.write(RenderTemplate("list.html", Content=List["content"], Title=List["title"]))
189
190
if __name__ == "__main__":
191
print("Wiping directory")
192
WipeFinalDir()
193
print("Creating blog holder")
194
CreateDirectory(BUILD_DIRECTORY + "/blog")
195
print("Rendering posts")
196
RenderPosts()
197
CreateJSONFeed()
198
print("Copying static directory")
199
CopyDirectory("static", BUILD_DIRECTORY)
200
print("Creating lists")
201
RenderLists()
202
203
print("Building pages")
204
for file, path in PAGES.items():
205
if file in DISALLOWED_SITEMAP:
206
RenderPage(file, path, False, PostList=PostList)
207
continue
208
RenderPage(file, path, PostList=PostList)
209
210
with open(BUILD_DIRECTORY + "/sitemap.txt", "w") as SitemapFile:
211
SitemapFile.write("\n".join(sitemap))
212
213
pass