#! /usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2007-2008 PediaPress GmbH # See README.txt for additional licensing information. import os from mwlib import parser, rendermath, timeline import urllib import cgi #from PIL import Image from mwlib.log import Log log = Log("htmlwriter") class HTMLWriter(object): imglevel = 0 namedLinkCount = 1 def __init__(self, out, images=None, math_renderer=None): self.out = out self.level = 0 self.images = images # self.images = imgdb.ImageDB(os.path.expanduser("~/images")) self.references = [] if math_renderer is None: self.math_renderer = rendermath.Renderer() else: self.math_renderer = math_renderer def _write(self, s): self.out.write(cgi.escape(s).encode('utf8')) def getCategoryList(self, obj): categories = list(set(c.target for c in obj.find(parser.CategoryLink))) categories.sort() return categories def write(self, obj): m = "write" + obj.__class__.__name__ m=getattr(self, m) m(obj) def ignore(self, obj): pass def serializeVList(self,vlist): args = [] styleArgs = [] gotClass = 0 gotExtraClass = 0 for (key,value) in vlist.items(): if isinstance(value, (basestring, int)): if key=="class": args.append('%s="%s"' % (key, value)) gotClass = 1 else: args.append('%s="%s"' % (key, value)) if isinstance(value, dict) and key=="style": for (_key,_value) in value.items(): styleArgs.append("%s:%s" % (_key, _value)) args.append(' style="%s"' % ';'.join(styleArgs)) gotExtraClass = 1 return ' '.join(args) def writeMagic(self, m): if m.values.get('html'): for x in m.children: self.write(x) def writeCaption(self, obj): # todo- A table contained a Caption node, causing an exception in write. # Not sure what the HTML should be, if any. pass def writeSection(self, obj): header = "h%s" % (obj.level) self.out.write("<%s>" % header) self.write(obj.children[0]) self.out.write("" % header) self.level += 1 for x in obj.children[1:]: self.write(x) self.level -= 1 def writePreFormatted(self, n): self.out.write("
")
        for x in n:
            self.write(x)
        self.out.write("
") def writeNode(self, n): for x in n: self.write(x) def writeCell(self, cell): svl = "" if cell.vlist: svl = self.serializeVList(cell.vlist) self.out.write('' % svl) for x in cell: self.write(x) self.out.write("") def writeTagNode(self, t): if t.caption == 'ref': self.references.append(t) self.out.write("%s" % len(self.references)) return elif t.caption == 'references': if not self.references: return self.out.write("
    ") for r in self.references: self.out.write("
  1. ") for x in r: self.write(x) self.out.write("
  2. ") self.out.write("
") self.references = [] return elif t.caption=='imagemap': # FIXME. this is not complete. t.imagemap.entries should also be handled. print "WRITEIMAGEMAP:", t.imagemap if t.imagemap.imagelink: self.write(t.imagemap.imagelink) return self.out.write(t.starttext.encode('utf8')) for x in t: self.write(x) self.out.write(t.endtext.encode('utf8')) def writeRow(self, row): self.out.write('') for x in row: self.write(x) self.out.write('') def writeTable(self, t): svl = "" if t.vlist: svl = self.serializeVList(t.vlist) self.out.write("" % svl) if t.caption: self.out.write("
") self.write(t.caption) self.out.write("") for x in t: self.write(x) self.out.write("
") def writeMath(self, obj): latex = obj.caption p = self.math_renderer.render(latex) self.out.write(p) def writeURL(self, obj): self.out.write('' % obj.caption) if obj.children: for x in obj.children: self.write(x) else: self.out.write(obj.caption) self.out.write(' ') def writeNamedURL(self, obj): self.out.write('' % obj.caption) if obj.children: for x in obj.children: self.write(x) else: name = "[%s]" % self.namedLinkCount self.namedLinkCount += 1 self.out.write(name) self.out.write(' ') def writeParagraph(self, obj): self.out.write("\n

") for x in obj: self.write(x) self.out.write("

\n") def getHREF(self, obj): parts = obj.target.encode('utf-8').split('#') parts[0] = parts[0].replace(" ", "_") return '../%s/' % ("#".join([urllib.quote(x) for x in parts])) writeLangLink = ignore def writeLink(self, obj): if obj.target is None: return href = self.getHREF(obj) if href is not None: self.out.write('' % (href,)) else: self.out.write('') if obj.children: for x in obj.children: self.write(x) else: self._write(obj.target) self.out.write("") def writeSpecialLink(self, obj): if obj.children: for x in obj.children: self.write(x) else: self._write(obj.target) def writeCategoryLink(self, obj): if obj.colon: if obj.children: for x in obj.children: self.write(x) else: self._write(obj.target) def writeTimeline(self, obj): #img = timeline.drawTimeline(obj.caption) img = None if img is None: return target = "/timeline/"+os.path.basename(img) width, height = Image.open(img).size self.out.write('' % (target, width, height)) def writeImageLink(self, obj): """ bla bla """ if self.images is None: return width = obj.width height = obj.height #if not width: # width = 400 # what could be a sensible default if no width is given? maybe better 0? if width: path = self.images.getPath(obj.target, size=max(width, height)) url = self.images.getURL(obj.target, size=max(width, height)) else: path = self.images.getPath(obj.target) url = self.images.getURL(obj.target) if url is None: return if isinstance(path, str): path = unicode(path, 'utf8') if self.imglevel==0: self.imglevel += 1 # WTB: Added the ability to not specify width & height since images may not be found locally. # This may have to be redone eventually, perhaps we need a database of image dimensions, # but I doubt it. Besides, more hardcoded pathnames in 'getimg'? try: def getimg(): return Image.open(path) img = None if not width: if not img: img = getimg() size = img.size width = min(400, size[0]) if not height: if not img: img = getimg() size = img.size height = size[1]*width/size[0] except IOError, err: log.warn("Image.open failed:", err, "path=", repr(path)) # WTB: Removed following return as images will not always be found locally. #self.imglevel -= 1 #return attr = '' attr_css = '' if width: attr += "width='%d' " % width attr_css += "width:%dpx " % width if height: attr += "height='%d' " % height # WTB: Note- height not applied to CSS. if obj.isInline(): self.out.write('' % (url.encode("utf8"), attr.encode("utf8"))) else: # WTB: This looked like a mistake to me, it was modifying obj.align instead of align. # This function should not modify obj at all. align = obj.align if obj.thumb == True and not align: align = "clear right" self.out.write('''
'''% (align, attr_css)) self.out.write('' % (url.encode("utf8"), attr.encode("utf8"))) self.out.write('') for x in obj.children: self.write(x) self.out.write('
') self.imglevel -= 1 else: self.out.write('' % url) for x in obj.children: self.write(x) self.out.write('') def writeText(self, t): #self.out.write(cgi.escape(t.caption).encode('ascii', 'xmlcharrefreplace')) self._write(t.caption) writeControl = writeText def writeArticle(self, a): for x in a: self.write(x) self.out.write("\n
") def writeStyle(self, s): if s.caption == "''": tag = 'em' elif s.caption=="'''''": self.out.write("") for x in s: self.write(x) self.out.write("") return elif s.caption == "'''": tag = 'strong' elif s.caption == ";": self.out.write("
") for x in s: self.write(x) self.out.write("
") return elif s.caption.startswith(":"): self.out.write("
"*len(s.caption)) for x in s: self.write(x) self.out.write("
"*len(s.caption)) return elif s.caption == "overline": self.out.write('') for x in s: self.write(x) self.out.write('') return else: tag = s.caption self.out.write("<%s>" % tag) for x in s: self.write(x) self.out.write("" % tag) def writeItem(self, item): self.out.write("
  • ") for x in item: self.write(x) self.out.write("
  • \n") def writeItemList(self, lst): if lst.numbered: tag = "ol" else: tag = "ul" self.out.write("<%s>" % tag) for x in lst: self.write(x) self.out.write("\n") self.out.write("" % tag) class NoLinksWriter(HTMLWriter): """Subclass that ignores (non-outgoing) links""" def writeLink(self, obj): if obj.target is None: return if obj.children: for x in obj.children: self.write(x) else: self._write(obj.target)