1 #!/usr/bin/env python 2 3 """ 4 HTML serialiser. 5 6 Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 """ 21 22 from moinformat.serialisers.common import escape_attr, escape_text, Serialiser 23 24 class HTMLSerialiser(Serialiser): 25 26 "Serialisation of the page." 27 28 def _region_tag(self, type): 29 30 # NOTE: Need to support types in general. 31 32 type = type and type.split()[0] 33 34 if type == "inline": 35 return "tt" 36 elif type in (None, "python"): 37 return "pre" 38 else: 39 return "span" 40 41 def start_region(self, level, indent, type, extra): 42 l = [] 43 out = l.append 44 if level: 45 out("level-%d" % level) 46 47 if indent: 48 out("indent-%d" % indent) 49 50 # NOTE: Encode type details for CSS. 51 52 out("type-%s" % escape_attr(type or "opaque")) 53 54 tag = self._region_tag(type) 55 self.out("<%s class='%s'>" % (tag, " ".join(l))) 56 57 def end_region(self, level, indent, type, extra): 58 tag = self._region_tag(type) 59 self.out("</%s>" % tag) 60 61 def start_block(self): 62 self.out("<p>") 63 64 def end_block(self): 65 self.out("</p>") 66 67 def start_defitem(self, pad, extra): 68 self.out("<dd>") 69 70 def end_defitem(self, pad, extra): 71 self.out("</dd>") 72 73 def start_defterm(self, pad): 74 self.out("<dt>") 75 76 def end_defterm(self, pad): 77 self.out("</dt>") 78 79 def start_emphasis(self): 80 self.out("<em>") 81 82 def end_emphasis(self): 83 self.out("</em>") 84 85 def start_heading(self, level, extra, pad): 86 self.out("<h%d>" % level) 87 88 def end_heading(self, level, pad, extra): 89 self.out("</h%d>" % level) 90 91 def start_larger(self): 92 self.out("<big>") 93 94 def end_larger(self): 95 self.out("</big>") 96 97 def start_link(self, target): 98 self.out('<a href="%s">' % escape_attr(target)) 99 100 def end_link(self): 101 self.out("</a>") 102 103 def start_linktext(self): 104 pass 105 106 def end_linktext(self): 107 pass 108 109 list_tags = { 110 "i" : "lower-roman", 111 "I" : "upper-roman", 112 "a" : "lower-latin", 113 "A" : "upper-latin", 114 } 115 116 def _get_list_tag(self, marker): 117 if marker: 118 if marker[0].isdigit(): 119 return "ol", "decimal" 120 style_type = self.list_tags.get(marker[0]) 121 if style_type: 122 return "ol", style_type 123 124 return "ul", None 125 126 def start_list(self, indent, marker, num): 127 tag, style_type = self._get_list_tag(marker) 128 style = style_type and ' style="list-style-type: %s"' % escape_attr(style_type) or "" 129 start = style_type and num is not None and ' start="%s"' % escape_attr(num) or "" 130 self.out("<%s%s%s>" % (tag, style, start)) 131 132 def end_list(self, indent, marker, num): 133 tag, style = self._get_list_tag(marker) 134 self.out("</%s>" % tag) 135 136 def start_listitem(self, indent, marker, space, num): 137 self.out("<li>") 138 139 def end_listitem(self, indent, marker, space, num): 140 self.out("</li>") 141 142 def start_monospace(self): 143 self.out("<tt>") 144 145 def end_monospace(self): 146 self.out("</tt>") 147 148 def start_smaller(self): 149 self.out("<small>") 150 151 def end_smaller(self): 152 self.out("</small>") 153 154 def start_strikethrough(self): 155 self.out("<del>") 156 157 def end_strikethrough(self): 158 self.out("</del>") 159 160 def start_strong(self): 161 self.out("<strong>") 162 163 def end_strong(self): 164 self.out("</strong>") 165 166 def start_subscript(self): 167 self.out("<sub>") 168 169 def end_subscript(self): 170 self.out("</sub>") 171 172 def start_superscript(self): 173 self.out("<sup>") 174 175 def end_superscript(self): 176 self.out("</sup>") 177 178 def start_table(self): 179 self.out("<table>") 180 181 def end_table(self): 182 self.out("</table>") 183 184 def start_table_attrs(self): 185 pass 186 187 def end_table_attrs(self): 188 pass 189 190 def start_table_cell(self, attrs): 191 self.out("<td") 192 if attrs and not attrs.empty(): 193 attrs.to_string(self) 194 self.out(">") 195 196 def end_table_cell(self): 197 self.out("</td>") 198 199 def start_table_row(self): 200 self.out("<tr>") 201 202 def end_table_row(self, trailing): 203 self.out("</tr>") 204 205 def start_underline(self): 206 self.out("<span style='text-decoration: underline'>") 207 208 def end_underline(self): 209 self.out("</span>") 210 211 def break_(self): 212 pass 213 214 def rule(self, length): 215 self.out("<hr style='height: %dpt' />" % min(length, 10)) 216 217 def table_attr(self, name, value, concise, quote): 218 self.out(" %s%s" % (escape_text(name), value is not None and 219 "='%s'" % escape_attr(value) or "")) 220 221 def text(self, s): 222 self.out(escape_text(s)) 223 224 serialiser = HTMLSerialiser 225 226 # vim: tabstop=4 expandtab shiftwidth=4