Fix merge conflict.
This commit is contained in:
commit
f3e5923737
4 changed files with 66 additions and 18 deletions
24
README.md
24
README.md
|
|
@ -16,7 +16,7 @@ Rendered documents are produced in ODT format, and can then be converted to PDF,
|
||||||
## Rendering a Template
|
## Rendering a Template
|
||||||
|
|
||||||
from secreatary import Render
|
from secreatary import Render
|
||||||
|
|
||||||
engine = Render(template)
|
engine = Render(template)
|
||||||
result = engine.render(foo=foo, bar=bar)
|
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:
|
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
|
from secreatary import Render
|
||||||
|
|
||||||
engine = Render(template)
|
engine = Render(template)
|
||||||
|
|
||||||
# Configure custom application filters
|
# Configure custom application filters
|
||||||
|
|
@ -54,9 +54,25 @@ Secretary will handle multiline variable values replacing the line breaks with a
|
||||||
|
|
||||||
### Control Flow
|
### Control Flow
|
||||||
|
|
||||||
To be documented...
|
To be documented...
|
||||||
|
|
||||||
|
|
||||||
|
### Builtin Filters
|
||||||
|
Apart of the available Jinja2 filters. Secretary includes some additionals filters. These are:
|
||||||
|
|
||||||
|
- **markdown(value)**
|
||||||
|
Convert the value, a markdown formated string, into a ODT formated text. Example:
|
||||||
|
|
||||||
|
{{ invoice.description|markdown }}
|
||||||
|
|
||||||
|
**Output value will take the whole paragraph** so be aware of loosing text which is on the same paragraph of the markdown field.
|
||||||
|
|
||||||
|
- **pad(value, length)**
|
||||||
|
Pad zeroes to `value` to the left until output's length will equal to `length`. Default output length is 5. Example:
|
||||||
|
|
||||||
|
{{ invoice.number|pad(6) }}
|
||||||
|
|
||||||
|
|
||||||
[1]: http://jinja.pocoo.org/docs/templates/
|
[1]: http://jinja.pocoo.org/docs/templates/
|
||||||
[2]: https://github.com/mirkonasato/pyodconverter
|
[2]: https://github.com/mirkonasato/pyodconverter
|
||||||
[3]: http://jinja.pocoo.org/docs/api/#jinja2.Environment
|
[3]: http://jinja.pocoo.org/docs/api/#jinja2.Environment
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
from random import randint
|
||||||
|
|
||||||
# Transform map used by the markdown filter. transform_map have
|
# Transform map used by the markdown filter. transform_map have
|
||||||
# instructions of how to transform a HTML style tag into a ODT document
|
# instructions of how to transform a HTML style tag into a ODT document
|
||||||
# styled tag. Some ODT tags may need extra attributes; these are defined
|
# styled tag. Some ODT tags may need extra attributes; these are defined
|
||||||
|
|
@ -39,7 +41,7 @@ common_styles = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
'p': {
|
'p': {
|
||||||
'replace_with': 'text:p',
|
'replace_with': 'text:p',
|
||||||
'style_attributes': {
|
'style_attributes': {
|
||||||
'style-name': 'Standard'
|
'style-name': 'Standard'
|
||||||
|
|
@ -51,7 +53,8 @@ transform_map = {
|
||||||
'a': {
|
'a': {
|
||||||
'replace_with': 'text:a',
|
'replace_with': 'text:a',
|
||||||
'attributes': {
|
'attributes': {
|
||||||
'xlink:type': 'simple'
|
'xlink:type': 'simple',
|
||||||
|
'xlink:href': ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -103,4 +106,22 @@ transform_map = {
|
||||||
'style-name': 'Preformatted_20_Text'
|
'style-name': 'Preformatted_20_Text'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'ul': {
|
||||||
|
'replace_with': 'text:list',
|
||||||
|
'attributes': {
|
||||||
|
'xml:id': 'list' + str(randint(100000000000000000,900000000000000000))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'ol': {
|
||||||
|
'replace_with': 'text:list',
|
||||||
|
'attributes': {
|
||||||
|
'xml:id': 'list' + str(randint(100000000000000000,900000000000000000))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'li': {
|
||||||
|
'replace_with': 'text:list-item'
|
||||||
|
},
|
||||||
}
|
}
|
||||||
31
secretary.py
31
secretary.py
|
|
@ -38,7 +38,6 @@ import re
|
||||||
import sys
|
import sys
|
||||||
import zipfile
|
import zipfile
|
||||||
import io
|
import io
|
||||||
from copy import deepcopy
|
|
||||||
from xml.dom.minidom import parseString
|
from xml.dom.minidom import parseString
|
||||||
from jinja2 import Environment, Undefined
|
from jinja2 import Environment, Undefined
|
||||||
|
|
||||||
|
|
@ -252,7 +251,7 @@ class Render(object):
|
||||||
|
|
||||||
keep_field = field
|
keep_field = field
|
||||||
field_reference = field.getAttribute('text:description')
|
field_reference = field.getAttribute('text:description')
|
||||||
|
|
||||||
if re.findall(r'\|markdown', field_content):
|
if re.findall(r'\|markdown', field_content):
|
||||||
# a markdown should take the whole paragraph
|
# a markdown should take the whole paragraph
|
||||||
field_reference = 'text:p'
|
field_reference = 'text:p'
|
||||||
|
|
@ -295,10 +294,10 @@ class Render(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
auto_styles = self.content.getElementsByTagName('office:automatic-styles')[0]
|
auto_styles = self.content.getElementsByTagName('office:automatic-styles')[0]
|
||||||
|
|
||||||
if not auto_styles.hasChildNodes():
|
if not auto_styles.hasChildNodes():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
for style_node in auto_styles.childNodes:
|
for style_node in auto_styles.childNodes:
|
||||||
if style_node.hasAttribute('style:name') and \
|
if style_node.hasAttribute('style:name') and \
|
||||||
(style_node.getAttribute('style:name') == style_name):
|
(style_node.getAttribute('style:name') == style_name):
|
||||||
|
|
@ -319,7 +318,7 @@ class Render(object):
|
||||||
style_node.setAttribute('style:name', style_name)
|
style_node.setAttribute('style:name', style_name)
|
||||||
style_node.setAttribute('style:family', 'text')
|
style_node.setAttribute('style:family', 'text')
|
||||||
style_node.setAttribute('style:parent-style-name', 'Standard')
|
style_node.setAttribute('style:parent-style-name', 'Standard')
|
||||||
|
|
||||||
if attributes:
|
if attributes:
|
||||||
for k, v in attributes.iteritems():
|
for k, v in attributes.iteritems():
|
||||||
style_node.setAttribute('style:%s' % k, v)
|
style_node.setAttribute('style:%s' % k, v)
|
||||||
|
|
@ -337,6 +336,10 @@ class Render(object):
|
||||||
"""
|
"""
|
||||||
Convert a markdown text into a ODT formated text
|
Convert a markdown text into a ODT formated text
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if not isinstance(markdown_text, basestring):
|
||||||
|
return ''
|
||||||
|
|
||||||
from xml.dom import Node
|
from xml.dom import Node
|
||||||
from markdown_map import transform_map
|
from markdown_map import transform_map
|
||||||
|
|
||||||
|
|
@ -345,7 +348,7 @@ class Render(object):
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise SecretaryError('Could not import markdown2 library. Install it using "pip install markdown2"')
|
raise SecretaryError('Could not import markdown2 library. Install it using "pip install markdown2"')
|
||||||
|
|
||||||
styles_cache = {} # cache styles searching
|
styles_cache = {} # cache styles searching
|
||||||
html_text = markdown(markdown_text)
|
html_text = markdown(markdown_text)
|
||||||
xml_object = parseString('<html>%s</html>' % html_text)
|
xml_object = parseString('<html>%s</html>' % html_text)
|
||||||
|
|
||||||
|
|
@ -394,12 +397,20 @@ class Render(object):
|
||||||
|
|
||||||
html_node.parentNode.replaceChild(odt_node, html_node)
|
html_node.parentNode.replaceChild(odt_node, html_node)
|
||||||
|
|
||||||
|
def node_to_string(node):
|
||||||
|
result = node.toxml()
|
||||||
|
|
||||||
result = ''.join(c.toxml() for c in xml_object.getElementsByTagName('html')[0].childNodes)
|
# linebreaks in preformated nodes should be converted to <text:line-break/>
|
||||||
# A double linebreak should be replacece with an empty paragraph
|
if (node.__class__.__name__ != 'Text') and \
|
||||||
result = result.replace('\n\n', '<text:p text:style-name="Standard"/>')
|
(node.getAttribute('text:style-name') == 'Preformatted_20_Text'):
|
||||||
return result
|
result = result.replace('\n', '<text:line-break/>')
|
||||||
|
|
||||||
|
# All double linebreak should be replaced with an empty paragraph
|
||||||
|
return result.replace('\n\n', '<text:p text:style-name="Standard"/>')
|
||||||
|
|
||||||
|
|
||||||
|
return ''.join(node_as_str for node_as_str in map(node_to_string,
|
||||||
|
xml_object.getElementsByTagName('html')[0].childNodes))
|
||||||
|
|
||||||
def render_template(template, **kwargs):
|
def render_template(template, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
4
setup.py
4
setup.py
|
|
@ -24,7 +24,7 @@ class PyTest(TestCommand):
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='secretary',
|
name='secretary',
|
||||||
version='0.0.1',
|
version='0.1.0',
|
||||||
url='https://github.com/christopher-ramirez/secretary',
|
url='https://github.com/christopher-ramirez/secretary',
|
||||||
license='BSD',
|
license='BSD',
|
||||||
author='Christopher Ramírez',
|
author='Christopher Ramírez',
|
||||||
|
|
@ -32,7 +32,7 @@ setup(
|
||||||
description=('Take the power of Jinja2 templates to OpenOffice and '
|
description=('Take the power of Jinja2 templates to OpenOffice and '
|
||||||
'LibreOffice and create reports and letters in your web applications'),
|
'LibreOffice and create reports and letters in your web applications'),
|
||||||
long_description=read('README.md'),
|
long_description=read('README.md'),
|
||||||
py_modules=['secretary'],
|
py_modules=['secretary', 'markdown_map'],
|
||||||
platforms='any',
|
platforms='any',
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'Jinja2', 'markdown2'
|
'Jinja2', 'markdown2'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue