| 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 | class xhtmlcontext(_cons.context): |
| 18 | attrmap = {u"klass": u"class"} |
| 19 | |
| 20 | def addattr(self, node, k, v): |
| 21 | k = unicode(k) |
| 22 | super(xhtmlcontext, self).addattr(node, self.attrmap.get(k, k), v) |
| 23 | |
| 24 | def cons(ctx=None): |
| 25 | if ctx is None: ctx = xhtmlcontext() |
| 26 | return _cons.constructor(ns, htmlelement, ctx) |
| 27 | |
| 28 | def head(title=None, css=None): |
| 29 | h = cons() |
| 30 | head = h.head |
| 31 | if title: |
| 32 | head(h.title(title)) |
| 33 | if isinstance(css, str) or isinstance(css, unicode): |
| 34 | head(h.link(rel="stylesheet", type="text/css", href=css)) |
| 35 | elif css: |
| 36 | for ss in css: |
| 37 | head(h.link(rel="stylesheet", type="text/css", href=ss)) |
| 38 | return head |
| 39 | |
| 40 | class htmlformatter(util.formatter): |
| 41 | allowshort = set([u"br", u"hr", u"img", u"input", u"meta", u"link"]) |
| 42 | def shorttag(self, el): |
| 43 | if el.name in self.allowshort: |
| 44 | super(htmlformatter, self).shorttag(el) |
| 45 | else: |
| 46 | self.handle(">", el) |
| 47 | self.handle("<", el) |
| 48 | |
| 49 | class htmlindenter(util.textindenter, htmlformatter): |
| 50 | pass |
| 51 | |
| 52 | def forreq(req, tree): |
| 53 | # XXX: Use proper Content-Type for clients accepting it. |
| 54 | req.ohead["Content-Type"] = "text/html; charset=utf-8" |
| 55 | buf = StringIO.StringIO() |
| 56 | htmlindenter.output(buf, tree, doctype=(doctype, dtd), charset="utf-8") |
| 57 | ret = buf.getvalue() |
| 58 | req.ohead["Content-Length"] = len(ret) |
| 59 | return [ret] |
| 60 | |
| 61 | def xhtmlresp(callable): |
| 62 | def wrapper(req): |
| 63 | return forreq(req, callable(req)) |
| 64 | wrapper.__wrapped__ = callable |
| 65 | return wrapper |