❤ vegetablearian.com ❤


Super simple static site generators

I thought static site generators seemed like a cool modern alternative to frames until I looked at how they worked. Utter insanity. I'd rather learn php. If your site uses frames and/or could be easily rewritten to, these are the static site generators for you.

Super simple version 1

This works in Python 2.7 and Python 3. I could just about say I "wrote" it, because I transcribed it as my husband dictated it. I actually understood enough to spot a mistake, so let's just go ahead and say I wrote it all myself.

This is how I have my files and folders set up:

	/website
		/building
			/pages
			builder.py
			footer.html
			header.html
		/live
			[the real website to upload is exported here!! put your images/css/etc. here]

/pages, /live, footer.html and header.html are part of the script and need to be changed there if you change them. Everything else you can name whatever you want. The files in the /pages folder should have their final intended names, ie index.html, about.html

It outputs into the /live folder. It works with subfolders, too (like my /articles subfolder), but pay attention to the links/image paths/stylesheet locations/etc. in your header and footer (they need to start with a slash if you use subfolders)

It only outputs a new page if you updated the contents, the header or the footer :)

import os

file_list = os.listdir("pages")

for file in file_list[:]:
	if os.path.isdir(os.path.join("pages", file)):
		for subfile in os.listdir(os.path.join("pages", file)):
			file_list.append(os.path.join(file, subfile))
		
with open("header.html", "r") as f:
	header = f.read()
header_edittime = os.path.getmtime("header.html")
	
with open("footer.html", "r") as f:
	footer = f.read()
footer_edittime = os.path.getmtime("footer.html")

for file in file_list:
	if (
		os.path.exists(os.path.join("../live", file))
		and
		max(
			os.path.getmtime(os.path.join("pages", file)), 
			header_edittime,
			footer_edittime,
		)< os.path.getmtime(os.path.join("../live", file))
	):
		continue
	if os.path.isdir(os.path.join("pages", file)):
		try:
			os.makedirs(os.path.join("../live", file))
		except:
			pass
		continue
	print (file)
	with open(os.path.join("pages", file), "r") as f:
		contents = f.read()
		
	contents = header + contents + footer
	
	with open(os.path.join("../live", file), "w") as f:
		f.write(contents)

Not enough features? That's okay, we also have...

Simple SUPER version 2

Idk if this one works in Python 3 or why I don't have it. (I guess I'm just needlessly stubborn sometimes.) Works like a charm in 2.7!

This version has extra features: optional individual page titles if you set them in a <title> tag, a fallback whole-site one otherwise; ignores all non-html files for the stitching and just copies them across; and supports maybe more folder depth than the first version (all I can say is, this one is fine with deep directories, and idk if the other one was!)

It was again designed by my husband and typed/checked by me, who is slowly learning Python this way maybe :)

Directory structure:

	/website
		/building
			/pages [including EVERYTHING else: stylesheets, images, files...]
			builder.py
			footer.html
			header.html
		/live
			[the real website to upload is exported here!! ready to sync with your ftp client!]

You need to change/ignore similar things in this as the previous simpler version, with the addition of whatever you want in between your titles (page title --- site title). This contains my fun heart page titles which you can see are written out in python-unicode I guess (the u is needed before the actual unicode bit you can recognise if you know how to use these characters in css). You can change them to something more sensible if you want. As long as you put your site's real title (like mine of "vegetablearian.com") in your header.html in the ordinary way, you'll get page titles formatted like mine but not with my site's name, don't worry!

If you don't want these combo titles but a totally unique title for each page, I guess just get rid of the \1 bit because that's the self-thing like in regex (I hate regex so much omg) Or you could move that if you'd rather have "site --- specific page" or whatever. You can also rename the title tag part, it's not real html or real code, but just make sure to change it everywhere in the script, and pick something nice and unique for it to find only when you've actually meant to title a page!

import os
import shutil
import re


		
with open("header.html", "r") as f:
	header = f.read()
header_edittime = os.path.getmtime("header.html")
	
with open("footer.html", "r") as f:
	footer = f.read()
footer_edittime = os.path.getmtime("footer.html")

def cleanjoin(*args):
	path=os.path.join(*args)
	return path.replace("\\\\", "\\")

def copyfiles(folderpath):

	file_list = os.listdir(cleanjoin("pages", folderpath))

	for file in file_list[:]:
		if os.path.isdir(cleanjoin("pages", folderpath, file)):
			try:
				os.makedirs(cleanjoin("..", "live", folderpath, file))
			except:
				pass
			copyfiles(cleanjoin(folderpath, file))

	for file in file_list:
		if (
			os.path.exists(cleanjoin("..", "live", folderpath, file))
			and
			max(
				os.path.getmtime(cleanjoin("pages", folderpath, file)), 
				header_edittime,
				footer_edittime,
			)< os.path.getmtime(cleanjoin("..", "live", folderpath, file))
		):
			continue
		if (
			os.path.exists(cleanjoin("..", "live", folderpath, file))
			and
			not file.endswith(".html")
			and
			os.path.getmtime(cleanjoin("pages", folderpath, file))< os.path.getmtime(cleanjoin("..", "live", folderpath, file))
		):
			continue
		
		if os.path.isdir(cleanjoin("pages", folderpath, file)):
			continue
		print ('[',folderpath,']',file)
		if file.endswith(".html"):
			with open(cleanjoin("pages", folderpath, file), "r") as f:
				contents = f.read()
			pagetitle = re.search("<title>(.+?)</title>", contents)
			pageheader = header.decode("utf-8")
			if pagetitle:
				contents = re.sub("<title>(.+?)</title>", "", contents, 1)
				pageheader = re.sub("<title>", "<title>" + pagetitle.group(1) + u" -\u2661- ", header) 
			else:
				pageheader = re.sub("<title>(.+?)</title>", "<title>" + u"\u2661 " +"\\1" + u" \u2661" + "</title>", header)

			contents = pageheader + contents.decode("utf-8") + footer.decode("utf-8")
			
			with open(cleanjoin("..", "live", folderpath, file), "wb") as f:
				f.write(contents.encode("utf-8"))
		else:
			shutil.copy(
				cleanjoin("pages", folderpath, file),
				cleanjoin("..", "live", folderpath, file)
			)

copyfiles("")