1.1 --- a/moinformat/parsers/moin.py Tue Aug 14 22:33:30 2018 +0200
1.2 +++ b/moinformat/parsers/moin.py Thu Aug 16 17:51:57 2018 +0200
1.3 @@ -37,11 +37,12 @@
1.4
1.5 from moinformat.tree.moin import Anchor, Break, Comment, DefItem, DefTerm, \
1.6 Directive, FontStyle, Heading, Larger, \
1.7 - LineBreak, Link, List, ListItem, Macro, \
1.8 - Monospace, Region, Rule, Smaller, \
1.9 - Strikethrough, Subscript, Superscript, Table, \
1.10 - TableAttr, TableAttrs, TableCell, TableRow, \
1.11 - Text, Underline
1.12 + LineBreak, Link, LinkLabel, LinkParameter, \
1.13 + List, ListItem, Macro, Monospace, Region, \
1.14 + Rule, Smaller, Strikethrough, Subscript, \
1.15 + Superscript, Table, TableAttr, TableAttrs, \
1.16 + TableCell, TableRow, Text, Transclusion, \
1.17 + Underline
1.18
1.19 join = "".join
1.20
1.21 @@ -546,6 +547,39 @@
1.22 def parse_underline(self, region):
1.23 self.parse_inline(region, Underline, "underline")
1.24
1.25 + # Link formatting handlers.
1.26 +
1.27 + def _parse_link(self, region, cls, pattern_names):
1.28 + target = self.match_group("target")
1.29 + end = self.match_group("end")
1.30 +
1.31 + span = cls([], target)
1.32 +
1.33 + # Obtain the extra details.
1.34 +
1.35 + if not end:
1.36 + cls = LinkLabel
1.37 +
1.38 + # Introduce a label or parameter for each separated region.
1.39 +
1.40 + while True:
1.41 + param = cls([])
1.42 + self.parse_region_details(param, pattern_names)
1.43 + span.append(param)
1.44 +
1.45 + if self.matching_pattern() != "linksep":
1.46 + break
1.47 +
1.48 + cls = LinkParameter
1.49 +
1.50 + region.append_inline(span)
1.51 +
1.52 + def parse_link(self, region):
1.53 + self._parse_link(region, Link, self.link_pattern_names)
1.54 +
1.55 + def parse_transclusion(self, region):
1.56 + self._parse_link(region, Transclusion, self.transclusion_pattern_names)
1.57 +
1.58
1.59
1.60 # Complete inline pattern handlers.
1.61 @@ -558,12 +592,6 @@
1.62 def parse_linebreak(self, region):
1.63 region.append_inline(LineBreak())
1.64
1.65 - def parse_link(self, region):
1.66 - target = self.match_group("target")
1.67 - text = self.match_group("text")
1.68 - link = Link(text and [Text(text)] or [], target)
1.69 - region.append_inline(link)
1.70 -
1.71 def parse_macro(self, region):
1.72 name = self.match_group("name")
1.73 args = self.match_group("args")
1.74 @@ -698,6 +726,19 @@
1.75 "super" : r"\^", # ^
1.76 "underline" : r"__", # __
1.77
1.78 + # Links and transclusions may start inline spans.
1.79 +
1.80 + "link" : join((r"\[\[", # [[
1.81 + group("target", ".*?"), # ...
1.82 + choice((r"\|", # |
1.83 + group("end", r"]]"))))), # ]]
1.84 +
1.85 + "transclusion" : join((r"\{\{", # {{
1.86 + excl(r"\{"), # not-{
1.87 + group("target", ".*?"), # ...
1.88 + choice((r"\|", # |
1.89 + group("end", r"}}"))))), # }}
1.90 +
1.91 # Complete inline patterns are for markup features that do not support
1.92 # arbitrary content within them:
1.93
1.94 @@ -707,12 +748,6 @@
1.95
1.96 "linebreak" : r"\\\\", # \\
1.97
1.98 - "link" : join((r"\[\[", # [[
1.99 - group("target", ".*?"), # target
1.100 - optional(join((r"\|", # |
1.101 - group("text", r"\E*?")))), # text-incl-nl (optional)
1.102 - "]]")), # ]]
1.103 -
1.104 "macro" : join(("<<", # <<
1.105 group("name", "\w+?"), # digit-letter...
1.106 optional(join((r"\(", # ( (optional)
1.107 @@ -723,11 +758,13 @@
1.108 # Ending patterns for inline features:
1.109
1.110 "largerend" : r"\+~", # +~
1.111 + "linkend" : r"]]", # ]]
1.112 "monospaceend" : r"`", # `
1.113 "smallerend" : r"-~", # -~
1.114 "strikeend" : r"\)--", # )--
1.115 "subend" : r",,", # ,,
1.116 "superend" : r"\^", # ^
1.117 + "transclusionend": r"}}", # }}
1.118 "underlineend" : r"__", # __
1.119
1.120 # Heading contents:
1.121 @@ -736,6 +773,10 @@
1.122 group("level", "=+"), # =...
1.123 group("extra", r"\N*\n"))), # ws (optional) nl
1.124
1.125 + # Link/transclusion contents:
1.126 +
1.127 + "linksep" : r"\|", # |
1.128 +
1.129 # List contents:
1.130
1.131 "deftermend" : join(("::", group("pad", r"\s*?\n"))), # ::
1.132 @@ -801,12 +842,18 @@
1.133 "valign", "width"
1.134 ]
1.135
1.136 - inline_pattern_names = [
1.137 - "anchor", "fontstyle", "larger", "linebreak", "link", "macro",
1.138 + inline_without_links_pattern_names = [
1.139 + "anchor", "fontstyle", "larger", "linebreak", "macro",
1.140 "monospace", "regionstart", "smaller", "strike", "sub", "super",
1.141 "underline",
1.142 ]
1.143
1.144 + inline_pattern_names = inline_without_links_pattern_names + [
1.145 + "link", "transclusion"]
1.146 +
1.147 + link_pattern_names = inline_without_links_pattern_names + [
1.148 + "linkend", "linksep", "transclusion"]
1.149 +
1.150 list_pattern_names = [
1.151 "listitem", "listitem_alpha", "listitem_dot", "listitem_num",
1.152 "listitem_roman",
1.153 @@ -823,6 +870,9 @@
1.154 "tableattrs", "tablecell", "tableend"
1.155 ]
1.156
1.157 + transclusion_pattern_names = inline_without_links_pattern_names + [
1.158 + "linksep", "transclusionend"]
1.159 +
1.160 # The region pattern names are specifically used by the common parser
1.161 # functionality.
1.162
1.163 @@ -856,6 +906,8 @@
1.164 "largerend" : end_region,
1.165 "linebreak" : parse_linebreak,
1.166 "link" : parse_link,
1.167 + "linkend" : end_region,
1.168 + "linksep" : end_region,
1.169 "macro" : parse_macro,
1.170 "listitemend" : end_region,
1.171 "listitem" : parse_listitem,
1.172 @@ -882,6 +934,8 @@
1.173 "tablerow" : parse_table_row,
1.174 "tablecell" : end_region,
1.175 "tableend" : end_region,
1.176 + "transclusion" : parse_transclusion,
1.177 + "transclusionend" : end_region,
1.178 "underline" : parse_underline,
1.179 "underlineend" : end_region,
1.180 "valign" : parse_valign,