The order of XML attributes is now retained.
[philipp/winterrodeln/wrpylib.git] / wrpylib / mwmarkup.py
1 """For parsing MediaWiki text, we rely on the package mwparserfromhell (https://github.com/earwig/mwparserfromhell).
2 This module just contains a few additional useful functions.
3
4 Other Python MediaWiki parsers:
5 * py-wikimarkup https://github.com/dcramer/py-wikimarkup
6 * mwlib http://code.pediapress.com/wiki/wiki
7 * https://www.mediawiki.org/wiki/Alternative_parsers
8 """
9 from typing import Optional, Dict, List
10
11 from mwparserfromhell.nodes import Template
12
13
14 def create_template(name: str, args: List[str], kwargs: Optional[Dict[str, str]] = None) -> Template:
15     """Creates a mwparserfromhell template with from a dictionary (string: string)
16
17     :param name: Name of the template
18     :param args: list of unnamed parameters
19     :param kwargs: named parameters
20     """
21     template = Template(name)
22     for i, value in enumerate(args, 1):
23         template.add(str(i), value, False)
24     if kwargs is not None:
25         for key, value in kwargs.items():
26             template.add(key, value, True)
27     return template
28
29
30 def format_template_table(template: Template, keylen: Optional[int] = None):
31     """Reformat the given template to be tabular. The template is modified in-place
32
33     >>> template
34     {{foo|bar|bazz=7}}
35     >>> format_template_table(template)
36     {{foo
37     | bar
38     | bazz = 7
39     }}
40
41     :param template: MediaWiki template to be formatted
42     :param keylen: length of the keys or None for automatic determination
43     """
44     if keylen is None:
45         shown_keys = [len(param.name.strip()) for param in template.params if param.showkey]
46         keylen = max(shown_keys) if shown_keys else 0
47     template.name = f'{template.name.strip()}\n'
48     for param in template.params:
49         if param.showkey:
50             param.name = ' {{:{}}} '.format(keylen).format(param.name.strip())
51         value = param.value.strip()
52         if len(value) > 0:
53             param.value = f' {value}\n'
54         else:
55             param.value = '\n'
56
57
58 def format_template_oneline(template: Template):
59     """Formats a template like this: {{template_name|param| }}
60     (whitespace is stripped and empty parameters are replaced with one space).
61     The template is modified in-place."""
62     template.name = template.name.strip()
63     for param in template.params:
64         if param.showkey:
65             param.name = param.name.strip()
66         value = param.value.strip()
67         if value == '':
68             value = ' '
69         param.value = value
70
71
72 def dbkey_to_title(value: str) -> str:
73     """Converts a article database key to a article title. Private function secureAndSplit() of the Title class
74     on line 3316 of includes/Title.php says:
75     $this->mTextform = str_replace( '_', ' ', $this->mDbkeyform );
76     No check for None because a missing title is an error."""
77     return value.replace('_', ' ')