__ __ ___ __ _ / // /___ ___ _ _ __ __ __ / _ | ____ / / (_)___ ___ ____ __ __ / _ // -_)/ _ `/| |/ // // / / __ |/ __// _ \ / // _ \/ -_)/ __// // / /_//_/ \__/ \_,_/ |___/ \_, / /_/ |_|\__//_//_//_//_//_/\__//_/ \_, / /___/ /___/

A totally static blog with python

I dropped wordpress a while ago after getting fed up of the poor performance and security risks. I wanted something completely static. Just a plain HTML file that would display in someone's browser without having to use massive amounts of javascript, a database, css or antyhing that could create problems in the future, without the hassle of actually typing HTML by hand for every entry.

The idea had been in my head for a year, and I thought this would be a good time to give it a go, since it looked like a nice weekend project to try.

Thinking about what would imply to add a new blog entry to a totally static site, I came up with a few requirements for the script:

That was pretty much all I needed. Those are simple file and text operations, so python was the obvious choice for this.

Writing the entry

Since I wanted to be able to edit entries easily and also to have a backup of all of them, I decided to create every entry as a python file with a few variables. entry_title is the title of the entry (duh), entry_date the date, and entry_text the full markdown text of the entry.

Since the title of the entry can contain spaces and other weird stuff, I decided to use the python filename to name the folder in which the entry will be stored. So, from a file called test_entry.py containing a test entry, the script will generate a folder named test_entry in which it'll place an index.html with the actual entry. This'll make the URL look like url.com/blog/test_entry, which I like (At least more than the unreadable URLs wordpress generated)

The entry can contain all the usual markdown like lists, links, images, headers, code blocks, etc (This entry is pretty much a lorem ipsum + test entry + demonstration entry, all in one :P)

HTML from markdown

python has a neat module called markdown (Link). It allows you to translate a markdown string to HTML. Using the extensions=['fenced_code'] argument also makes it translate the code blocks to <pre> HTML blocks, which is neat. Syntax highlighting is also available and is a nice extra, but I was aiming for a minimal approach.

You can also use it as a module (python -m markdown input.txt > output.txt), which also makes it a very neat command line tool.

Creating header and footer

I'm a huge fan of plain HTML, so I wasn't going to think too hard about this. Everything you see in this page, up to the </center> after the title, is just a copypaste of some HTML in a header file. Same goes for the footer, which should be the last two lines (The link to go back). The header ascii art is from this site.

Once you have the header and footer, you just have to sandwich the entry between them.

Updating the entry list

Only thing left was to add the entry to the list. I decided to create a standard list page from the header and footer and put a marker in it (That's <!--newentry-->). So when I want to add a new entry, I just have to replace that string with a link to the new entry (And then the same string for the next time)

To avoid creating the same entry twice, the script first checks if the folder for the entry has been created. If it already exists, it gives you the option to update the html in it (To, for example, correct typos or add updates) without creating a new folder or modifying the file.

That's it!

Overall it was a pretty easy thing to make and I'm surprised about how well it works. Just edit the entry in your favourite editor, run it, and there you have it. Some of the things may be too hackish, but it works just fine (And I bet it'll load way, way faster than the old wordpress blog that exploded when 3 persons tried to read it at the same time)

#! /usr/bin/env python

import os, sys
import markdown

entryname=sys.argv[1]
exec("from %s import *"%entryname)

# Get header and footer from files, modify entry title
with open("./header.html","r") as f:
  header=f.read().replace("$title$", entry_title)
with open("./footer.html","r") as f:
  footer=f.read()

# Create new folder for the entry
try: 
  os.mkdir(entryname)

  # If folder (that is, entry) exists, create new entry in blog index
  with open("./index.html","r") as f:
    index=f.read()
  index=index.replace("<!--newentry-->",
                      "<!--newentry-->\n<li> <a href='%s'>%s</a> (%s)<br/> "%(
                        entryname, entry_title, entry_date))
  with open("./index.html","w+") as f:
    f.write(index)
except:
  if raw_input("folder exists. overwrite? [y/n]")!="y": 
    exit()

# Compose entry
entry=markdown.markdown(entry_text.decode("UTF-8"), extensions=['fenced_code'])
entry=header+entry+footer

# Write entry to file
with open("./%s/index.html"%entryname,"w+") as f:
  f.write(entry)


Back