1.1 --- a/moinformat/parsers/common.py Sat Jul 14 16:17:36 2018 +0200
1.2 +++ b/moinformat/parsers/common.py Sat Jul 14 23:37:30 2018 +0200
1.3 @@ -256,14 +256,14 @@
1.4
1.5 # Top-level parser handler methods.
1.6
1.7 - def parse_region(self, level=0, indent=0):
1.8 + def parse_region(self, level=0, indent=0, type=None):
1.9
1.10 """
1.11 Parse the data to populate a region with the given 'level' at the given
1.12 - 'indent'.
1.13 + 'indent' having the given initial 'type'.
1.14 """
1.15
1.16 - region = Region([], level, indent)
1.17 + region = Region([], level, indent, type)
1.18
1.19 # Parse section headers, then parse according to region type.
1.20
1.21 @@ -278,6 +278,12 @@
1.22 Use configured parsers to parse 'region' based on its type.
1.23 """
1.24
1.25 + # Handle potentially inline regions.
1.26 +
1.27 + if region.type == "inline":
1.28 + self.parse_region_inline(region)
1.29 + return
1.30 +
1.31 # Find an appropriate parser given the type.
1.32
1.33 parser = self.get_parser(region.type)
1.34 @@ -306,6 +312,20 @@
1.35 region.transparent = False
1.36 self.parse_region_details(region, ["regionend"])
1.37
1.38 + def parse_region_inline(self, region):
1.39 +
1.40 + "Parse the data to populate an inline 'region'."
1.41 +
1.42 + region.transparent = False
1.43 + self.parse_region_details(region, ["regionend"])
1.44 +
1.45 + # Reset the type if the region was not inline.
1.46 +
1.47 + if region.type == "inline":
1.48 + first = region.nodes and region.nodes[0]
1.49 + if first and isinstance(first, Text) and first.multiline():
1.50 + region.type = None
1.51 +
1.52 # Parsing utilities.
1.53
1.54 def parse_region_details(self, region, pattern_names, strict=False):
2.1 --- a/moinformat/parsers/moin.py Sat Jul 14 16:17:36 2018 +0200
2.2 +++ b/moinformat/parsers/moin.py Sat Jul 14 23:37:30 2018 +0200
2.3 @@ -55,7 +55,7 @@
2.4 """
2.5
2.6 self.items = self.get_items(s)
2.7 - self.region = Region([])
2.8 + self.region = Region([], type="moin")
2.9
2.10 # Parse page header.
2.11
2.12 @@ -278,7 +278,7 @@
2.13
2.14 indent = len(self.read_match(2))
2.15 level = len(self.read_match(3))
2.16 - self.add_node(region, self.parse_region(level, indent))
2.17 + self.add_node(region, self.parse_region(level, indent, "inline"))
2.18 self.new_block(region)
2.19
2.20 def parse_section_end(self, region):
2.21 @@ -459,8 +459,8 @@
2.22
2.23 syntax = {
2.24 # Page regions:
2.25 - "regionstart" : r"((^\N*)([{]{3,}))", # {{{...
2.26 - "regionend" : r"^\N*([}]{3,})", # }}}...
2.27 + "regionstart" : r"((\N*)([{]{3,}))", # [line-start ws] {{{...
2.28 + "regionend" : r"(?:\N*)([}]{3,})", # [line-start ws] }}}...
2.29 "header" : r"#!(.*?)\n", # #! char-excl-nl
2.30
2.31 # Region contents:
2.32 @@ -547,8 +547,8 @@
2.33 ]
2.34
2.35 inline_pattern_names = [
2.36 - "fontstyle", "larger", "link", "monospace", "smaller", "strike", "sub",
2.37 - "super", "underline",
2.38 + "fontstyle", "larger", "link", "monospace", "regionstart", "smaller",
2.39 + "strike", "sub", "super", "underline",
2.40 ]
2.41
2.42 list_pattern_names = [
3.1 --- a/moinformat/serialisers/html.py Sat Jul 14 16:17:36 2018 +0200
3.2 +++ b/moinformat/serialisers/html.py Sat Jul 14 23:37:30 2018 +0200
3.3 @@ -25,6 +25,19 @@
3.4
3.5 "Serialisation of the page."
3.6
3.7 + def _region_tag(self, type):
3.8 +
3.9 + # NOTE: Need to support types in general.
3.10 +
3.11 + type = type.split()[0]
3.12 +
3.13 + if type == "inline":
3.14 + return "tt"
3.15 + elif type in (None, "python"):
3.16 + return "pre"
3.17 + else:
3.18 + return "span"
3.19 +
3.20 def start_region(self, level, indent, type):
3.21 l = []
3.22 out = l.append
3.23 @@ -36,13 +49,14 @@
3.24
3.25 # NOTE: Encode type details for CSS.
3.26
3.27 - if type:
3.28 - out("type-%s" % escape_attr(type))
3.29 + out("type-%s" % escape_attr(type or "opaque"))
3.30
3.31 - self.out("<span class='%s'>" % " ".join(l))
3.32 + tag = self._region_tag(type)
3.33 + self.out("<%s class='%s'>" % (tag, " ".join(l)))
3.34
3.35 def end_region(self, level, indent, type):
3.36 - self.out("</span>")
3.37 + tag = self._region_tag(type)
3.38 + self.out("</%s>" % tag)
3.39
3.40 def start_block(self):
3.41 self.out("<p>")
4.1 --- a/moinformat/serialisers/moin.py Sat Jul 14 16:17:36 2018 +0200
4.2 +++ b/moinformat/serialisers/moin.py Sat Jul 14 23:37:30 2018 +0200
4.3 @@ -29,7 +29,10 @@
4.4 out = self.out
4.5 if level:
4.6 out(" " * indent + "{" * level)
4.7 - if type and level:
4.8 +
4.9 + # Produce a header for regions within a top-level region.
4.10 +
4.11 + if type and type != "inline" and level:
4.12 out("#!%s\n" % type)
4.13
4.14 def end_region(self, level, indent, type):
5.1 --- a/moinformat/tree.py Sat Jul 14 16:17:36 2018 +0200
5.2 +++ b/moinformat/tree.py Sat Jul 14 23:37:30 2018 +0200
5.3 @@ -552,6 +552,9 @@
5.4 def empty(self):
5.5 return not self.s
5.6
5.7 + def multiline(self):
5.8 + return "\n" in self.s
5.9 +
5.10 def merge(self, text):
5.11 self.s += text.s
5.12
6.1 --- a/tests/test3.txt Sat Jul 14 16:17:36 2018 +0200
6.2 +++ b/tests/test3.txt Sat Jul 14 23:37:30 2018 +0200
6.3 @@ -3,8 +3,12 @@
6.4
6.5 i. Romanus eunt domus!
6.6 I. What did they do for us?
6.7 + I. {{{Did for us}}}
6.8 1. {{{
6.9 -Doing for us}}}
6.10 +Doing ''for'' us}}}
6.11 + 1. {{{#!python
6.12 +motto = "Romanus eunt domus!"
6.13 +}}}
6.14 a.#18 The Romans.
6.15
6.16 1. Starting from one