185 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			185 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Python
		
	
	
	
| 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)
 | |
| 
 |