1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/moinconvert Mon Nov 26 16:05:50 2018 +0100
1.3 @@ -0,0 +1,313 @@
1.4 +#!/usr/bin/env python
1.5 +
1.6 +"""
1.7 +Moin wiki format converter.
1.8 +
1.9 +Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
1.10 +
1.11 +This program is free software; you can redistribute it and/or modify it under
1.12 +the terms of the GNU General Public License as published by the Free Software
1.13 +Foundation; either version 3 of the License, or (at your option) any later
1.14 +version.
1.15 +
1.16 +This program is distributed in the hope that it will be useful, but WITHOUT
1.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.18 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
1.19 +details.
1.20 +
1.21 +You should have received a copy of the GNU General Public License along with
1.22 +this program. If not, see <http://www.gnu.org/licenses/>.
1.23 +"""
1.24 +
1.25 +from moinformat import make_parser, make_serialiser, Metadata, parse, serialise
1.26 +from os.path import split
1.27 +import sys
1.28 +
1.29 +# Long messages.
1.30 +
1.31 +message_all_with_filenames = """\
1.32 +Using --all overrides any indicated pagenames. Either --all or the filenames
1.33 +should be omitted."""
1.34 +
1.35 +message_explicit_pagenames = """\
1.36 +Explicit pagenames (indicated using --pagename) are only to be specified when
1.37 +providing filenames without an input directory (indicated using --input-dir).
1.38 +
1.39 +To indicate pagenames within an input directory, omit any --pagename flags."""
1.40 +
1.41 +
1.42 +
1.43 +# Options management.
1.44 +
1.45 +def getmapping(mappings):
1.46 +
1.47 + """
1.48 + Return the given 'mappings' - a collection of key-then-value items - as a
1.49 + dictionary.
1.50 + """
1.51 +
1.52 + mapping = {}
1.53 + key = None
1.54 +
1.55 + for arg in mappings:
1.56 + if key is None:
1.57 + key = arg
1.58 + else:
1.59 + mapping[key] = arg
1.60 + key = None
1.61 +
1.62 + return mapping
1.63 +
1.64 +def getvalue(values, default=None):
1.65 +
1.66 + """
1.67 + Return the first value from 'values' or 'default' if 'values' is empty or
1.68 + the first value tests as false.
1.69 + """
1.70 +
1.71 + return values and values[0] or default
1.72 +
1.73 +
1.74 +
1.75 +# Main program.
1.76 +
1.77 +def main():
1.78 +
1.79 + "Interpret program options and perform the conversion."
1.80 +
1.81 + dirname, progname = split(sys.argv[0])
1.82 + args = sys.argv[1:]
1.83 +
1.84 + # Option values.
1.85 +
1.86 + l = filenames = []
1.87 + formats = []
1.88 + input_dir_types = []
1.89 + input_dirs = []
1.90 + input_encodings = []
1.91 + input_page_seps = []
1.92 + mappings = []
1.93 + output_dirs = []
1.94 + output_encodings = []
1.95 + theme_names = []
1.96 + pagenames = []
1.97 + root_pagenames = []
1.98 +
1.99 + # Flags.
1.100 +
1.101 + all = False
1.102 + fragment = False
1.103 + macros = False
1.104 + tree = False
1.105 +
1.106 + for arg in args:
1.107 +
1.108 + # Detect tree output.
1.109 +
1.110 + if arg == "--tree":
1.111 + tree = True
1.112 +
1.113 + # Detect macro evaluation.
1.114 +
1.115 + elif arg == "--macros":
1.116 + macros = True
1.117 +
1.118 + # Detect all documents.
1.119 +
1.120 + elif arg == "--all":
1.121 + all = True
1.122 +
1.123 + # Detect fragment output (if serialising).
1.124 +
1.125 + elif arg == "--fragment":
1.126 + fragment = True
1.127 +
1.128 + # Switch to collecting formats.
1.129 +
1.130 + elif arg == "--format":
1.131 + l = formats
1.132 + continue
1.133 +
1.134 + # Switch to collecting input locations.
1.135 +
1.136 + elif arg == "--input-dir":
1.137 + l = input_dirs
1.138 + continue
1.139 +
1.140 + # Switch to collecting input context types.
1.141 +
1.142 + elif arg == "--input-dir-type":
1.143 + l = input_dir_types
1.144 + continue
1.145 +
1.146 + # Switch to collecting input encodings.
1.147 +
1.148 + elif arg == "--input-encoding":
1.149 + l = input_encodings
1.150 + continue
1.151 +
1.152 + # Switch to collecting input page hierarchy separators.
1.153 +
1.154 + elif arg == "--input-page-sep":
1.155 + l = input_page_seps
1.156 + continue
1.157 +
1.158 + # Switch to collecting mappings.
1.159 +
1.160 + elif arg == "--mapping":
1.161 + l = mappings
1.162 + continue
1.163 +
1.164 + # Switch to collecting output locations.
1.165 +
1.166 + elif arg == "--output-dir":
1.167 + l = output_dirs
1.168 + continue
1.169 +
1.170 + # Switch to collecting output encodings.
1.171 +
1.172 + elif arg == "--output-encoding":
1.173 + l = output_encodings
1.174 + continue
1.175 +
1.176 + # Switch to collecting page names.
1.177 +
1.178 + elif arg == "--pagename":
1.179 + l = pagenames
1.180 + continue
1.181 +
1.182 + # Switch to collecting root page names.
1.183 +
1.184 + elif arg == "--root":
1.185 + l = root_pagenames
1.186 + continue
1.187 +
1.188 + # Switch to collecting theme names.
1.189 +
1.190 + elif arg == "--theme":
1.191 + l = theme_names
1.192 + continue
1.193 +
1.194 + # Collect options and arguments.
1.195 +
1.196 + else:
1.197 + l.append(arg)
1.198 +
1.199 + # Collect multiple mappings.
1.200 +
1.201 + if l is mappings:
1.202 + continue
1.203 +
1.204 + # Collect filenames normally.
1.205 +
1.206 + l = filenames
1.207 +
1.208 + format = formats and formats[0] or "html"
1.209 + input_dir = getvalue(input_dirs)
1.210 + output_dir = getvalue(output_dirs)
1.211 +
1.212 + # Define metadata.
1.213 +
1.214 + metadata = Metadata({
1.215 + "input_context" : input_dir and \
1.216 + getvalue(input_dir_types, "directory") or \
1.217 + "standalone",
1.218 + "input_encoding" : getvalue(input_encodings),
1.219 + "input_filename" : input_dir,
1.220 + "input_separator" : getvalue(input_page_seps),
1.221 + "link_format" : format,
1.222 + "mapping" : getmapping(mappings),
1.223 + "output_context" : output_dir and "directory" or "standalone",
1.224 + "output_encoding" : getvalue(output_encodings),
1.225 + "output_format" : format,
1.226 + "output_filename" : output_dir,
1.227 + "root_pagename" : getvalue(root_pagenames, "FrontPage"),
1.228 + "theme_name" : not fragment and \
1.229 + "%s.%s" % (getvalue(theme_names, "default"), format) or None,
1.230 + })
1.231 +
1.232 + # Define the input context and theme.
1.233 +
1.234 + input = metadata.get_input()
1.235 + theme = metadata.get_theme()
1.236 +
1.237 + # Treat filenames as pagenames if an input directory is indicated and if no
1.238 + # pagenames are explicitly specified.
1.239 +
1.240 + if input_dir:
1.241 + if pagenames:
1.242 + print >>sys.stderr, message_explicit_pagenames
1.243 + sys.exit(1)
1.244 +
1.245 + if all:
1.246 + if filenames:
1.247 + print >>sys.stderr, message_all_with_filenames
1.248 + sys.exit(1)
1.249 + else:
1.250 + filenames = input.all()
1.251 +
1.252 + pagenames = filenames
1.253 + filenames = []
1.254 +
1.255 + # Open each file or page, parse the content, serialise the document.
1.256 +
1.257 + for pagename, filename in map(None, pagenames, filenames):
1.258 +
1.259 + # Define a pagename if missing.
1.260 +
1.261 + pagename = pagename or split(filename)[-1]
1.262 + metadata.set("pagename", pagename)
1.263 +
1.264 + # Read either from a filename or using a pagename.
1.265 +
1.266 + if filename:
1.267 + pagetext = input.readfile(filename)
1.268 + else:
1.269 + pagetext = input.readpage(pagename)
1.270 +
1.271 + # Parse the page content.
1.272 +
1.273 + p = make_parser(metadata)
1.274 + d = parse(pagetext, p)
1.275 +
1.276 + if macros:
1.277 + p.evaluate_macros()
1.278 +
1.279 + # Show a document tree for debugging purposes, if requested.
1.280 +
1.281 + if tree:
1.282 + print d.prettyprint()
1.283 + continue
1.284 +
1.285 + # Otherwise, serialise the document.
1.286 +
1.287 + # Obtain a serialiser using the configuration.
1.288 +
1.289 + serialiser = make_serialiser(metadata)
1.290 + outtext = serialise(d, serialiser)
1.291 +
1.292 + # With a theme, apply it to the text.
1.293 +
1.294 + if theme:
1.295 + outtext = theme.apply(outtext)
1.296 +
1.297 + # If reading from a file, show the result. Otherwise, write to the
1.298 + # output context.
1.299 +
1.300 + output = metadata.get_output()
1.301 +
1.302 + if not output.can_write():
1.303 + print outtext
1.304 + else:
1.305 + output.writepage(outtext, pagename)
1.306 + print >>sys.stderr, pagename
1.307 +
1.308 + # Install any theme resources.
1.309 +
1.310 + if theme:
1.311 + theme.install_resources()
1.312 +
1.313 +if __name__ == "__main__":
1.314 + main()
1.315 +
1.316 +# vim: tabstop=4 expandtab shiftwidth=4