First usable version of markdown filter

This commit is contained in:
Christopher Ramírez 2013-09-12 15:50:17 -06:00
parent 3b7eb6d9ad
commit 686e598a73
2 changed files with 129 additions and 99 deletions

View file

@ -6,11 +6,20 @@
# as a dict in the 'attributes' key. Also, some tags may need to create
# new styles in the document.
transform_map = {
'p': {
'replace_with': 'text:p',
common_styles = {
'italic': {
'replace_with': 'text:span',
'attributes': {
'style-name': 'Standard'
'style-name': 'markdown_italic'
},
'style': {
'name': 'markdown_italic',
'properties': {
'fo:font-style': 'italic',
'style:font-style-asian': 'italic',
'style:font-style-complex': 'italic'
}
}
},
@ -30,21 +39,20 @@ transform_map = {
}
},
'i': {
'replace_with': 'text:span',
'p': {
'replace_with': 'text:p',
'attributes': {
'style-name': 'markdown_italic'
},
'style-name': 'Standard'
}
}
}
'style': {
'name': 'markdown_italic',
'properties': {
'fo:font-style': 'italic',
'style:font-style-asian': 'italic',
'style:font-style-complex': 'italic'
}
}
},
transform_map = {
'p': common_styles['p'],
'strong': common_styles['strong'],
'em': common_styles['italic'],
'b': common_styles['strong'],
'i': common_styles['italic'],
# Heading Styles (Use styles defined in the document)
'h1': {

View file

@ -38,10 +38,10 @@ import re
import sys
import zipfile
import io
from copy import deepcopy
from xml.dom.minidom import parseString
from jinja2 import Environment, Undefined
# ---- Exceptions
class SecretaryError(Exception):
pass
@ -99,9 +99,12 @@ class Render(object):
self.template = template
self.environment = Environment(undefined=UndefinedSilently, autoescape=True)
self.environment.filters['pad'] = pad_string
self.file_list = {}
# Register provided filters
self.environment.filters['pad'] = pad_string
self.environment.filters['markdown'] = self.markdown_filter
self.file_list = {}
def unpack_template(self):
"""
@ -161,7 +164,14 @@ class Render(object):
template = self.environment.from_string(self.content.toxml())
result = template.render(**kwargs)
result = result.replace('\n', '<text:line-break/>')
self.content = parseString(result.encode('ascii', 'xmlcharrefreplace'))
# 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]
document = self.content.getElementsByTagName('office:document-content')[0]
document.replaceChild(rendered_body, original_body)
# Render style.xml
self.prepare_template_tags(self.styles)
@ -223,6 +233,10 @@ class Render(object):
field_description = field.getAttribute('text:description')
if re.findall(r'\|markdown', field_content):
# a markdown should take the whole paragraph
field_description = 'text:p'
if not field_description:
new_node = self.create_text_span_node(xml_document, field_content)
else:
@ -250,10 +264,11 @@ class Render(object):
return None
for style_node in auto_styles.childNodes:
if style_node.hasattr('style:name') and
if style_node.hasAttribute('style:name') and \
(style_node.getAttribute('style:name') == style_name):
return style_node
return None
def insert_style_in_content(self, style_name, attributes=None,
**style_properties):
@ -263,8 +278,11 @@ class Render(object):
"""
auto_styles = self.content.getElementsByTagName('office:automatic-styles')[0]
style_node = self.content.createElement(transform_map[tag]['style:style'])
style_node = self.content.createElement('style:style')
style_node.setAttribute('style:name', style_name)
style_node.setAttribute('style:family', 'text')
style_node.setAttribute('style:parent-style-name', 'Standard')
if attributes:
for k, v in attributes.iteritems():
@ -273,21 +291,17 @@ class Render(object):
if style_properties:
style_prop = self.content.createElement('style:text-properties')
for k, v in style_properties.iteritems():
style_prop.setAttribute('style:%s' % k, v)
style_prop.setAttribute('%s' % k, v)
style_node.appendChild(style_prop)
auto_styles.appendChild(style_node)
return auto_styles.appendChild(style_node)
return style_node
def markdown_filter(markdown_text):
def markdown_filter(self, markdown_text):
"""
Convert a markdown text into a ODT formated text
"""
from copy import deepcopy
from xml.dom import Node
from markdown_map import transform_map
@ -296,9 +310,8 @@ def markdown_filter(markdown_text):
except ImportError:
raise SecretaryError('Could not import markdown2 library. Install it using "pip install markdown2"')
styles_cache = {} # cache styles searching
html_text = markdown(markdown_text)
xml_object = parseString( html_text )
# Transform HTML tags as specified in transform_map
@ -329,8 +342,17 @@ def markdown_filter(markdown_text):
odt_node.setAttribute('text:%s' % k, v)
# Does the node need to create an style?
if 'append_style' in transform_map[tag]:
pass
if 'style' in transform_map[tag]:
name = transform_map[tag]['style']['name']
if not name in styles_cache:
style_node = self.get_style_by_name(name)
if style_node is None:
# Create and cache the style node
style_node = self.insert_style_in_content(
name, transform_map[tag]['style'].get('attributes', None),
**transform_map[tag]['style']['properties'])
styles_cache[name] = style_node
html_node.parentNode.replaceChild(odt_node, html_node)