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