MoinLight

Annotated moinformat/serialisers/moin/moin.py

314:a1a322d095bd
2022-06-03 Paul Boddie Permit the suppression of macro output if the child nodes are set to None.
paul@38 1
#!/usr/bin/env python
paul@38 2
paul@38 3
"""
paul@38 4
Moin wiki text serialiser.
paul@38 5
paul@314 6
Copyright (C) 2017, 2018, 2021, 2022 Paul Boddie <paul@boddie.org.uk>
paul@38 7
paul@38 8
This program is free software; you can redistribute it and/or modify it under
paul@38 9
the terms of the GNU General Public License as published by the Free Software
paul@38 10
Foundation; either version 3 of the License, or (at your option) any later
paul@38 11
version.
paul@38 12
paul@38 13
This program is distributed in the hope that it will be useful, but WITHOUT
paul@38 14
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
paul@38 15
FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
paul@38 16
details.
paul@38 17
paul@38 18
You should have received a copy of the GNU General Public License along with
paul@38 19
this program.  If not, see <http://www.gnu.org/licenses/>.
paul@38 20
"""
paul@38 21
paul@38 22
from moinformat.serialisers.common import escape_attr, escape_text, Serialiser
paul@38 23
paul@38 24
class MoinSerialiser(Serialiser):
paul@38 25
paul@38 26
    "Serialisation of the page."
paul@38 27
paul@301 28
    input_formats = ["moin", "wiki"]
paul@301 29
    formats = ["moin", "wiki"]
paul@85 30
paul@313 31
    def start_region(self, level, indent, type, args, extra):
paul@38 32
        out = self.out
paul@38 33
        if level:
paul@38 34
            out(" " * indent + "{" * level)
paul@52 35
paul@52 36
        # Produce a header for regions within a top-level region.
paul@52 37
paul@52 38
        if type and type != "inline" and level:
paul@313 39
paul@313 40
            # Obtain individual arguments, excluding the region type.
paul@38 41
paul@313 42
            args = args.split(" ")[1:]
paul@313 43
            args_str = args and (" %s" % " ".join(args)) or ""
paul@313 44
paul@313 45
            out("#!%s%s\n" % (type, args_str))
paul@313 46
paul@313 47
    def end_region(self, level, indent, type, args, extra):
paul@38 48
        out = self.out
paul@38 49
        if level:
paul@67 50
            out("%s%s" % ("}" * level, extra or ""))
paul@38 51
paul@38 52
    def start_block(self):
paul@38 53
        pass
paul@38 54
paul@38 55
    def end_block(self):
paul@38 56
        pass
paul@38 57
paul@38 58
    def start_defitem(self, pad, extra):
paul@122 59
        self.out((extra and extra + "::" or "") + pad)
paul@38 60
paul@38 61
    def end_defitem(self, pad, extra):
paul@38 62
        pass
paul@38 63
paul@122 64
    def start_defterm(self, pad, extra):
paul@38 65
        self.out(pad)
paul@38 66
paul@122 67
    def end_defterm(self, pad, extra):
paul@122 68
        self.out("::" + extra)
paul@38 69
paul@38 70
    def start_emphasis(self):
paul@38 71
        self.out("''")
paul@38 72
paul@38 73
    def end_emphasis(self):
paul@38 74
        self.out("''")
paul@38 75
paul@128 76
    def start_heading(self, level, extra, pad, identifier):
paul@38 77
        self.out(extra + "=" * level + pad)
paul@38 78
paul@38 79
    def end_heading(self, level, pad, extra):
paul@38 80
        self.out(pad + "=" * level + extra)
paul@38 81
paul@38 82
    def start_larger(self):
paul@38 83
        self.out("~+")
paul@38 84
paul@38 85
    def end_larger(self):
paul@38 86
        self.out("+~")
paul@38 87
paul@51 88
    def start_list(self, indent, marker, num):
paul@43 89
        pass
paul@43 90
paul@51 91
    def end_list(self, indent, marker, num):
paul@43 92
        pass
paul@43 93
paul@51 94
    def start_listitem(self, indent, marker, space, num):
paul@55 95
        self.out("%s%s%s%s" % (indent * " ", marker, num and "#%s" % num or "", space))
paul@38 96
paul@51 97
    def end_listitem(self, indent, marker, space, num):
paul@38 98
        pass
paul@38 99
paul@262 100
    def start_macro(self, name, args, nodes, inline):
paul@89 101
paul@314 102
        # Special case of a deliberately unexpanded macro.
paul@314 103
paul@314 104
        if nodes is None:
paul@314 105
            return
paul@314 106
paul@89 107
        # Fallback case for when macros are not replaced.
paul@89 108
paul@89 109
        if not nodes:
paul@89 110
            self.out("<<%s%s>>" % (name, args and "(%s)" % ",".join(args) or ""))
paul@87 111
paul@262 112
    def end_macro(self, inline):
paul@87 113
        pass
paul@87 114
paul@38 115
    def start_monospace(self):
paul@38 116
        self.out("`")
paul@38 117
paul@38 118
    def end_monospace(self):
paul@38 119
        self.out("`")
paul@38 120
paul@38 121
    def start_smaller(self):
paul@38 122
        self.out("~-")
paul@38 123
paul@38 124
    def end_smaller(self):
paul@38 125
        self.out("-~")
paul@38 126
paul@38 127
    def start_strong(self):
paul@38 128
        self.out("'''")
paul@38 129
paul@38 130
    def end_strong(self):
paul@38 131
        self.out("'''")
paul@38 132
paul@48 133
    def start_strikethrough(self):
paul@48 134
        self.out("--(")
paul@48 135
paul@48 136
    def end_strikethrough(self):
paul@48 137
        self.out(")--")
paul@48 138
paul@38 139
    def start_subscript(self):
paul@38 140
        self.out(",,")
paul@38 141
paul@38 142
    def end_subscript(self):
paul@38 143
        self.out(",,")
paul@38 144
paul@38 145
    def start_superscript(self):
paul@38 146
        self.out("^")
paul@38 147
paul@38 148
    def end_superscript(self):
paul@38 149
        self.out("^")
paul@38 150
paul@38 151
    def start_table(self):
paul@38 152
        pass
paul@38 153
paul@38 154
    def end_table(self):
paul@38 155
        pass
paul@38 156
paul@38 157
    def start_table_attrs(self):
paul@38 158
        self.out("<")
paul@38 159
paul@38 160
    def end_table_attrs(self):
paul@38 161
        self.out(">")
paul@38 162
paul@305 163
    def start_table_cell(self, attrs, leading, padding):
paul@38 164
        self.out("||")
paul@38 165
paul@38 166
    def end_table_cell(self):
paul@38 167
        pass
paul@38 168
paul@305 169
    def start_table_row(self, leading, padding):
paul@38 170
        pass
paul@38 171
paul@38 172
    def end_table_row(self, trailing):
paul@38 173
        self.out("||")
paul@38 174
        self.out(trailing)
paul@38 175
paul@38 176
    def start_underline(self):
paul@38 177
        self.out("__")
paul@38 178
paul@38 179
    def end_underline(self):
paul@38 180
        self.out("__")
paul@38 181
paul@116 182
    def anchor(self, target):
paul@116 183
        self.out("((%s))" % target)
paul@116 184
paul@38 185
    def break_(self):
paul@38 186
        self.out("\n")
paul@38 187
paul@151 188
    def comment(self, comment, extra):
paul@151 189
        self.out("##%s%s" % (comment, extra))
paul@151 190
paul@151 191
    def directive(self, directive, extra):
paul@151 192
        self.out("#%s%s" % (directive, extra))
paul@151 193
paul@106 194
    def linebreak(self):
paul@106 195
        self.out(r"\\")
paul@106 196
paul@167 197
    def link(self, target, nodes):
paul@167 198
        self.out("[[%s" % target)
paul@167 199
        for node in nodes:
paul@167 200
            self.out("|")
paul@167 201
            node.to_string(self)
paul@167 202
        self.out("]]")
paul@167 203
paul@167 204
    def link_label(self, nodes):
paul@167 205
        for node in nodes:
paul@167 206
            node.to_string(self)
paul@167 207
paul@167 208
    def link_parameter(self, key_value):
paul@167 209
        if len(key_value) == 1:
paul@167 210
            self.out(key_value[0])
paul@167 211
        else:
paul@167 212
            self.out("=".join(key_value))
paul@167 213
paul@267 214
    def rule(self, height):
paul@267 215
        self.out("-" * (height + 4))
paul@38 216
paul@102 217
    def table_attrs(self, nodes):
paul@102 218
        for node in nodes:
paul@102 219
            node.to_string(self)
paul@102 220
paul@38 221
    def table_attr(self, name, value, concise, quote):
paul@38 222
        if concise:
paul@207 223
            if name == "bgcolor": self.out(value)
paul@38 224
            elif name == "colspan": self.out("-%s" % value)
paul@207 225
            elif name == "align" : self.out(value == "left" and "(" or value == "right" and ")" or ":")
paul@38 226
            elif name == "rowspan": self.out("|%s" % value)
paul@38 227
            elif name == "valign" : self.out(value == "top" and "^" or "v")
paul@38 228
            elif name == "width" : self.out(value)
paul@38 229
        else:
paul@38 230
            self.out("%s%s" % (escape_text(name), value is not None and
paul@38 231
                               "=%s%s%s" % (quote or '"', escape_attr(value), quote or '"') or ""))
paul@38 232
paul@38 233
    def text(self, s):
paul@38 234
        self.out(s)
paul@38 235
paul@167 236
    def transclusion(self, target, nodes):
paul@167 237
        self.out("{{%s" % target)
paul@167 238
        for node in nodes:
paul@167 239
            self.out("|")
paul@167 240
            node.to_string(self)
paul@167 241
        self.out("}}")
paul@167 242
paul@169 243
    def verbatim(self, text):
paul@169 244
        self.out("<<<")
paul@169 245
        self.out(text)
paul@169 246
        self.out(">>>")
paul@169 247
paul@39 248
serialiser = MoinSerialiser
paul@39 249
paul@38 250
# vim: tabstop=4 expandtab shiftwidth=4