koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 1 | from typing import Optional, List, Callable |
| 2 | |
| 3 | |
| 4 | import xmlbuilder3 |
| 5 | |
| 6 | |
| 7 | eol = "<br>" |
| 8 | |
| 9 | |
| 10 | def tag(name: str) -> Callable[[str], str]: |
| 11 | def closure(data: str) -> str: |
| 12 | return "<{}>{}</{}>".format(name, data, name) |
| 13 | return closure |
| 14 | |
| 15 | |
| 16 | H3 = tag("H3") |
| 17 | H2 = tag("H2") |
| 18 | center = tag("center") |
| 19 | |
| 20 | |
| 21 | def img(link: str) -> str: |
koder aka kdanilov | 108ac36 | 2017-01-19 20:17:16 +0200 | [diff] [blame] | 22 | return '<img src="{}">'.format(link) |
koder aka kdanilov | a732a60 | 2017-02-01 20:29:56 +0200 | [diff] [blame] | 23 | |
| 24 | |
| 25 | def table(caption: str, headers: Optional[List[str]], data: List[List[str]]) -> str: |
| 26 | doc = xmlbuilder3.XMLBuilder("table", |
| 27 | **{"class": "table table-bordered table-striped table-condensed table-hover", |
| 28 | "style": "width: auto;"}) |
| 29 | |
| 30 | doc.caption.H3.center(caption) |
| 31 | |
| 32 | if headers is not None: |
| 33 | with doc.thead: |
| 34 | with doc.tr: |
| 35 | for header in headers: |
| 36 | doc.th(header) |
| 37 | |
| 38 | with doc.tbody: |
| 39 | for line in data: |
| 40 | with doc.tr: |
| 41 | for vl in line: |
| 42 | doc.td(vl) |
| 43 | |
| 44 | return xmlbuilder3.tostr(doc).split("\n", 1)[1] |