1# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. 2# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr 3# 4# This file is part of logilab-common. 5# 6# logilab-common is free software: you can redistribute it and/or modify it 7# under the terms of the GNU Lesser General Public License as published by the 8# Free Software Foundation, either version 2.1 of the License, 9# or (at your option) any later version. 10# 11# logilab-common is distributed in the hope that it will be useful, but WITHOUT 12# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 14# details. 15# 16# You should have received a copy of the GNU Lesser General Public License 17# along with logilab-common. If not, see <http://www.gnu.org/licenses/>. 18"""HTML formatting drivers for ureports""" 19__docformat__ = "restructuredtext en" 20 21 22from logilab.common.ureports import BaseWriter 23from logilab.common.ureports.nodes import ( 24 Section, 25 Title, 26 Table, 27 List, 28 Paragraph, 29 Link, 30 VerbatimText, 31 Text, 32) 33from typing import Any 34 35 36class HTMLWriter(BaseWriter): 37 """format layouts as HTML""" 38 39 def __init__(self, snippet: int = None) -> None: 40 super(HTMLWriter, self).__init__() 41 self.snippet = snippet 42 43 def handle_attrs(self, layout: Any) -> str: 44 """get an attribute string from layout member attributes""" 45 attrs = "" 46 klass = getattr(layout, "klass", None) 47 if klass: 48 attrs += ' class="%s"' % klass 49 nid = getattr(layout, "id", None) 50 if nid: 51 attrs += ' id="%s"' % nid 52 return attrs 53 54 def begin_format(self, layout: Any) -> None: 55 """begin to format a layout""" 56 super(HTMLWriter, self).begin_format(layout) 57 if self.snippet is None: 58 self.writeln("<html>") 59 self.writeln("<body>") 60 61 def end_format(self, layout: Any) -> None: 62 """finished to format a layout""" 63 if self.snippet is None: 64 self.writeln("</body>") 65 self.writeln("</html>") 66 67 def visit_section(self, layout: Section) -> None: 68 """display a section as html, using div + h[section level]""" 69 self.section += 1 70 self.writeln("<div%s>" % self.handle_attrs(layout)) 71 self.format_children(layout) 72 self.writeln("</div>") 73 self.section -= 1 74 75 def visit_title(self, layout: Title) -> None: 76 """display a title using <hX>""" 77 self.write("<h%s%s>" % (self.section, self.handle_attrs(layout))) 78 self.format_children(layout) 79 self.writeln("</h%s>" % self.section) 80 81 def visit_table(self, layout: Table) -> None: 82 """display a table as html""" 83 self.writeln("<table%s>" % self.handle_attrs(layout)) 84 table_content = self.get_table_content(layout) 85 for i in range(len(table_content)): 86 row = table_content[i] 87 if i == 0 and layout.rheaders: 88 self.writeln('<tr class="header">') 89 elif i + 1 == len(table_content) and layout.rrheaders: 90 self.writeln('<tr class="header">') 91 else: 92 self.writeln('<tr class="%s">' % (i % 2 and "even" or "odd")) 93 for j in range(len(row)): 94 cell = row[j] or " " 95 if ( 96 (layout.rheaders and i == 0) 97 or (layout.cheaders and j == 0) 98 or (layout.rrheaders and i + 1 == len(table_content)) 99 or (layout.rcheaders and j + 1 == len(row)) 100 ): 101 self.writeln("<th>%s</th>" % cell) 102 else: 103 self.writeln("<td>%s</td>" % cell) 104 self.writeln("</tr>") 105 self.writeln("</table>") 106 107 def visit_list(self, layout: List) -> None: 108 """display a list as html""" 109 self.writeln("<ul%s>" % self.handle_attrs(layout)) 110 for row in list(self.compute_content(layout)): 111 self.writeln("<li>%s</li>" % row) 112 self.writeln("</ul>") 113 114 def visit_paragraph(self, layout: Paragraph) -> None: 115 """display links (using <p>)""" 116 self.write("<p>") 117 self.format_children(layout) 118 self.write("</p>") 119 120 def visit_span(self, layout): 121 """display links (using <p>)""" 122 self.write("<span%s>" % self.handle_attrs(layout)) 123 self.format_children(layout) 124 self.write("</span>") 125 126 def visit_link(self, layout: Link) -> None: 127 """display links (using <a>)""" 128 self.write(' <a href="%s"%s>%s</a>' % (layout.url, self.handle_attrs(layout), layout.label)) 129 130 def visit_verbatimtext(self, layout: VerbatimText) -> None: 131 """display verbatim text (using <pre>)""" 132 self.write("<pre>") 133 self.write(layout.data.replace("&", "&").replace("<", "<")) 134 self.write("</pre>") 135 136 def visit_text(self, layout: Text) -> None: 137 """add some text""" 138 data = layout.data 139 if layout.escaped: 140 data = data.replace("&", "&").replace("<", "<") 141 self.write(data) 142