diff --git a/README.md b/README.md index 5db706f..fbe18b4 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Rendered documents are produced in ODT format, and can then be converted to PDF, ## Rendering a Template from secreatary import Render - + engine = Render(template) result = engine.render(foo=foo, bar=bar) @@ -27,7 +27,7 @@ To render a template create an instance of class `Render` and call the instance' Before rendering a template, you can configure the internal templating engine using the `Render` instance's variable `environment`, which is an instance of jinja2 **[Environment][3]** class. For example, to declare a custom filter use: from secreatary import Render - + engine = Render(template) # Configure custom application filters @@ -76,7 +76,7 @@ Most of the time secretary will handle the internal composing of XML when you in > YOU HAVEN'T PAID > `{% endif %}` -The last example could had been simplified into a single paragraph in Writer like: +The last example could had been simplified into a single paragraph in Writer like: > `{% if already_paid %}`YOU ALREADY PAID`{% else %}`YOU HAVEN'T PAID`{% endif %}` @@ -101,15 +101,18 @@ Although most of the time the automatic handling of control flow in secretary ma * `after::cell`: Same as `after::row` but for a table cell. > Field content is the control flow tag you insert with the Writer *input field* +### Features of jinja2 not supported +Secretary supports most of the jinja2 control structure/flow tags. But please avoid using the following tags since they are not supported: `block`, `extends`, `macro`, `call`, `include` and `import`. + ### Builtin Filters Secretary includes some predefined *jinja2* filters. Included filters are: -- **markdown(value)** +- **markdown(value)** Convert the value, a markdown formated string, into a ODT formated text. Example: {{ invoice.description|markdown }} - -- **pad(value, length)** + +- **pad(value, length)** Pad zeroes to `value` to the left until output value's length be equal to `length`. Default length if 5. Example: {{ invoice.number|pad(6) }} diff --git a/secretary.py b/secretary.py index af00f9a..39f1f7e 100644 --- a/secretary.py +++ b/secretary.py @@ -180,27 +180,35 @@ class Render(object): Unpack and render the internal template and returns the rendered ODF document. """ + def unescape_gt_lt(text): + # unescape XML entities gt and lt + unescape_entities = { + r'({[{|%].*)(>)(.*[%|}]})': r'\1>\3', + r'({[{|%].*)(<)(.*[%|}]})': r'\1<\3', + } + for pattern, repl in unescape_entities.iteritems(): + text = re.sub(pattern, repl, text, flags=re.IGNORECASE or re.DOTALL) + + return text self.unpack_template() # Render content.xml self.prepare_template_tags(self.content) - # print(self.content.toprettyxml()) - template = self.environment.from_string(self.content.toxml()) + template = self.environment.from_string(unescape_gt_lt(self.content.toxml())) result = template.render(**kwargs) result = result.replace('\n', '') # Replace original body with rendered body original_body = self.content.getElementsByTagName('office:body')[0] - rendered_body = parseString(result.encode('ascii', 'xmlcharrefreplace')) \ - .getElementsByTagName('office:body')[0] + rendered_body = parseString(result.encode('ascii', 'xmlcharrefreplace')).getElementsByTagName('office:body')[0] document = self.content.getElementsByTagName('office:document-content')[0] document.replaceChild(rendered_body, original_body) # Render style.xml self.prepare_template_tags(self.styles) - template = self.environment.from_string(self.styles.toxml()) + template = self.environment.from_string(unescape_gt_lt(self.styles.toxml())) result = template.render(**kwargs) result = result.replace('\n', '') self.styles = parseString(result.encode('ascii', 'xmlcharrefreplace')) @@ -332,7 +340,7 @@ class Render(object): # Avoid removing whole container, just original text:p parent field = self.node_parents(keep_field, 'text:p') parent = field.parentNode - + parent.removeChild(field) @@ -494,7 +502,7 @@ if __name__ == "__main__": ] - render = Render('a.odt') + render = Render('simple_template.odt') result = render.render(countries=countries, document=document) output = open('rendered.odt', 'wb') diff --git a/simple_template.odt b/simple_template.odt index f153ff3..e30eb6e 100644 Binary files a/simple_template.odt and b/simple_template.odt differ