Commit | Line | Data |
---|---|---|
ff79cdbf FT |
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 | ||
a573465e FT |
17 | class xhtmlcontext(_cons.context): |
18 | attrmap = {u"klass": u"class"} | |
19 | ||
20 | def addattr(self, node, k, v): | |
21 | k = unicode(k) | |
4c4dcf7a | 22 | super(xhtmlcontext, self).addattr(node, self.attrmap.get(k, k), v) |
a573465e | 23 | |
ff79cdbf | 24 | def cons(ctx=None): |
a573465e | 25 | if ctx is None: ctx = xhtmlcontext() |
ff79cdbf FT |
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): | |
d11a27e2 | 41 | allowshort = set([u"br", u"hr", u"img", u"input", u"meta", u"link"]) |
ff79cdbf FT |
42 | def element(self, el, **extra): |
43 | if el.name in self.allowshort: | |
44 | super(htmlformatter, self).element(el, **extra) | |
45 | else: | |
46 | self.longtag(el, **extra) | |
47 | ||
48 | class htmlindenter(util.indenter, htmlformatter): | |
49 | pass | |
50 | ||
51 | def forreq(req, tree): | |
52 | # XXX: Use proper Content-Type for clients accepting it. | |
53 | req.ohead["Content-Type"] = "text/html; charset=utf-8" | |
54 | buf = StringIO.StringIO() | |
55 | htmlindenter.output(buf, tree, doctype=(doctype, dtd), charset="utf-8") | |
a7b35f84 FT |
56 | ret = buf.getvalue() |
57 | req.ohead["Content-Length"] = len(ret) | |
58 | return [ret] | |
ff79cdbf FT |
59 | |
60 | def xhtmlresp(callable): | |
61 | def wrapper(req): | |
62 | return forreq(req, callable(req)) | |
d22f3483 | 63 | wrapper.__wrapped__ = callable |
ff79cdbf | 64 | return wrapper |