A simple orgmode HTTP server written with Tornado
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
4.9 KiB

import os
import subprocess
contentDirectory = "content"
renderedDirectory = "renderedContent"
# Pairs of extension, pandoc read type
# HTML->HTML is essentially a copy, with some pandoc sugar added (see pandoc docs)
convertableContentTypes = [(".org", "org"), (".html", "html")]
contentExtensions = []
for contentType in convertableContentTypes:
contentExtensions.append(contentType[0])
contentExtensions = tuple(contentExtensions)
renderedContentTypes = [(".html", "html")]
defaultRenderedTypeIndex = 0
renderedContentExtensions = []
for contentType in renderedContentTypes:
renderedContentExtensions.append(contentType[0])
renderedContentExtensions = tuple(renderedContentExtensions)
def getContentReadType(contentFilename):
contentExtension = contentFilename[contentFilename.rfind("."):]
for contentType in convertableContentTypes:
if contentExtension == contentType[0]:
return contentType[1]
# Strip the content directory
def getContentLocalName(contentFilename):
return contentFilename[len(contentDirectory):]
# Strip the rendered directory
def getRenderedLocalName(filename):
return filename[len(renderedDirectory):]
def stripExtension(filename):
return filename[:filename.rfind(".")]
def contentFilenameToRenderedFilename(contentFilename):
return "{}{}{}".format(renderedDirectory,
stripExtension(getContentLocalName(contentFilename)),
renderedContentTypes[defaultRenderedTypeIndex][0])
def renderContent(contentFilename):
# Content modified recently; render it
print("\tRendering {}".format(contentFilename))
outputFilename = contentFilenameToRenderedFilename(contentFilename)
# Make subdirectory if necessary
if not os.path.exists(os.path.dirname(outputFilename)):
os.makedirs(os.path.dirname(outputFilename))
# TODO: Support multiple output formats?
subprocess.run(["pandoc",
"-r", getContentReadType(contentFilename),
"-w", renderedContentTypes[defaultRenderedTypeIndex][1],
"-o", outputFilename, contentFilename])
# List of all content files
contentCache = []
renderedCache = []
renderedDictionary = {}
def updateRenderedCache():
global renderedCache
global renderedDictionary
renderedCache = []
# Get all rendered files
for root, dirs, files in os.walk(renderedDirectory):
for file in files:
if file.endswith(renderedContentExtensions):
renderedFile = os.path.join(root, file)
renderedCache.append(renderedFile)
# The path actually used to look up the content (strip '/' from front)
contentPath = getRenderedLocalName(stripExtension(renderedFile))[1:]
print("\t'{}' = '{}'".format(contentPath, renderedFile))
# No use for the value yet, we just want fast key lookups
renderedDictionary[contentPath] = renderedFile
"""
Interface
"""
def getAllPostsList():
allPosts = []
for key, value in renderedDictionary.items():
allPosts.append(key)
return allPosts
def getRenderedBody(contentPath):
body = None
if contentPath in renderedDictionary:
renderedFilename = renderedDictionary[contentPath]
renderedFile = open(renderedFilename)
body = renderedFile.readlines()
body = "".join(body)
renderedFile.close()
return body
def checkForContentChange():
global contentCache
print("Checking for content updates...")
# Get all content files
contentCache = []
for root, dirs, files in os.walk(contentDirectory):
for file in files:
if file.endswith(contentExtensions):
contentCache.append(os.path.join(root, file))
updateRenderedCache()
numRenderedFiles = 0
# Compare timestamps to determine which files need regeneration
for contentFilename in contentCache:
contentModified = os.path.getmtime(contentFilename)
contentLocalName = getContentLocalName(contentFilename)
renderedFileFound = False
for renderedFile in renderedCache:
if stripExtension(renderedFile[len(renderedDirectory):]) != stripExtension(contentLocalName):
continue
renderedFileFound = True
renderedModified = os.path.getmtime(renderedFile)
# Modified content
if contentModified > renderedModified:
renderContent(contentFilename)
numRenderedFiles += 1
# New content file
if not renderedFileFound:
renderContent(contentFilename)
numRenderedFiles += 1
# We generated new content; make sure the cache is up-to-date
if numRenderedFiles:
updateRenderedCache()
print("Checking for content updates done. Rendered {} files".format(numRenderedFiles))