# -*- coding: utf-8 -*- # lp4all: literate programming embedded in source code as wiki comments # Copyright (C) 2006 Jean-Marie Favreau, Frédéric Lehobey, David Mentré # and Thomas Petazzoni # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. import re import os.path from tree_struct import * from label_dict import * from html_tools import * class HtmlTreeRendering: def __init__(self, firstHeader = 2, listLevels = [], filename = ""): self.firstHeader = firstHeader self.listLevels = listLevels self.filename = filename def closeList(self): if self.listLevels == []: return '' raw_html = '' for i in self.listLevels: raw_html += '</li>\n</ul>\n' self.listLevels = [] return raw_html + '<p>' def treeToHtml(self, tree): raw_html = '<p>' + self.treeToRawHtml(tree) return self.htmlClean(raw_html + self.closeList() + '</p>\n') def nodeToRawHtml(self, node): result = html_escape(node.text) for c in node.children: result += self.treeToRawHtml(c) return result def treeToRawHtml(self, tree): if tree.__class__ == NodeContentList: if self.listLevels == []: self.listLevels.append(tree.level) return '</p>\n<ul>\n<li>' + self.nodeToRawHtml(tree) else: if tree.level > self.listLevels[-1]: self.listLevels.append(tree.level) return '<ul>\n<li>' + self.nodeToRawHtml(tree) elif tree.level == self.listLevels[-1]: return '</li>\n<li>' + self.nodeToRawHtml(tree) else: raw_html = '' while len(self.listLevels) != 1 and tree.level < self.listLevels[-1]: raw_html += '</li>\n</ul>\n' self.listLevels = self.listLevels[:-1] self.listLevels[-1] = tree.level return raw_html + "</li>\n<li>" + self.nodeToRawHtml(tree) elif tree.__class__ == NodeContentCancel: return '<span class="cancel">' + self.nodeToRawHtml(tree) + '</span>' elif tree.__class__ == NodeContentPre: return '<pre>' + self.nodeToRawHtml(tree) + '</pre>\n' elif tree.__class__ == NodeContentCode: return '<code>' + self.nodeToRawHtml(tree) + '</code>' elif tree.__class__ == NodeContentEmphasize: return '<em>' + self.nodeToRawHtml(tree) + '</em>' elif tree.__class__ == NodeContentStrong: return '<strong>' + self.nodeToRawHtml(tree) + '</strong>' elif tree.__class__ == NodeContentTitle: return self.closeList() + '</p>\n<h' + str(self.firstHeader + tree.level) + '>' + self.nodeToRawHtml(tree) + '</h' + str(self.firstHeader + tree.level) + '>\n<p>' elif tree.__class__ == NodeContentNewLine: return self.closeList() + '</p>\n<p>' elif tree.__class__ == NodeContentRef: try: label = LabelDict.getSingleton().find(tree.uri) except KeyError: print "WARNING: Label '%s' doesn't exist" % tree.uri return '<a href="#%s" class="broken">%s</a>' % (tree.uri, self.nodeToRawHtml(tree)) return '<a href="%s#%s">%s</a>' % (self.findTargetLink(self.filename, label.file), tree.uri, self.nodeToRawHtml(tree)) elif tree.__class__ == NodeContentLabel: return '<a id="%s"></a>' % tree.text elif tree.__class__ == NodeContentLink: return '<a class="external" href="' + tree.uri + '">' + self.nodeToRawHtml(tree) + '</a>' elif tree.__class__ == NodeContentText: return self.nodeToRawHtml(tree) elif tree.__class__ == NodeContentHR: return '</p><hr /><p>' else: result = '' for c in tree.children: result += self.treeToRawHtml(c) return result def removeCommonPrefix(self, a, b): if a == [] or b == []: return (a, b) if a[0] == b[0]: return self.removeCommonPrefix(a[1:], b[1:]) return (a, b) # Given a source filename and a target filename, return the simplest # link from source to target def findTargetLink(self, sourceFilename, targetFilename): assert sourceFilename == os.path.normpath(sourceFilename) assert targetFilename == os.path.normpath(targetFilename) source, target = self.removeCommonPrefix(sourceFilename.split('/'), targetFilename.split('/')) targetRemaining = "" for e in target: targetRemaining = os.path.join(targetRemaining, e) if targetRemaining != "": return os.path.join("../" * (len(target)-1), targetRemaining + ".html") else: return "" def htmlCleanEmplyTag(self, html_code, tag): return re.sub("<" + tag + ">[ \t\n]*</" + tag + ">", "", html_code) # Removes empty <p></p>, <li></li>, <ul></ul> and various other # html tags def htmlClean(self, html_code): clean_html = self.htmlCleanEmplyTag(html_code, 'p') for i in [0, 1, 2]: clean_html = self.htmlCleanEmplyTag(clean_html, 'h' + str(self.firstHeader + i)) clean_html = self.htmlCleanEmplyTag(clean_html, "strong") clean_html = self.htmlCleanEmplyTag(clean_html, "em") l = -1 while l != len(clean_html): clean_html = self.htmlCleanEmplyTag(clean_html, "li") clean_html = self.htmlCleanEmplyTag(clean_html, "ul") l = len(clean_html) return clean_html