1.1 --- a/tests/test_xml_lists_blocks.txt Sun Apr 14 21:47:21 2013 +0200
1.2 +++ b/tests/test_xml_lists_blocks.txt Sun Apr 14 21:50:02 2013 +0200
1.3 @@ -5,4 +5,9 @@
1.4 <li>An item with <ac:macro name="code"><ac:plain-text-body>preformatted text</ac:plain-text-body></ac:macro> and more text</li>
1.5 <li>An item with <a href="http://moinmo.in/">a link</a> and following text</li>
1.6 <li><a href="http://moinmo.in/">A link</a> and following text and <a href="http://moinmo.in/">another link</a></li>
1.7 +<li>An item with <ac:macro name="code"><ac:plain-text-body><![CDATA[
1.8 +newlines in a preformatted region
1.9 +which must therefore appear on a
1.10 +separate line
1.11 +]] ></ac:plain-text-body></ac:macro></li>
1.12 </ul>
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/tests/test_xml_macros.txt Sun Apr 14 21:50:02 2013 +0200
2.3 @@ -0,0 +1,6 @@
2.4 +<p>This is a test of <ac:macro ac:name="color"><ac:default-parameter>red</ac:default-parameter>colours</ac:macro>.</p>
2.5 +
2.6 +<ac:macro ac:name="code"><ac:plain-text-body>sections featuring code</ac:plain-text-body></ac:macro>
2.7 +
2.8 +<ac:macro ac:name="anchor"><ac:default-parameter>second</ac:default-parameter></ac:macro>
2.9 +<p>This is the second paragraph.</p>
3.1 --- a/xmlparser.py Sun Apr 14 21:47:21 2013 +0200
3.2 +++ b/xmlparser.py Sun Apr 14 21:50:02 2013 +0200
3.3 @@ -139,7 +139,7 @@
3.4
3.5 # Indentation and element nesting states.
3.6
3.7 - self.indent = 0
3.8 + self.indents = [0]
3.9 self.states = {}
3.10 self.max_level = self.level = 0
3.11
3.12 @@ -162,11 +162,11 @@
3.13 # Track indentation for lists.
3.14
3.15 if list_tags.has_key(name):
3.16 - self.indent += 1
3.17 + self.indents.append(self.indents[-1] + 1)
3.18
3.19 # Track element nesting.
3.20
3.21 - elif self.states.has_key(name):
3.22 + if self.states.has_key(name):
3.23 self.states[name] += 1
3.24
3.25 # Track cumulative element nesting in order to produce appropriate depth
3.26 @@ -176,6 +176,10 @@
3.27 self.level += 1
3.28 self.max_level = max(self.level, self.max_level)
3.29
3.30 + # Reset indentation within regions.
3.31 +
3.32 + self.indents.append(0)
3.33 +
3.34 Parser.startElement(self, name, attrs)
3.35
3.36 # Remember macro information for use within the element.
3.37 @@ -184,17 +188,32 @@
3.38 self.macro = self.attributes[-1].get("ac:name")
3.39
3.40 def endElement(self, name):
3.41 +
3.42 + # Reset the indent for any preformatted/formatted region so that it may
3.43 + # itself be indented.
3.44 +
3.45 + if name in preformatted_tags or name in formatted_tags:
3.46 + self.indents.pop()
3.47 +
3.48 Parser.endElement(self, name)
3.49
3.50 if list_tags.has_key(name):
3.51 - self.indent -= 1
3.52 - elif self.states.has_key(name):
3.53 + self.indents.pop()
3.54 +
3.55 + if self.states.has_key(name):
3.56 self.states[name] -= 1
3.57 +
3.58 if name in preformatted_tags or name in formatted_tags:
3.59 self.level -= 1
3.60 if not self.level:
3.61 self.max_level = 0
3.62
3.63 + # Discard macro state.
3.64 +
3.65 + if name == "ac:macro":
3.66 + self.macro = None
3.67 + self.macro_parameters = {}
3.68 +
3.69 def characters(self, content):
3.70 if not self.is_preformatted():
3.71 content = self.normalise(content, self.elements[-1])
3.72 @@ -272,18 +291,16 @@
3.73 self.label = text.strip()
3.74 text = ""
3.75
3.76 - # Discard macro state.
3.77 -
3.78 - elif name == "ac:macro":
3.79 - self.macro = None
3.80 - self.macro_parameters = {}
3.81 -
3.82 # Remember macro information.
3.83
3.84 - elif name in ("ac:parameter", "ac:default-parameter"):
3.85 + elif name == "ac:parameter":
3.86 self.macro_parameters[self.attributes[-1].get("ac:name")] = text
3.87 text = ""
3.88
3.89 + elif name == "ac:default-parameter":
3.90 + self.macro_parameters[self.attributes[-2].get("ac:name")] = text
3.91 + text = ""
3.92 +
3.93 # Handle single-level tags.
3.94
3.95 elif name in single_level_tags and self.states[name] > 1:
3.96 @@ -342,13 +359,21 @@
3.97 text = conversion % (self.target, self.label or self.target)
3.98 self.target = self.target_type = self.label = None
3.99
3.100 - # Handle the common case.
3.101 + # Macros require various kinds of information.
3.102 +
3.103 + elif name == "ac:macro":
3.104 + macro_name = self.attributes[-1]["ac:name"]
3.105 +
3.106 + # Handle the common cases for parameterised and unparameterised
3.107 + # substitutions.
3.108
3.109 elif text and conversion:
3.110 text = conversion % text
3.111 elif simple_tags.has_key(name):
3.112 text = simple_tags[name]
3.113
3.114 +
3.115 +
3.116 # Postprocess table columns and rows.
3.117
3.118 if name in ("th", "td"):
3.119 @@ -360,10 +385,12 @@
3.120 text = "\n==\n%s" % text
3.121 self.table_rows += 1
3.122
3.123 +
3.124 +
3.125 # Normalise leading whitespace and indent the text if appropriate.
3.126
3.127 if name in indented_tags:
3.128 - text = " " * self.indent + text.lstrip()
3.129 + text = " " * self.indents[-1] + text.lstrip()
3.130
3.131 # Add the converted text to the end of the parent element's text nodes.
3.132
3.133 @@ -451,7 +478,7 @@
3.134 f.close()
3.135
3.136 if __name__ == "__main__":
3.137 - s = sys.stdin.read()
3.138 + s = codecs.getreader("utf-8")(sys.stdin).read()
3.139 out = codecs.getwriter("utf-8")(sys.stdout)
3.140 parse(s, out)
3.141