Commit | Line | Data |
---|---|---|
62551769 FT |
1 | import xml.dom.minidom, io |
2 | from . import cons as _cons | |
3 | from . import util | |
ff79cdbf FT |
4 | dom = xml.dom.minidom.getDOMImplementation() |
5 | ||
62551769 FT |
6 | ns = "http://www.w3.org/1999/xhtml" |
7 | doctype = "-//W3C//DTD XHTML 1.1//EN" | |
8 | dtd = "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" | |
ff79cdbf FT |
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 | 17 | class xhtmlcontext(_cons.context): |
26648796 | 18 | attrmap = {"klass": "class"} |
a573465e FT |
19 | |
20 | def addattr(self, node, k, v): | |
26648796 FT |
21 | k = str(k) |
22 | node.attrs[self.attrmap.get(k, k)] = str(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)) | |
62551769 | 33 | if isinstance(css, str) or isinstance(css, bytes): |
ff79cdbf FT |
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): | |
3e91bb19 | 41 | allowshort = set(["br", "hr", "img", "input", "meta", "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" | |
dc437c45 | 54 | buf = io.BytesIO() |
ff79cdbf | 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 |