steve0greatness,
created on Friday, 22 December 2023, 01:48:16 (1703209696),
received on Monday, 6 May 2024, 02:55:32 (1714964132)
Author identity: Steve0Greatness <75220768+Steve0Greatness@users.noreply.github.com>
5ed7b73960321185eb11902ed2cdc5114fc33e27
.gitignore
@@ -0,0 +1,2 @@
__pycache__ docs/*
Renderers.py
@@ -0,0 +1,14 @@
from jinja2 import Environment as JinjaEnv, FileSystemLoader as JinjaFS from markdown2 import Markdown as MDEnv __TemplateRenderer__ = JinjaEnv(loader=JinjaFS(searchpath="./views")) def RenderTemplate(TemplateFileName: str, *args, **kwargs): """Renders a Jinja2 template from a file.""" return __TemplateRenderer__.get_template(TemplateFileName).render(*args, **kwargs) __MDRenderer__ = MDEnv(extras=["header-ids", "metadata", "markdown-in-html", "code-friendly", "footnotes", "fenced-code-blocks"], footnote_title="Jump back to footnote %d in the text.", footnote_return_symbol="↩") def RenderMarkdown(MDSource: str): """Renders Markdown, but pre-configured.""" return __MDRenderer__.convert(MDSource)
blog-posts/test-post.md
@@ -0,0 +1,10 @@
--- title: test date: 2023-12-09 --- # TEST ```python foo = "bar" ```
main.py
@@ -0,0 +1,55 @@
from Renderers import RenderTemplate, RenderMarkdown from shutil import rmtree as DeleteDirectory from os import mkdir as CreateDirectory, listdir as ListDirectory, unlink as DeleteFile from os.path import isfile as IsFile from distutils.dir_util import copy_tree as CopyDirectory def WipeDocsDir(): for item in ListDirectory("docs"): path = "docs/" + item if IsFile(path): DeleteFile(path) continue DeleteDirectory(path) def GetBlogList(): PostSlugs = ListDirectory("blog-posts") Posts = [] for slug in PostSlugs: with open("blog-posts/" + slug) as MDFile: PostHTML = RenderMarkdown(MDFile.read()) Item = PostHTML.metadata Item["content"] = PostHTML Item["pathname"] = slug.replace(".md", ".html") Posts.append(Item) return Posts PostList = GetBlogList() def RenderPosts(): for post in ListDirectory("blog-posts"): path = "blog-posts/" + post RenderedHTML: str with open(path, "r") as PostContent: PostHTML = RenderMarkdown(PostContent.read()) Title = PostHTML.metadata["title"] PostDate = PostHTML.metadata["date"] RenderedHTML = RenderTemplate("blog-post.html", Title=Title, PostDate=PostDate, Content=PostHTML) with open("docs/blog/" + post.replace(".md", ".html"), "w") as PostLocation: PostLocation.write(RenderedHTML) def RenderPage(PageInput: str, ContentDest: str, **kwargs): with open("docs/" + ContentDest, "w") as DestLocation: DestLocation.write(RenderTemplate(PageInput, **kwargs)) if __name__ == "__main__": WipeDocsDir() CreateDirectory("docs/blog") RenderPosts() CopyDirectory("static", "docs/static") RenderPage("index.html", "index.html", PostList=PostList) RenderPage("index.html", "index.html", PostList=PostList) pass
requirements.txt
@@ -0,0 +1,3 @@
jinja2==3.1.2 markdown2==2.4.11 pyyaml==6.0.1
static/src/pygments-friendly.css
@@ -0,0 +1,70 @@
.codehilite .hll { background-color: #ffffcc } .codehilite { background: #f0f0f0; padding: 7px; } .codehilite pre { margin: 0; } .codehilite .c { color: #60a0b0; font-style: italic } /* Comment */ .codehilite .err { border: 1px solid #FF0000 } /* Error */ .codehilite .k { color: #007020; font-weight: bold } /* Keyword */ .codehilite .o { color: #666666 } /* Operator */ .codehilite .ch { color: #60a0b0; font-style: italic } /* Comment.Hashbang */ .codehilite .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */ .codehilite .cp { color: #007020 } /* Comment.Preproc */ .codehilite .cpf { color: #60a0b0; font-style: italic } /* Comment.PreprocFile */ .codehilite .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */ .codehilite .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */ .codehilite .gd { color: #A00000 } /* Generic.Deleted */ .codehilite .ge { font-style: italic } /* Generic.Emph */ .codehilite .gr { color: #FF0000 } /* Generic.Error */ .codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */ .codehilite .gi { color: #00A000 } /* Generic.Inserted */ .codehilite .go { color: #888888 } /* Generic.Output */ .codehilite .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ .codehilite .gs { font-weight: bold } /* Generic.Strong */ .codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ .codehilite .gt { color: #0044DD } /* Generic.Traceback */ .codehilite .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ .codehilite .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ .codehilite .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ .codehilite .kp { color: #007020 } /* Keyword.Pseudo */ .codehilite .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ .codehilite .kt { color: #902000 } /* Keyword.Type */ .codehilite .m { color: #40a070 } /* Literal.Number */ .codehilite .s { color: #4070a0 } /* Literal.String */ .codehilite .na { color: #4070a0 } /* Name.Attribute */ .codehilite .nb { color: #007020 } /* Name.Builtin */ .codehilite .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ .codehilite .no { color: #60add5 } /* Name.Constant */ .codehilite .nd { color: #555555; font-weight: bold } /* Name.Decorator */ .codehilite .ni { color: #d55537; font-weight: bold } /* Name.Entity */ .codehilite .ne { color: #007020 } /* Name.Exception */ .codehilite .nf { color: #06287e } /* Name.Function */ .codehilite .nl { color: #002070; font-weight: bold } /* Name.Label */ .codehilite .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ .codehilite .nt { color: #062873; font-weight: bold } /* Name.Tag */ .codehilite .nv { color: #bb60d5 } /* Name.Variable */ .codehilite .ow { color: #007020; font-weight: bold } /* Operator.Word */ .codehilite .w { color: #bbbbbb } /* Text.Whitespace */ .codehilite .mb { color: #40a070 } /* Literal.Number.Bin */ .codehilite .mf { color: #40a070 } /* Literal.Number.Float */ .codehilite .mh { color: #40a070 } /* Literal.Number.Hex */ .codehilite .mi { color: #40a070 } /* Literal.Number.Integer */ .codehilite .mo { color: #40a070 } /* Literal.Number.Oct */ .codehilite .sa { color: #4070a0 } /* Literal.String.Affix */ .codehilite .sb { color: #4070a0 } /* Literal.String.Backtick */ .codehilite .sc { color: #4070a0 } /* Literal.String.Char */ .codehilite .dl { color: #4070a0 } /* Literal.String.Delimiter */ .codehilite .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ .codehilite .s2 { color: #4070a0 } /* Literal.String.Double */ .codehilite .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ .codehilite .sh { color: #4070a0 } /* Literal.String.Heredoc */ .codehilite .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ .codehilite .sx { color: #c65d09 } /* Literal.String.Other */ .codehilite .sr { color: #235388 } /* Literal.String.Regex */ .codehilite .s1 { color: #4070a0 } /* Literal.String.Single */ .codehilite .ss { color: #517918 } /* Literal.String.Symbol */ .codehilite .bp { color: #007020 } /* Name.Builtin.Pseudo */ .codehilite .fm { color: #06287e } /* Name.Function.Magic */ .codehilite .vc { color: #bb60d5 } /* Name.Variable.Class */ .codehilite .vg { color: #bb60d5 } /* Name.Variable.Global */ .codehilite .vi { color: #bb60d5 } /* Name.Variable.Instance */ .codehilite .vm { color: #bb60d5 } /* Name.Variable.Magic */ .codehilite .il { color: #40a070 } /* Literal.Number.Integer.Long */
views/_layout.html
@@ -0,0 +1,16 @@
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{% block title %}{% endblock %} - S0G</title> <link rel="stylesheet" href="/static/src/pygments-friendly.css"> </head> <body> <header> <h1>Steve0Greatness</h1> <nav></nav> </header> <main>{% block content %}{% endblock %}</main> </body> </html>
views/blog-post.html
@@ -0,0 +1,9 @@
{% extends "_layout.html" %} {% block title %}{{ Title }}{% endblock %} {% block content %} <article> <h2 id="blog-post-titled">{{ Title }}</h2> <time>{{PostDate}}</time> {{ Content }} </article> {% endblock %}
views/index.html
@@ -0,0 +1,26 @@
{% extends "_layout.html" %} {% block title %}Homepage{% endblock %} {% block content %} <h2 id="blog-posts">Blog Posts</h2> <table class="blog-list"> <tbody> {% for post in PostList %} <tr class="blog-list-title-and-date"> <td style="padding-right: 15px;"> <a href="/blog/{{post['pathname']}}">{{post["title"]}}</a> </td> <td> <time>{{post["date"]}}</time> </td> </tr> <!-- <tr class="blog-list-preview"> <td colspan="2"> <article style="max-height: 100px;overflow-y: hidden;"> {{post["content"]}} </article> </td> </tr> --> {% endfor %} </tbody> </table> {% endblock %}