# # This python program is designed to build GouldHome web pages. # # Note: on August 16th I overhauled this script to use embeded Python # code instead of hardcoded constants. The comments may be slight out # of date on some functions. # # ----- # # To run from the command line, pass in 1 parameter which is either a # directory name or the name of a single .go(n) file. If you pass in a # directory name, every .go(n) file in that directory will be processed. # # When we design web pages for our home site, we will create files which # contain all the html for the guts of the page but none of the html for # the menu and page borders. This script will add the menu and page borders # to the raw page contents. # # In addition, this script will also handle creating thumbnail pages when # appropiate and will cross link the thumbnail pages into the corresponding # text page. # # We assume a directory structure as follows. # # c:\My Documents\GouldHome # index.go # index.html (*) # other.go # other.html (*) # .\images # foo.jpg # bar.jpg # .\daphne # index.go # index.html (*) # manual.html # visit.go # visit.html (*) # visit_thumb.gon (**) # visit_thumb.html (*) # .\visit # 990605_1214_PictureTitle.jpg # l990605_1214_PictureTitle.jpg (**) # s990605_1214_PictureTitle.jpg (**) # .\images # foo.jpg # bar.jpg # .\joel # index.go # index.html (*) # random.go # random.html (*) # party.go # party.html (*) # party_thumb.gon (**) # party_thumb.html (*) # party_thumb2.gon (**) # party_thumb2.html (*) # .\party # 990605_1214_PictureTitle.jpg # l990605_1214_PictureTitle.jpg (**) # s990605_1214_PictureTitle.jpg (**) # .\beth # .\ben # .\events # .\orienteering # # Files marked with a single asterisk (*) are created by this python script. # Files marked with a double asterisk (**) are created by the makeThumb.py # script which will be called from this script. # All other files are created manually. # # We support the following extensions: # # go = html source which will be converted into a htm file of the same name # after adding the navigation bar and menu. Files with an extension of # .go are listed in the menu of that directory. # # gon = same as a .go file except that the file is not listed in the menu # for that directrory. This is used for thumbnail files since those # files are accessed from the corresponding text page (a .go file). # This extension is also used for files under construction to avoid # having references to them appear on the website. # # htm = html file. We automatically create .html files from both .go and # .gon files but is is also possible that another .html file is created # manually in the directory for some reason. # # jpg = jpg image file. The thumbnail program deals with .jpg files # both as input (the original full size image) and as output (when # it creates thumbnails and scaled images). Other .jpg files may # also be created manually. # # As currently designed, we expect the following subdirectories: daphne, # joel, beth, ben, events, orienteering. These directories are special # because they are accessed from the navigation bar at the top of every # page. We also assume that each of these directories contain an index.html # file which will be created from an index.go file. # # About thumbnail pages. Thumbnail pages will automatically be created when # a .go is converted into html is there exists a subdiectory with the same # name as the .go file (ex: 'xxxxx.go' and '.\xxxxx'). In that case the # makeThumb.py script will be used to create a file called (for this example) # xxxxx_thumb.gon which will, in turn, be converted into xxxxx_thumb.html. # # Conversion details. Normally, the contents of the .go file will be inserted # into a .html page unmodified. The resulting .html page will have a header # and footer added which turns it into a standard GouldHome style web page. # # The header includes a navigation bar which displays on the screen as a # series of tabs. Zero or one tab will be highlighted denending on the # directory which contains the .go file. # # The header also includes a menu of pages which is displayed down the left # side of the screen. This menu contains one link correspnding to every .go # page in the current directory. # # If a thumbnail page is created, the source html code in the .go page will # be modified slightly to include a link to the thumbnail page(s). # # ----- # # The header/footer instructions are not hard coded in this file. Instead # we look for a file called "template.got" in the GouldHome directory. The # template.got file is an html file with special markers of the form # and . These comments actually contain Python code # which describes what text should be generated. # # When we refer to a page's location a page can be a top-level page which # means that the .go(n) file is in the GouldHome directory, or a section # page which means the .go(n) file is in a section like GouldHome\daphne. # In the latter case, the section name is "daphne". # # A page's title is extracted from the page filename by separating the words # in the filename at capital letters or numeric sequences. If the page # filename is "index" then the title is always "Introduction". # # ----- # # Comments within the delimeters <--~ ~--> contain Python code which is # executed as a statement. These comments are all processed before comments # of the other type. The Python code within these delimeters (which may be # multiline) is usually function or variable definition code. Once the code # is executed, the entire comment is removed from the html. # # Comments within the delimeters contain Python code which is # executed as an expression. The expression must return a string. When the # expression is executed, the entire comment will be replaced by the string # computed by the Python expression. # # The following global variables and functions can be used inside the # template file's Python code. They will be defined before the template # file is interpreted. # # pageBaseName = name of this page without extension # pageTitle = the title of the page # pageFileDate = the date that the *.go file was last modified # pageSection = subdirectory or None # # mainBody = processed .go(n) file # # ----- # # When we read in the source .go file, we also look for embeded Python # code. The goFile is allowed to define variables which have meaning # in the template. # # ----- # # Building the side menu html is specially coded inside this file. It # creates a block of html code for .go file in the same directory as the # file being processed. # # Insert the main menu code in the source file by including the following # block in the template file: # # # # # The insertMenuHere function will use the source html code to create the # entire main menu. This block of html code can also contain # Python expressions (but not Python statements). # # These variables are defined when the menu expansion is done: # # menuFile = file name corresponding to that menu item # menuText = page title which corresponds to that menu item # menuBaseName = file name of menu item without extension # import os import re import sys import glob import time import string import traceback import makeThumb from stat import * gouldHome = 'gouldhome' sectionNames = ('daphne','joel','beth','ben','events','orienteering') MyError = 'MyError' # We cache the list of menu items because it is time consuming to recreate # it. We remember the directory we processed and the menu items list here lastMenuPath = '' menuItems = None # These variables are accessible in the Python code embeded in the template # and go files. pageBaseName = '' pageTitle = '' pageFileDate = '' pageSection = '' mainBody = '' menuFile = '' menuText = '' menuBaseName = '' #--------------------------------------------------------------------------- # This set of three functions will take a string which is either the page # template or a subset of the page template and process all embedded Python # code. # # Python code inside will exec executed in the global namespace. # This code usually contains function and variable definitions. # # Python code inside will be evaluated. This Python code is # required to return a string which is then substituted back into the # source string and returned. # localDict = {} def runPythonCode(data): global localDict # find all ',re.DOTALL) data = pat.sub(execString,data) # find all ',re.DOTALL) data = pat.sub(evalString,data) # return the modified string return data def execString(res): globalDict = sys.modules[__name__].__dict__ exec(res.group(1),globalDict,localDict) return '' def evalString(res): globalDict = sys.modules[__name__].__dict__ return eval(res.group(1),globalDict,localDict) #--------------------------------------------------------------------------- def run(fileName): global pageBaseName global pageTitle global pageFileDate global pageSection global mainBody global localDict localDict = {} #-------- # Preparation # make sure the input file has an extension of .go or .gon if fileName[-3:] != '.go' and fileName[-4:] != '.gon': raise MyError,'File %s must have an extension of .go or .gon'%fileName # extract the directory name and make sure that it is legal baseName,pageSection,sectPath,homePath = decodeFilename(fileName) pageBaseName = stripExtension(baseName) pageTitle = convertNameIntoTitle(pageBaseName) print 'Processing %s\\%s...'%(pageSection,baseName) # compute the menu items for this directory global menuItems,lastMenuPath if menuItems == None or lastMenuPath != sectPath: menuItems = computeMenuItems(sectPath) lastMenuPath = sectPath # see if there is a thumbnail directory corresponding to this page try: mode = os.stat(sectPath+'\\'+pageBaseName)[ST_MODE] if S_ISDIR(mode): thumbLink = pageBaseName+'_thumb.html' else: thumbLink = '' thumbTitle = pageTitle+' Pictures' except OSError: thumbLink = '' # figure out the last modified time of the input file modDate = os.stat(fileName)[ST_MTIME] pageFileDate = time.strftime('%B %d, %Y',time.localtime(modDate)) #-------- # Processing # here we read the .go file into memory mainBody = open(fileName,'r').read() mainBody = runPythonCode(mainBody) # If there is a thumbnail file, here we add the link to that file. This # special processing is hard coded to avoid having to code this in every # .go file. if thumbLink: mainBody = insertThumbLink(mainBody,thumbLink,thumbTitle) # here we load the template file into memory homePath = homePath+'\\template.got' if not os.access(homePath,0): raise MyError,'Template file %s is missing'%homePath template = open(homePath,'r').read() # Here we fix the html references for subdirectorys. This processing is # hard coded to avoid having to include macros for every image reference # in the template file. if pageSection: template = fixupHtmlRefs(template) template = runPythonCode(template) # write the html file open(sectPath+'\\'+pageBaseName+'.html','w').write(template) #--------------------------------------------------------------------------- def convertNameIntoTitle(baseName): if baseName == 'index': return 'Introduction' else: return makeThumb.convertNameIntoTitle(baseName) #--------------------------------------------------------------------------- def stripExtension(baseName): return baseName[:string.rfind(baseName,'.')] #--------------------------------------------------------------------------- # This subroutine tests and decodes the filename. It returns a tuple of # (1) the base file name ('index.go') # (2) the section name ('daphne') '' for GouldHome # (3) the path to the section ('c:\temp\GouldHome\daphne') # (4) the path to GouldHome ('c:\temp\GouldHome') def decodeFilename(fileName): if fileName[1] != ':' and fileName[0:2] != '\\\\': raise MyError,'File %s must have include an absolute path'%fileName dirList = string.split(fileName,'\\') if len(dirList) < 3: raise MyError,'File %s must not be in the root directory'%fileName baseName = dirList[-1] section = string.lower(dirList[-2]) sectPath = string.join(dirList[:-1],'\\') if section == gouldHome: section = '' homePath = sectPath elif section in sectionNames and string.lower(dirList[-3]) == gouldHome: homePath = string.join(dirList[:-2],'\\') else: raise MyError,'File '+fileName+' must be in GouldHome or one of '+repr(sectionNames) return baseName,section,sectPath,homePath #--------------------------------------------------------------------------- # Computes a list of menu items. Each menu item is a tuple of: # (1) the file name # (2) the file title # (3) the last access time. # The list is sorted in reverse chronological order except that index.go is # listed first. def computeMenuItems(sectPath): menuItems = [] files = glob.glob(sectPath+'\\*.go') if sectPath+'\\index.go' not in files: raise MyError,'The files index.go is missing from %s'%sectPath for file in files: baseName = file[string.rfind(file,'\\')+1:] rootName = stripExtension(baseName) title = convertNameIntoTitle(rootName) fileDate = os.stat(file)[ST_MTIME] menuItems.append( (rootName+'.html',title,fileDate) ) menuItems.sort(sortFunc) return menuItems def sortFunc(item1,item2): if item1[0] == item2[0]: return 0 elif item1[0] == 'index.html': return -1 elif item2[0] == 'index.html': return 1 elif item1[2] > item2[2]: return -1 elif item1[2] < item2[2]: return 1 else: return 0 #--------------------------------------------------------------------------- # This adds a thumbnail link to a html file in memory. # # The file is stored in a list of lines. If the file begins with a header # of the form:
| """ + res.group(1) + """ |
|