| 1 | import xml.dom.minidom, StringIO |
| 2 | import cons as _cons |
| 3 | import util |
| 4 | dom = xml.dom.minidom.getDOMImplementation() |
| 5 | |
| 6 | ns = u"http://www.w3.org/1999/xhtml" |
| 7 | doctype = u"-//W3C//DTD XHTML 1.1//EN" |
| 8 | dtd = u"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" |
| 9 | |
| 10 | class htmlelement(_cons.element): |
| 11 | def __todoc__(self): |
| 12 | doc = dom.createDocument(None, None, None) |
| 13 | doc.appendChild(dom.createDocumentType("html", doctype, dtd)) |
| 14 | doc.appendChild(self.__todom__(doc)) |
| 15 | return doc |
| 16 | |
| 17 | def cons(ctx=None): |
| 18 | return _cons.constructor(ns, htmlelement, ctx) |
| 19 | |
| 20 | def head(title=None, css=None): |
| 21 | h = cons() |
| 22 | head = h.head |
| 23 | if title: |
| 24 | head(h.title(title)) |
| 25 | if isinstance(css, str) or isinstance(css, unicode): |
| 26 | head(h.link(rel="stylesheet", type="text/css", href=css)) |
| 27 | elif css: |
| 28 | for ss in css: |
| 29 | head(h.link(rel="stylesheet", type="text/css", href=ss)) |
| 30 | return head |
| 31 | |
| 32 | class htmlformatter(util.formatter): |
| 33 | allowshort = set([u"br", u"hr", u"img", u"input"]) |
| 34 | def element(self, el, **extra): |
| 35 | if el.name in self.allowshort: |
| 36 | super(htmlformatter, self).element(el, **extra) |
| 37 | else: |
| 38 | self.longtag(el, **extra) |
| 39 | |
| 40 | class htmlindenter(util.indenter, htmlformatter): |
| 41 | pass |
| 42 | |
| 43 | def forreq(req, tree): |
| 44 | # XXX: Use proper Content-Type for clients accepting it. |
| 45 | req.ohead["Content-Type"] = "text/html; charset=utf-8" |
| 46 | buf = StringIO.StringIO() |
| 47 | htmlindenter.output(buf, tree, doctype=(doctype, dtd), charset="utf-8") |
| 48 | return [buf.getvalue()] |
| 49 | |
| 50 | def xhtmlresp(callable): |
| 51 | def wrapper(req): |
| 52 | return forreq(req, callable(req)) |
| 53 | return wrapper |