diff --git a/secretary.py b/secretary.py index a5172ae..a284ad0 100644 --- a/secretary.py +++ b/secretary.py @@ -218,6 +218,31 @@ class Renderer(object): self.environment.block_end_string )) + self._compile_escape_expressions() + + + def _compile_escape_expressions(self): + # Compiles escape expressions + self.escape_map = dict() + unescape_rules = { + r'>' : r'>', + r'<' : r'<', + r'&' : r'&', + r'"' : r'"', + } + + for key, value in unescape_rules.items(): + exp = r'(?is)(({0}|{1}).*?)({2})(.*?({3}|{4}))' + key = re.compile(exp.format( + self.environment.variable_start_string, + self.environment.block_start_string, + key, + self.environment.variable_end_string, + self.environment.block_end_string + )) + + self.escape_map[key] = r'\1{0}\4'.format(value) + def _is_jinja_tag(self, tag): """ @@ -366,24 +391,16 @@ class Renderer(object): placeholder_parent.removeChild(placeholder) - @staticmethod - def _unescape_entities(xml_text): + def _unescape_entities(self, xml_text): """ - Strips tags of the form from inside Jinja elements - and unescapes HTML codes for >, <, & and " + Unescape '&', '<', '"' and '>' within jinja instructions. + The regexs rules used here are compiled in _compile_escape_expressions. """ - unescape_rules = { - r'(?is)({([{%])[^%}]*?)()(.*?[%}]})': r'\1 \4', - r'(?is)({([{%])[^%}]*?)(>)(.*?[%}]})' : r'\1>\4', - r'(?is)({([{%])[^%}]*?)(<)(.*?[%}]})' : r'\1<\4', - r'(?is)({([{%])[^%}]*?)(&)(.*?[%}]})' : r'\1&\4', - r'(?is)({([{%])[^%}]*?)(")(.*?[%}]})' : r'\1"\4', - } - - for regexp, replacement in unescape_rules.items(): - subs_made = True - while subs_made: - xml_text, subs_made = re.subn(regexp, replacement, xml_text) + for regexp, replacement in self.escape_map.items(): + while True: + xml_text, substitutions = regexp.subn(replacement, xml_text) + if not substitutions: + break return xml_text diff --git a/test_secretary.py b/test_secretary.py index a6cdab9..efc1bad 100644 --- a/test_secretary.py +++ b/test_secretary.py @@ -43,12 +43,6 @@ class RenderTestCase(TestCase): '{{ a < b }}' : '{{ a < b }}', '{% a|filter < b %}' : '{% a|filter < b %}', '{% a == b %}{% else if a < b %}': '{% a == b %}{% else if a < b %}', - - # test scapig of multiple spaces, even encoded as nodes - '{{ if multiple_spaces }}' : '{{ if multiple_spaces }}', - '{{ if multiple_spaces }}' : '{{ if multiple_spaces }}', - '{{ if multiple_spaces }}' : '{{ if multiple_spaces }}', - '{{ if [1,2,3]<2 }}': '{{ if [1,2,3] < 2 }}', } for test, expect in test_samples.items():