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 %}