test_ok1/py/rest/transform.py

185 lines
5.1 KiB
Python
Raw Normal View History

import py
from py.__.rest import rst
from py.xml import html
class RestTransformer(object):
def __init__(self, tree):
self.tree = tree
self._titledepths = {}
self._listmarkers = []
def parse(self, handler):
handler.startDocument()
self.parse_nodes(self.tree.children, handler)
handler.endDocument()
def parse_nodes(self, nodes, handler):
for node in nodes:
name = node.__class__.__name__
if name == 'Rest':
continue
getattr(self, 'handle_%s' % (name,))(node, handler)
def handle_Title(self, node, handler):
depthkey = (node.abovechar, node.belowchar)
if depthkey not in self._titledepths:
if not self._titledepths:
depth = 1
else:
depth = max(self._titledepths.values()) + 1
self._titledepths[depthkey] = depth
else:
depth = self._titledepths[depthkey]
handler.startTitle(depth)
self.parse_nodes(node.children, handler)
handler.endTitle(depth)
def handle_ListItem(self, node, handler):
# XXX oomph...
startlist = False
c = node.parent.children
nodeindex = c.index(node)
if nodeindex == 0:
startlist = True
else:
prev = c[nodeindex - 1]
if not isinstance(prev, rst.ListItem):
startlist = True
elif prev.indent < node.indent:
startlist = True
endlist = False
if nodeindex == len(c) - 1:
endlist = True
else:
next = c[nodeindex + 1]
if not isinstance(next, rst.ListItem):
endlist = True
elif next.indent < node.indent:
endlist = True
type = isinstance(node, rst.OrderedListItem) and 'o' or 'u'
handler.startListItem('u', startlist)
self.parse_nodes(node.children, handler)
handler.endListItem('u', endlist)
def handle_Transition(self, node, handler):
handler.handleTransition()
def handle_Paragraph(self, node, handler):
handler.startParagraph()
self.parse_nodes(node.children, handler)
handler.endParagraph()
def handle_SubParagraph(self, node, handler):
handler.startSubParagraph()
self.parse_nodes(node.children, handler)
handler.endSubParagraph()
def handle_LiteralBlock(self, node, handler):
handler.handleLiteralBlock(node._text)
def handle_Text(self, node, handler):
handler.handleText(node._text)
def handle_Em(self, node, handler):
handler.handleEm(node._text)
def handle_Strong(self, node, handler):
handler.handleStrong(node._text)
def handle_Quote(self, node, handler):
handler.handleQuote(node._text)
def handle_Link(self, node, handler):
handler.handleLink(node._text, node.target)
def entitize(txt):
for char, repl in (('&', 'amp'), ('>', 'gt'), ('<', 'lt'), ('"', 'quot'),
("'", 'apos')):
txt = txt.replace(char, '&%s;' % (repl,))
return txt
class HTMLHandler(object):
def __init__(self, title='untitled rest document'):
self.title = title
self.root = None
self.tagstack = []
self._currlist = None
def startDocument(self):
h = html.html()
self.head = head = html.head()
self.title = title = html.title(self.title)
self._push(h)
h.append(head)
h.append(title)
self.body = body = html.body()
self._push(body)
def endDocument(self):
self._pop() # body
self._pop() # html
def startTitle(self, depth):
h = getattr(html, 'h%s' % (depth,))()
self._push(h)
def endTitle(self, depth):
self._pop()
def startParagraph(self):
self._push(html.p())
def endParagraph(self):
self._pop()
def startSubParagraph(self):
self._push(html.p(**{'class': 'sub'}))
def endSubParagraph(self):
self._pop()
def handleLiteralBlock(self, text):
pre = html.pre(text)
if self.tagstack:
self.tagstack[-1].append(pre)
else:
self.root = pre
def handleText(self, text):
self.tagstack[-1].append(text)
def handleEm(self, text):
self.tagstack[-1].append(html.em(text))
def handleStrong(self, text):
self.tagstack[-1].append(html.strong(text))
def startListItem(self, type, startlist):
if startlist:
nodename = type == 'o' and 'ol' or 'ul'
self._push(getattr(html, nodename)())
self._push(html.li())
def endListItem(self, type, closelist):
self._pop()
if closelist:
self._pop()
def handleLink(self, text, target):
self.tagstack[-1].append(html.a(text, href=target))
def _push(self, el):
if self.tagstack:
self.tagstack[-1].append(el)
else:
self.root = el
self.tagstack.append(el)
def _pop(self):
self.tagstack.pop()
def _html(self):
return self.root.unicode()
html = property(_html)