This commit is contained in:
Kovid Goyal 2015-03-19 10:27:33 +05:30
parent ca26df381a
commit c981e4b50d

View File

@ -55,6 +55,7 @@ if False: # Added by Kovid
# In ODF a style can have a parent, these parents can be chained.
class StyleToCSS:
""" The purpose of the StyleToCSS class is to contain the rules to convert
ODF styles to CSS2. Since it needs the generic fonts, it would probably
make sense to also contain the Styles in a dict as well..
@ -119,12 +120,18 @@ class StyleToCSS:
This method put the font and fallback into a dictionary
"""
htmlgeneric = "sans-serif"
if generic == "roman": htmlgeneric = "serif"
elif generic == "swiss": htmlgeneric = "sans-serif"
elif generic == "modern": htmlgeneric = "monospace"
elif generic == "decorative": htmlgeneric = "sans-serif"
elif generic == "script": htmlgeneric = "monospace"
elif generic == "system": htmlgeneric = "serif"
if generic == "roman":
htmlgeneric = "serif"
elif generic == "swiss":
htmlgeneric = "sans-serif"
elif generic == "modern":
htmlgeneric = "monospace"
elif generic == "decorative":
htmlgeneric = "sans-serif"
elif generic == "script":
htmlgeneric = "monospace"
elif generic == "system":
htmlgeneric = "serif"
self.fontdict[name] = (family, htmlgeneric)
def c_drawfillimage(self, ruleset, sdict, rule, val):
@ -159,8 +166,10 @@ class StyleToCSS:
def c_text_align(self, ruleset, sdict, rule, align):
""" Text align """
if align == "start": align = "left"
if align == "end": align = "right"
if align == "start":
align = "left"
if align == "end":
align = "right"
sdict['text-align'] = align
def c_fn(self, ruleset, sdict, rule, fontstyle):
@ -224,7 +233,7 @@ class StyleToCSS:
elif wrap == "run-through":
sdict['position'] = "absolute" # Simulate run-through
sdict['top'] = "0"
sdict['right'] = "0";
sdict['right'] = "0"
else: # No wrapping
sdict['margin-left'] = "auto"
sdict['margin-right'] = "0px"
@ -243,7 +252,7 @@ class StyleToCSS:
sdict['float'] = "left"
else:
sdict['position'] = "relative" # No wrapping
if ruleset.has_key( (SVGNS,'x') ):
if (SVGNS,'x') in ruleset:
sdict['left'] = ruleset[(SVGNS,'x')]
def c_page_width(self, ruleset, sdict, rule, val):
@ -286,6 +295,7 @@ class StyleToCSS:
class TagStack:
def __init__(self):
self.stack = []
@ -303,13 +313,14 @@ class TagStack:
def rfindattr(self, attr):
""" Find a tag with the given attribute """
for tag, attrs in self.stack:
if attrs.has_key(attr):
if attr in attrs:
return attrs[attr]
return None
def count_tags(self, tag):
c = 0
for ttag, tattrs in self.stack:
if ttag == tag: c = c + 1
if ttag == tag:
c = c + 1
return c
special_styles = {
@ -341,6 +352,7 @@ special_styles = {
#
# -----------------------------------------------------------------------------
class ODF2XHTML(handler.ContentHandler):
""" The ODF2XHTML parses an ODF file and produces XHTML"""
def __init__(self, generate_css=True, embedable=False):
@ -459,7 +471,6 @@ class ODF2XHTML(handler.ContentHandler):
self.elements[(OFFICENS, u"presentation")] = (None,None)
self.elements[(OFFICENS, u"document-content")] = (None,None)
def add_style_file(self, stylefilename, media=None):
""" Add a link to an external style file.
Also turns of the embedding of styles in the HTML
@ -506,7 +517,6 @@ class ODF2XHTML(handler.ContentHandler):
# Tags from meta.xml
self.metatags = []
def writeout(self, s):
if s != '':
self._wfunc(s)
@ -526,14 +536,14 @@ class ODF2XHTML(handler.ContentHandler):
self.writeout("<%s>" % tag)
else:
self.writeout("<%s %s>" % (tag, " ".join(a)))
if block == True:
if block:
self.writeout("\n")
def closetag(self, tag, block=True):
""" Close an open HTML tag """
self.htmlstack.pop()
self.writeout("</%s>" % tag)
if block == True:
if block:
self.writeout("\n")
def emptytag(self, tag, attrs={}):
@ -604,7 +614,7 @@ class ODF2XHTML(handler.ContentHandler):
def get_anchor(self, name):
""" Create a unique anchor id for a href name """
if not self.anchors.has_key(name):
if name not in self.anchors:
# Changed by Kovid
self.anchors[name] = "anchor%d" % (len(self.anchors) + 1)
return self.anchors.get(name)
@ -665,13 +675,13 @@ class ODF2XHTML(handler.ContentHandler):
style = ''
else:
style = "position: absolute;"
if attrs.has_key( (SVGNS,"width") ):
if (SVGNS,"width") in attrs:
style = style + "width:" + attrs[(SVGNS,"width")] + ";"
if attrs.has_key( (SVGNS,"height") ):
if (SVGNS,"height") in attrs:
style = style + "height:" + attrs[(SVGNS,"height")] + ";"
if attrs.has_key( (SVGNS,"x") ):
if (SVGNS,"x") in attrs:
style = style + "left:" + attrs[(SVGNS,"x")] + ";"
if attrs.has_key( (SVGNS,"y") ):
if (SVGNS,"y") in attrs:
style = style + "top:" + attrs[(SVGNS,"y")] + ";"
if self.generate_css:
self.opentag(htmltag, {'class': name, 'style': style})
@ -701,13 +711,13 @@ class ODF2XHTML(handler.ContentHandler):
style = ''
else:
style = "position:absolute;"
if attrs.has_key( (SVGNS,"width") ):
if (SVGNS,"width") in attrs:
style = style + "width:" + attrs[(SVGNS,"width")] + ";"
if attrs.has_key( (SVGNS,"height") ):
if (SVGNS,"height") in attrs:
style = style + "height:" + attrs[(SVGNS,"height")] + ";"
if attrs.has_key( (SVGNS,"x") ):
if (SVGNS,"x") in attrs:
style = style + "left:" + attrs[(SVGNS,"x")] + ";"
if attrs.has_key( (SVGNS,"y") ):
if (SVGNS,"y") in attrs:
style = style + "top:" + attrs[(SVGNS,"y")] + ";"
if self.generate_css:
self.opentag(htmltag, {'class': name, 'style': style})
@ -766,7 +776,7 @@ class ODF2XHTML(handler.ContentHandler):
class_id = attrs[(DRAWNS,"class-id")]
except KeyError: # Added by Kovid to ignore <draw> without the right
return # attributes
if class_id and class_id.lower() == "00020803-0000-0000-c000-000000000046": ## Microsoft Graph 97 Chart
if class_id and class_id.lower() == "00020803-0000-0000-c000-000000000046": # Microsoft Graph 97 Chart
tagattrs = {'name':'object_ole_graph', 'class':'ole-graph'}
self.opentag('a', tagattrs)
self.closetag('a', tagattrs)
@ -794,7 +804,7 @@ class ODF2XHTML(handler.ContentHandler):
def s_draw_textbox(self, tag, attrs):
style = ''
if attrs.has_key( (FONS,"min-height") ):
if (FONS,"min-height") in attrs:
style = style + "min-height:" + attrs[(FONS,"min-height")] + ";"
self.opentag('div')
# self.opentag('div', {'style': style})
@ -837,14 +847,14 @@ dl.notes dd:last-of-type { page-break-after: avoid }
for name in self.stylestack:
styles = self.styledict.get(name)
# Preload with the family's default style
if styles.has_key('__style-family') and self.styledict.has_key(styles['__style-family']):
if '__style-family' in styles and styles['__style-family'] in self.styledict:
familystyle = self.styledict[styles['__style-family']].copy()
del styles['__style-family']
for style, val in styles.items():
familystyle[style] = val
styles = familystyle
# Resolve the remaining parent styles
while styles.has_key('__parent-style-name') and self.styledict.has_key(styles['__parent-style-name']):
while '__parent-style-name' in styles and styles['__parent-style-name'] in self.styledict:
parentstyle = self.styledict[styles['__parent-style-name']].copy()
del styles['__parent-style-name']
for style, val in styles.items():
@ -976,7 +986,6 @@ dl.notes dd:last-of-type { page-break-after: avoid }
for key,attr in attrs.items():
self.styledict[self.currentstyle][key] = attr
familymap = {'frame':'frame', 'paragraph':'p', 'presentation':'presentation',
'text':'span','section':'div',
'table':'table','table-cell':'td','table-column':'col',
@ -1070,7 +1079,7 @@ dl.notes dd:last-of-type { page-break-after: avoid }
pagelayout = attrs.get((STYLENS,'page-layout-name'), None)
if pagelayout:
pagelayout = ".PL-" + pagelayout
if self.styledict.has_key( pagelayout ):
if pagelayout in self.styledict:
styles = self.styledict[pagelayout]
for style, val in styles.items():
self.styledict[self.currentstyle][style] = val
@ -1100,7 +1109,7 @@ dl.notes dd:last-of-type { page-break-after: avoid }
parent = attrs.get((STYLENS,'parent-style-name'))
self.currentstyle = special_styles.get(name,"."+name)
self.stylestack.append(self.currentstyle)
if not self.styledict.has_key(self.currentstyle):
if self.currentstyle not in self.styledict:
self.styledict[self.currentstyle] = {}
self.styledict[self.currentstyle]['__style-family'] = htmlfamily
@ -1109,7 +1118,7 @@ dl.notes dd:last-of-type { page-break-after: avoid }
if parent:
parent = "%s-%s" % (sfamily, parent)
parent = special_styles.get(parent, "."+parent)
if self.styledict.has_key( parent ):
if parent in self.styledict:
styles = self.styledict[parent]
for style, val in styles.items():
self.styledict[self.currentstyle][style] = val
@ -1225,8 +1234,10 @@ dl.notes dd:last-of-type { page-break-after: avoid }
def s_text_h(self, tag, attrs):
""" Headings start """
level = int(attrs[(TEXTNS,'outline-level')])
if level > 6: level = 6 # Heading levels go only to 6 in XHTML
if level < 1: level = 1
if level > 6:
level = 6 # Heading levels go only to 6 in XHTML
if level < 1:
level = 1
self.headinglevels[level] = self.headinglevels[level] + 1
name = self.classname(attrs)
for x in range(level + 1,10):
@ -1245,12 +1256,15 @@ dl.notes dd:last-of-type { page-break-after: avoid }
"""
self.writedata()
level = int(attrs[(TEXTNS,'outline-level')])
if level > 6: level = 6 # Heading levels go only to 6 in XHTML
if level < 1: level = 1
if level > 6:
level = 6 # Heading levels go only to 6 in XHTML
if level < 1:
level = 1
lev = self.headinglevels[1:level+1]
outline = '.'.join(map(str,lev))
heading = ''.join(self.data)
if self.title == '': self.title = heading
if self.title == '':
self.title = heading
# Changed by Kovid
tail = ''.join(self.data)
anchor = self.get_anchor("%s.%s" % (outline, tail))
@ -1348,12 +1362,18 @@ dl.notes dd:last-of-type { page-break-after: avoid }
self.listtypes[list_class] = 'ol'
self.stylestack.append(self.currentstyle)
self.styledict[self.currentstyle] = {}
if num_format == "1": listtype = "decimal"
elif num_format == "I": listtype = "upper-roman"
elif num_format == "i": listtype = "lower-roman"
elif num_format == "A": listtype = "upper-alpha"
elif num_format == "a": listtype = "lower-alpha"
else: listtype = "decimal"
if num_format == "1":
listtype = "decimal"
elif num_format == "I":
listtype = "upper-roman"
elif num_format == "i":
listtype = "lower-roman"
elif num_format == "A":
listtype = "upper-alpha"
elif num_format == "a":
listtype = "lower-alpha"
else:
listtype = "decimal"
self.styledict[self.currentstyle][('','list-style-type')] = listtype
def e_text_list_level_style_number(self, tag, attrs):
@ -1535,7 +1555,6 @@ dl.notes dd:last-of-type { page-break-after: avoid }
if node.nodeType == Node.TEXT_NODE or node.nodeType == Node.CDATA_SECTION_NODE:
self.characters(unicode(node))
def odf2xhtml(self, odffile):
""" Load a file and return the XHTML
"""
@ -1543,7 +1562,8 @@ dl.notes dd:last-of-type { page-break-after: avoid }
return self.xhtml()
def _wlines(self,s):
if s != '': self.lines.append(s)
if s != '':
self.lines.append(s)
def xhtml(self):
""" Returns the xhtml
@ -1551,7 +1571,8 @@ dl.notes dd:last-of-type { page-break-after: avoid }
return ''.join(self.lines)
def _writecss(self, s):
if s != '': self._csslines.append(s)
if s != '':
self._csslines.append(s)
def _writenothing(self, s):
pass
@ -1583,6 +1604,7 @@ dl.notes dd:last-of-type { page-break-after: avoid }
class ODF2XHTMLembedded(ODF2XHTML):
""" The ODF2XHTML parses an ODF file and produces XHTML"""
def __init__(self, lines, generate_css=True, embedable=False):
@ -1625,21 +1647,21 @@ class ODF2XHTMLembedded(ODF2XHTML):
# (OFFICENS, "text"):(self.s_office_text, self.e_office_text),
(OFFICENS, "scripts"):(self.s_ignorexml, None),
(PRESENTATIONNS, "notes"):(self.s_ignorexml, None),
## (STYLENS, "default-page-layout"):(self.s_style_default_page_layout, self.e_style_page_layout),
# (STYLENS, "default-page-layout"):(self.s_style_default_page_layout, self.e_style_page_layout),
# (STYLENS, "default-page-layout"):(self.s_ignorexml, None),
# (STYLENS, "default-style"):(self.s_style_default_style, self.e_style_default_style),
# (STYLENS, "drawing-page-properties"):(self.s_style_handle_properties, None),
# (STYLENS, "font-face"):(self.s_style_font_face, None),
## (STYLENS, "footer"):(self.s_style_footer, self.e_style_footer),
## (STYLENS, "footer-style"):(self.s_style_footer_style, None),
# (STYLENS, "footer"):(self.s_style_footer, self.e_style_footer),
# (STYLENS, "footer-style"):(self.s_style_footer_style, None),
# (STYLENS, "graphic-properties"):(self.s_style_handle_properties, None),
# (STYLENS, "handout-master"):(self.s_ignorexml, None),
## (STYLENS, "header"):(self.s_style_header, self.e_style_header),
## (STYLENS, "header-footer-properties"):(self.s_style_handle_properties, None),
## (STYLENS, "header-style"):(self.s_style_header_style, None),
# (STYLENS, "header"):(self.s_style_header, self.e_style_header),
# (STYLENS, "header-footer-properties"):(self.s_style_handle_properties, None),
# (STYLENS, "header-style"):(self.s_style_header_style, None),
# (STYLENS, "master-page"):(self.s_style_master_page, None),
# (STYLENS, "page-layout-properties"):(self.s_style_handle_properties, None),
## (STYLENS, "page-layout"):(self.s_style_page_layout, self.e_style_page_layout),
# (STYLENS, "page-layout"):(self.s_style_page_layout, self.e_style_page_layout),
# (STYLENS, "page-layout"):(self.s_ignorexml, None),
# (STYLENS, "paragraph-properties"):(self.s_style_handle_properties, None),
# (STYLENS, "style"):(self.s_style_style, self.e_style_style),
@ -1680,4 +1702,3 @@ class ODF2XHTMLembedded(ODF2XHTML):
(TEXTNS, "user-index-source"):(self.s_text_x_source, self.e_text_x_source),
(TEXTNS, "page-number"):(None, None),
}