Welcome To My Blog
18 May 2022 at 09:49 PM
Introduction
This is my blog, which I made using a Python script. The source code for the blog is available on my GitHub repository.
A Trick In Python
I have automated the process of running ssg.py
on GitHub pages,
meaning that I can write the blog post on the GitHub website, commit it, and it will
build it for me.
My blog script, ssg.py
(stands for Static Site Generator),
uses the modules markdown
and chevron
.
However, I want to install them without having to type the commands into the
GitHub configuration file.
There is a trick that can be done to automatically install any module if it doesn't exist:
import os
try:
import <module>
except ImportError:
os.system('pip3 install <module>')
import <module>
Some may say it's cursed, I say it's a great feature.
How it Works
In the src
folder, my blog posts reside in Markdown format.
Their filename are in snake_case and are converted to Title Case by the script.
For example, this article is called welcome_to_my_blog.md
,
so the title you see is "Welcome To My Blog".
This means that the filename is the title, so I don't need to write it in my Markdown file.
The PostDate
class
I made a new PostDate
class in order to format the dates like how they would be
in a blog (not like the ISO format):
class PostDate:
dt: datetime
def __init__(self, dt: datetime):
self.dt = dt
def __str__(self) -> str:
return self.dt.strftime('%w %b %Y at %I:%M %p')
This means that a template file can just say {{date}}
for a PostDate
object date
,
and my script will format the date correctly.
Classes in Python are Nice
I defined a class in Python to hold my post:
class Post:
title: str
url: str
date: PostDate
content: str
The best part of putting all the attributes in a class in this case is that
the templating engine chevron
can easily use these variables:
with open('template/post.html', 'r') as f:
rendered = chevron.render(f, self.__dict__)
chevron
takes in a dict
for variables, but luckily in scripting languages like Python,
it is easy to convert between an object and dict
. In Ruby, you use the .attributes
method
to convert an object to a hash, and in Javascript, the object is already a hash.
I wonder how difficult it would be to do the same thing in C.
Sorting by Date
The landing page of this blog has a list of blogs sorted by date. I easily did that with this function:
def add_and_sort(posts: List[Post], post: Post):
index = 0
for i in range(len(posts) - 1):
if posts[i].date.dt >= post.date.dt >= posts[i + 1].date.dt:
index = i
break
posts.insert(index, post)
Focus on the line starting with if
. in C, that statement would be more like:
if (date_cmp(posts[i].date.dt, post.date.dt) >= 0
&& date_cmp(post, posts[i + 1].date.dt) >= 0)
The Highlighting Process
As you can see in the code blocks, this code is highlighted. How does this work? I used the "Fenced Code Blocks" python-markdown extension while processing the markdown in my script:
def compile(self):
self.content = markdown(self.content, extensions=['fenced_code'])
Whenever this extension detects a markdown code block that has a name after the opening three backticks, it adds it to a class based on the name. For example, for the upper code block:
<pre><code class="language-py">
def compile(self):
self.content = markdown(self.content, extensions=['fenced_code'])
</code></pre>
The script highlight.js
recognizes this, and highlights the code. It is the only
client-side code in my site (besides the obligatory method call to it), so my blog is
very minimal and fast. Although highlight.js
highlights on the client-side, it
just doesn't feel like it, because it runs extremely quickly.
Rewrite in C?
I am comparing everything to C because I regularly use C to write applications. However, I realized that C might not be a great idea for an application like this.
Still, I love the C programming language for its simplicity and speed, which is why I write so many programs in C. I will eventually rewrite this program in C, and I will write a blog post about that new program.
Frontend Design
The last thing I want to talk about is designing the frontend. As a systems developer, this at first seems easy, but gets very difficult. I have to keep looking things up about CSS, and I have to make sure everything looks just right. Eventually, though, I got to my current style, and I think it looks very beautiful. The borders on the code blocks were actually unintentional, as they were a side efect of this CSS:
pre {
background-color: #333;
padding: 10px;
}
Although there is no actual border, the padding of the pre
element combined with its
dark color against my highlight.js
theme's light background color creates the border. I actually find it very nice, and I think it goes well with my website.