--- /dev/null
+#makeHTML.py version 0.8 May 1, 2005 Jerry Stratton
+#
+#part(code="tag" (defaults to paragraph), content="text" style="css style name", id="css id", attributes={named array of attributes for tag}
+# addAttribute(attributename="name for tag attribute", attributevalue="value for tag attribute")
+# addPart(code, content, style, id, attributes): adds at end
+# addPiece(thePart=another part object or "content text")
+# addPieces(pices=a list of part objects or content texts)
+# insertPart(code, content, style, id, attributes): inserts at start
+# insertPiece(thePart)
+# make(tab="initial tabs")
+# makePart(code, content, style, id, attributes): returns a part object
+# __len__: parts support the len() function; return number of pieces directly contained
+#snippet(code (defaults to "em"), content, posttext="text that comes directly after tag", pretext="text that comes directly before tag", style, id, attributes)
+#
+#head(title="text for title of page")
+#body(title="text for main headline", style, id, attributes)
+#page(pieces, style, id, attributes)
+#styleSheet(sheet="url of stylesheet", media="relevance of style sheet")
+#
+#headline(content="text content" (required), level="numerical level", style, id, attributes)
+#
+#table(rows=list of data for rows, style, thStyle="css style for table headers", tdStyle="css style for table cells",
+# trStyle="css style for table rows", tdBlankStyle="css style for blank cells", firstRowHeader=1--if first row is a header row,
+# firstColumnHeader=1--if first column is a header column, id, attributes)
+# addRow(rowList=[list of cells or data], celltype="th or td", cellclass="css style of cells", attributes, style)
+# addRows(rows=[list of list of cells or data], celltype, cellclass, attributes)
+# columnCount()
+#tableByColumn(columns=[list of columns], style, thStyle, tdStyle, trStyle, tdBlankStyle, firstRowHeader, firstColumnHeader, id, attributes)
+# addColumn(columnList=[list of column data or cells], celltype, cellclass, attributes)
+# addColumns(columns=[list of list of columns or column data], celltype, cellclass, attributes)
+#tableColumn(column=[list of data or cells for column], celltype, cellclass, firstRowHeader, thStyle, tdBlankStyle, attributes)
+# addCell(cell="cell or cell content", celltype, cellclass, id, attributes)
+# addCells(column="list of cells or cell contents", celltype, cellclass, attributes)
+#tableRow(celltype, row=[list of cells or cell data], style, cellclass, firstColumnHeader, thStyle, id, attributes)
+# addCell(cell="cell or cell content", celltype, cellclass, colspan="numerical span of cell vertically", rowspan="numerical span of cell horizontally")
+# addCells(cells=[list of cells or cell content])
+# columnCount()
+#
+#linkedList(links=[list of items of the form [url, name]], outer="outer html tag", inner="inner html tag", style="outer css style",
+# iclass="inner css style", id, attributes)
+# addLink(link=[url, name])
+# addLinks(links)
+#simpleList(items=[list of text items], outer, inner, defaultname="text for marking default entry", default="text of default entry",
+# style, iclass, id, attributes)
+# addItem(item="text of item")
+# addItems(items)
+#
+#image(src="url of image", alt="alternate text for image", align="alignment", style, id, attributes)
+#link(content, url, posttext, pretext, style, id, attributes)
+#
+#form(submitText="text of submit button", pieces, method="submit method", action="form action", submitName="name for submit button", submitAction="javascript for submission"
+# headline="headline text", headlineLevel (defaults to 2), style, attributes, id)
+#input(type="type of form input", name="name for input", value="default value for input", size="size for input", maxlength="maximum characters accepted",
+# style, id, attributes)
+#select(name, items, default, style, iclass, id, attributes
+#textinput(name, text, value, size, maxlength, style, id, attributes, type, tableRow=true if this should be a tr row, otherwise it is a paragraph)
+
+#basic parts
+class part:
+ def __init__(self, code="p", content=None, style=None, id=None, attributes=None):
+ self.style = style
+ self.id=id
+ self.pieces = []
+ self.code = code
+ if attributes == None:
+ self.attributes = {}
+ else:
+ self.attributes = attributes
+ if isinstance(content, list):
+ self.addPieces(content)
+ elif content != None:
+ self.addPiece(content)
+
+ def __len__(self):
+ return len(self.pieces)
+
+ def addAttribute(self, attributename, attributevalue):
+ self.attributes[attributename] = attributevalue
+
+ def addPart(self, code='p', content=None, style=None, id=None, attributes=None):
+ newPart = self.makePart(code, content, style, id, attributes)
+ self.addPiece(newPart)
+
+ def addPiece(self, thePart):
+ self.pieces.append(thePart)
+
+ def addPieces(self, theParts):
+ if theParts != None:
+ if isinstance(theParts, list):
+ for part in theParts:
+ self.addPiece(part)
+ else:
+ self.addPiece(theParts)
+
+ def insertPart(self, code='p', content=None, style=None, id=None, attributes=None):
+ newPart = self.makePart(code, content, style, id, attributes)
+ self.insertPiece(newPart)
+
+ def insertPiece(self, thePart):
+ self.pieces.insert(0, thePart)
+
+ def make(self, tab="\t"):
+ startHTML = '<' + self.code
+
+ if (self.attributes):
+ for attribute in self.attributes:
+ content = self.attributes[attribute]
+ if content == None:
+ startHTML += ' ' + attribute
+ else:
+ startHTML += ' ' + attribute + '="' + str(content) + '"'
+
+ if (self.style):
+ startHTML += ' class="' + self.style + '"'
+
+ if (self.id):
+ startHTML += ' id="' + self.id + '"'
+
+ if self.pieces:
+ startHTML += '>'
+
+ partItems = [startHTML]
+
+ if len(self.pieces) > 1:
+ sep = "\n" + tab
+ finalSep = sep[:-1]
+ newtab = tab + "\t"
+ else:
+ newtab = tab
+ sep = ""
+ finalSep = ""
+
+ for piece in self.pieces:
+ if isinstance(piece, str):
+ partItems.append(piece)
+ elif isinstance(piece, int) or isinstance(piece, float):
+ partItems.append(str(piece))
+ elif piece == None:
+ partItems.append("")
+ else:
+ partItems.append(piece.make(newtab))
+
+ code = sep.join(partItems)
+ code += finalSep + '</' + self.code + '>'
+ return code
+
+ else:
+ startHTML += ' />'
+ return startHTML
+
+ def makePart(self, code='p', content=None, style=None, id=None, attributes=None):
+ if content == None:
+ newPart = part(code)
+ else:
+ newPart = part(code, content, style, id, attributes)
+
+ return newPart
+
+class snippet(part):
+ def __init__(self, code="em", content=None, posttext=None, pretext=None, style=None, id=None, attributes=None):
+ part.__init__(self, code, content, style, id, attributes)
+ self.posttext = posttext
+ self.pretext = pretext
+
+ def make(self, tab=''):
+ snippets = []
+
+ if self.pretext:
+ snippets.append(self.pretext)
+
+ snippets.append(part.make(self, tab))
+
+ if self.posttext:
+ snippets.append(self.posttext)
+
+ return "".join(snippets)
+
+#common body parts
+
+class head(part):
+ def __init__(self, title=None):
+ part.__init__(self, code="head")
+ if title:
+ self.addPiece(part("title", title))
+
+class body(part):
+ def __init__(self, title=None, style=None, id=None, attributes=None):
+ part.__init__(self, code="body", style=style, id=id, attributes=attributes)
+ if title:
+ self.addPiece(headline(title, 1))
+
+class page(part):
+ def __init__(self, pieces=None, style=None, id=None, attributes=None):
+ part.__init__(self, code="html", style=style, id=id, attributes=attributes)
+ if isinstance(pieces, list):
+ self.addPieces(pieces)
+ elif isinstance(pieces, part):
+ self.addPiece(pieces)
+
+ def make(self, tab=''):
+ pageContent = part.make(self)
+
+ print 'Content-type: text/html'
+ print ''
+
+ print pageContent
+
+class styleSheet(part):
+ def __init__(self, sheet, media='all'):
+ attributes = {}
+ attributes['rel'] = "StyleSheet"
+ attributes['href'] = sheet + '.css'
+ attributes['type'] = "text/css"
+ attributes['media'] = media
+ part.__init__(self, code="link", attributes=attributes)
+
+
+#paragraph level parts
+class headline(part):
+ def __init__(self, content, level=2, style=None, id=None, attributes=None):
+ code = "h"+str(level)
+ part.__init__(self, content=content, style=style, code=code, id=id, attributes=attributes)
+
+
+
+#tables
+class table(part):
+ def __init__(self, rows=None, style=None, thStyle=None, tdStyle=None, trStyle=None, tdBlankStyle=None, firstRowHeader=None, firstColumnHeader=None, id=None, attributes=None):
+ part.__init__(self, code="table", style=style, id=id, attributes=attributes)
+ self.rowclass=trStyle
+ self.cellclass=tdStyle
+ self.cellheaderclass=thStyle
+ self.cellblankclass=tdBlankStyle
+ self.firstRowHeader=firstRowHeader
+ self.firstColumnHeader=firstColumnHeader
+ if rows:
+ self.addRows(rows)
+
+ def addRow(self, rowList, celltype=None, cellclass=None, attributes=None, style=None):
+ if cellclass==None:
+ if self.firstRowHeader and len(self.pieces) == 0:
+ celltype="th"
+ cellclass=self.cellheaderclass
+ else:
+ cellclass=self.cellclass
+
+ if style==None:
+ style = self.rowclass
+
+ newRow = tableRow(celltype, rowList, style, cellclass, self.firstColumnHeader, self.cellheaderclass, attributes)
+ self.addPiece(newRow)
+
+ def addRows(self, rows, cellclass=None, celltype=None, attributes=None):
+ for row in rows:
+ self.addRow(row)
+
+ def columnCount(self):
+ maxCount = 0
+ for row in self.pieces:
+ if isinstance(row, tableRow):
+ colCount = row.columnCount()
+ maxCount = max(maxCount, colCount)
+
+ return maxCount
+
+class tableByColumn(table):
+ def __init__(self, columns=None, style=None, thStyle=None, tdStyle=None, trStyle=None, tdBlankStyle=None, firstRowHeader=None, firstColumnHeader=None, id=None, attributes=None):
+ table.__init__(self, [], style, thStyle, tdStyle, trStyle, tdBlankStyle, firstRowHeader, firstColumnHeader, id, attributes)
+ self.columns = []
+ if columns:
+ self.addColumns(columns)
+
+ def addColumn(self, columnList, celltype=None, cellclass=None, attributes=None):
+ if cellclass==None:
+ if celltype == "th" or (self.firstColumnHeader and len(self.columns) == 0):
+ celltype="th"
+ cellclass=self.cellheaderclass
+ else:
+ cellclass=self.cellclass
+
+ newColumn = tableColumn(columnList, celltype, cellclass, self.firstRowHeader, self.cellheaderclass, self.cellblankclass, attributes)
+ self.columns.append(newColumn)
+
+ def addColumns(self, columns, celltype=None, cellclass=None, attributes=None):
+ for column in columns:
+ self.addColumn(column)
+
+ def addPiece(self, thePart):
+ if isinstance(thePart, tableColumn):
+ self.columns.append(thePart)
+ else:
+ part.addPiece(self, thePart)
+
+ def make(self, tabs):
+ rowCount = 0
+ for column in self.columns:
+ rowCount = max(rowCount, len(column.pieces))
+
+ if rowCount:
+ for cRow in range(rowCount):
+ row = tableRow()
+ for column in self.columns:
+ if cRow < len(column.pieces):
+ cell = column.pieces[cRow]
+ else:
+ cell = part("td")
+ row.addPiece(cell)
+
+ self.addPiece(row)
+
+ myPart = part.make(self, tabs)
+ return myPart
+
+
+class tableColumn(part):
+ def __init__(self, column=None, celltype="td", cellclass=None, firstRowHeader=None, thStyle=None, tdBlankStyle=None, attributes=None):
+ part.__init__(self, "column", style=cellclass, attributes=attributes)
+ if celltype==None:
+ self.celltype = "td"
+ else:
+ self.celltype=celltype
+
+ self.firstRowHeader=firstRowHeader
+ self.cellheaderclass=thStyle
+ self.cellblankclass=tdBlankStyle
+
+ if column:
+ self.addCells(column)
+
+ def addCell(self, cell=None, celltype=None, cellclass=None, id=None, attributes=None):
+ if self.cellblankclass and (cell==None or cell==""):
+ celltype="td"
+ cellclass = self.cellblankclass
+ elif self.firstRowHeader and len(self.pieces) == 0:
+ celltype = "th"
+ cellclass = self.cellheaderclass
+ else:
+ if celltype == None:
+ celltype = self.celltype
+ if cellclass == None:
+ cellclass = self.style
+ if cell == None:
+ cell = ""
+
+ tableCell = part(code=celltype, style=cellclass, content=cell, id=id, attributes=attributes)
+ self.addPiece(tableCell)
+
+ def addCells(self, column, celltype=None, cellclass=None, attributes=None):
+ for cell in column:
+ self.addCell(cell, celltype, cellclass, attributes=attributes)
+
+ def make(self):
+ print "Problem: columns should never be requested to make themselves."
+ print "Columns are not true html structures, and should only be added to tableByColumn parts."
+
+
+class tableRow(part):
+ def __init__(self, celltype="td", row=None, style=None, cellclass=None, firstColumnHeader=None, thStyle=None, id=None, attributes=None):
+ part.__init__(self, "tr", style=style, id=id, attributes=attributes)
+ self.celltype=celltype
+ self.cellclass=cellclass
+ self.firstColumnHeader=firstColumnHeader
+ self.cellheaderclass=thStyle
+ if row:
+ self.addCells(row)
+
+ def addCell(self, cell, celltype=None, cellclass=None, colspan=None, rowspan=None):
+ if self.firstColumnHeader and len(self.pieces) == 0:
+ celltype="th"
+ cellclass=self.cellheaderclass
+ elif celltype == None:
+ celltype = self.celltype
+
+ if celltype == None:
+ celltype = "td"
+
+ if cellclass==None:
+ cellclass=self.cellclass
+
+ attributes = {}
+ if colspan:
+ attributes['colspan'] = colspan
+ if rowspan:
+ attributes['rowspan'] = rowspan
+
+ if cell == None:
+ cell = ""
+
+ self.addPiece(part(code=celltype, style=cellclass, content=cell, attributes=attributes))
+
+ def addCells(self, cells):
+ for cell in cells:
+ self.addCell(cell)
+
+ def columnCount(self):
+ return len(self.pieces)
+
+
+#lists
+
+class linkedList(part):
+ def __init__(self, links=None, outer = "ul", inner="li", style=None, iclass=None, id=None, attributes=None):
+ part.__init__(self, code=outer, style=style, id=id, attributes=attributes)
+ self.innercode = inner
+ self.innerstyle = iclass
+ if isinstance(links, list):
+ self.addLinks(links)
+
+ def addLink(self, link):
+ [url, name] = link
+ link = part("a", attributes={"href": url}, content=name)
+ listitem = part(self.innercode, content=link, style=self.innerstyle)
+ self.pieces.append(listitem)
+
+ def addLinks(self, links):
+ theLinks = []
+ for link in links:
+ self.addLink(link)
+
+class simpleList(part):
+ def __init__(self, items=None, outer = "ul", inner="li", defaultname=None, default=None, style=None, iclass=None, id=None, attributes=None):
+ part.__init__(self, code=outer, style=style, id=id, attributes=attributes)
+ self.innercode = inner
+ self.innerstyle = iclass
+ self.defaultname = defaultname
+ self.default=default
+ if isinstance(items, list):
+ self.addItems(items)
+
+ def addItem(self, item):
+ attributes = {}
+ if self.defaultname:
+ if item == self.default:
+ attributes[self.defaultname] = None
+
+ theItem = part(self.innercode, content=item, style=self.innerstyle, attributes=attributes)
+ self.pieces.append(theItem)
+
+ def addItems(self, items):
+ theList = []
+ for item in items:
+ self.addItem(item)
+
+#individual pieces
+
+class image(part):
+ def __init__(self, src, alt=None, align=None, style=None, id=None, attributes=None):
+ if attributes == None:
+ attributes = {}
+ attributes['src'] = src
+ if alt:
+ attributes['alt'] = alt
+ if align:
+ attributes['align'] = align
+
+ part.__init__(self, 'img', style=style, id=id, attributes=attributes)
+
+class link(snippet):
+ def __init__(self, content=None, url=None, posttext=None, pretext=None, style=None, id=None, attributes=None):
+ if url != None:
+ if attributes == None:
+ attributes = {}
+ attributes['href'] = url
+
+ snippet.__init__(self, "a", content, posttext, pretext, style, id, attributes)
+
+
+#forms
+
+class form(part):
+ def __init__(self, submitText="Submit", pieces=None, method="get", action='./', submitName = None, submitAction=None, headline=None, headlineLevel = 2, style=None, attributes=None):
+ self.submitText = submitText
+ self.submitName = submitName
+ self.making = None
+ if attributes == None:
+ attributes = {}
+ if action != None:
+ attributes['action'] = action
+ if method != None:
+ attributes['method'] = method
+ if submitAction != None:
+ attributes['onSubmit'] = '"' + submitaction + '"'
+
+ part.__init__(self, 'form', style=style, attributes=attributes)
+
+ if headline != None:
+ headcode = "h" + headlineLevel
+ self.addPart(headcode, content=headline)
+
+ self.addPieces(pieces)
+
+
+ def make(self, tab=''):
+ if self.making:
+ return part.make(self, tab)
+ else:
+ if self.submitName:
+ submitButton = input("submit", value=self.submitText, name=self.submitName)
+ else:
+ submitButton = input("submit", value=self.submitText)
+ trueForm = self
+ trueForm.making = 1
+ trueForm.addPiece(submitButton)
+ pageContent = trueForm.make(tab)
+ return pageContent
+
+class input(part):
+ def __init__(self, type, name=None, value=None, size=None, maxlength=None, style=None, id=None, attributes=None):
+ if attributes == None:
+ attributes = {}
+
+ attributes['type'] = type
+ if name:
+ attributes['name'] = name
+ if value!=None:
+ attributes['value'] = value
+ if size:
+ attributes['size'] = size
+ if maxlength:
+ attributes['maxlength'] = maxlength
+
+ part.__init__(self, 'input', style=style, id=id, attributes=attributes)
+
+class select(simpleList):
+ def __init__(self, name, items=None, default=None, style=None, iclass=None, id=None, attributes=None):
+ if attributes==None:
+ attributes={}
+ attributes['name'] = name
+
+ simpleList.__init__(self, items, outer='select', inner='option', defaultname='selected', default=default, style=style, iclass=iclass, id=id, attributes=attributes)
+
+class textinput(part):
+ def __init__(self, name=None, text=None, value=None, size=None, maxlength=None, style=None, id=None, attributes=None, type="text", tableRow=None):
+ if (text == None):
+ text = name
+ self.field = input(type=type, name=name, value=value, size=size, maxlength=maxlength, style=style, id=id, attributes=attributes)
+ self.text = text
+
+ if tableRow == None:
+ part.__init__(self, 'p', style=style, attributes=attributes)
+ self.addPiece(self.text)
+ self.addPiece(self.field)
+ else:
+ part.__init__(self, 'tr', style=style, attributes=attributes)
+ self.addPart('th', content=self.text)
+ self.addPart('td', content=self.field)
+
+
+
+#need some functions for HTML
+#ought to be somewhere else in Python?
+#cgi.escape only seems to do <, >, and &
+from htmlentitydefs import entitydefs
+import re
+
+entitydefs_inverted = {}
+for k,v in entitydefs.items():
+ entitydefs_inverted[v] = k
+
+needencoding = re.compile('|'.join(entitydefs.values()))
+alreadyencoded = re.compile('&\w+;|&#[0-9]+;')
+
+#encodes any special characters to their HTML equivalents
+def encode(text, skip=None, once_only=1):
+ # if extra_careful, check to see if this text has already been converted
+ if not (once_only and alreadyencoded.findall(text)):
+ if not isinstance(skip, list):
+ skip = [skip]
+
+ #do ampersands on their own or we might end up converting our conversions
+ if '&' not in skip:
+ text = text.replace('&','&')
+ skip.append('&')
+
+ needlist= []
+ #grab the characters in the text that need encoding
+ for x in needencoding.findall(text):
+ #and make sure we aren't skipping them
+ if x not in skip:
+ needlist.append(x)
+
+ for uncoded in needlist:
+ encoded = entitydefs_inverted[uncoded]
+ #if it is not a numerical encoding, we need to do the & and ; ourselves
+ if not encoded.startswith('&#'):
+ encoded = '&%s;'%entitydefs_inverted[uncoded]
+
+ text = text.replace(uncoded, encoded)
+
+ return text