Add main ODT style XML

This commit is contained in:
Veronica K. B. Olsen
2021-01-26 20:22:32 +01:00
parent c9eebafb2d
commit e3c37f003b
2 changed files with 319 additions and 2 deletions
+302 -1
View File
@@ -24,23 +24,87 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import nw
import logging
import os
from lxml import etree
from nw.core.tokenizer import Tokenizer
logger = logging.getLogger(__name__)
XML_NS = {
"office" : "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
"style" : "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
"text" : "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
"fo" : "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
"loext" : "urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0",
}
class ToOdt(Tokenizer):
def __init__(self, theProject, theParent):
Tokenizer.__init__(self, theProject, theParent)
self.mainConf = nw.CONFIG
self._xRoot = None
self._xStyl = None
self._xText = None
self._dLanguage = "en"
self._dCountry = "GB"
self._dFontFace = "Liberation Serif"
self._dFontSize = 12
return
##
# Setters
##
def setLanguage(self, theLang):
"""Set language for the document.
"""
if theLang is None:
return False
langBits = theLang.split("_")
self._dLanguage = langBits[0]
if len(langBits) > 1:
self._dCountry = langBits[1]
return True
def setFont(self, fontFace, fontSize):
"""Set font and font size.
"""
self._dFontFace = fontFace
self._dFontSize = fontSize
return
##
# Class Methods
##
def initDocument(self):
"""Initialises a new open document XML tree.
"""
rAttr = {
_mkTag("office", "version") : "1.3",
_mkTag("office", "mimetype") : "application/vnd.oasis.opendocument.text",
}
self._xRoot = etree.Element(_mkTag("office", "document"), attrib=rAttr, nsmap=XML_NS)
self._xStyl = etree.SubElement(self._xRoot, _mkTag("office", "styles"))
self._xText = etree.SubElement(self._xRoot, _mkTag("office", "text"))
# Add Styles
self._styleParagraph()
self._styleHeaders()
return
def doConvert(self):
"""Convert the list of text tokens into a HTML document saved
to theResult.
@@ -48,8 +112,245 @@ class ToOdt(Tokenizer):
self.theResult = ""
for tType, tLine, tText, tFormat, tStyle in self.theTokens:
continue
# Process Text Type
if tType == self.T_EMPTY:
continue
elif tType == self.T_TITLE:
continue
return
def closeDocument(self):
"""Return the serialised XML document
"""
self.theResult = etree.tostring(
self._xRoot,
pretty_print = True,
encoding = "utf-8",
xml_declaration = True
)
cacheFile = os.path.join(os.path.expanduser("~"), "Temp", "odtGen.fodt")
with open(cacheFile, mode="wb") as outFile:
outFile.write(self.theResult)
return
##
# Style Elements
##
def _styleParagraph(self):
"""Set the paragraph styles.
"""
# Add Default Paragraph Style
# ===========================
theAttr = {}
theAttr[_mkTag("style", "family")] = "paragraph"
xStyl = etree.SubElement(self._xStyl, _mkTag("style", "default-style"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("style", "line-break")] = "strict"
theAttr[_mkTag("style", "tab-stop-distance")] = "1.251cm"
theAttr[_mkTag("style", "writing-mode")] = "page"
etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("style", "font-name")] = self._dFontFace
theAttr[_mkTag("fo", "font-size")] = "%dpt" % self._dFontSize
theAttr[_mkTag("fo", "language")] = self._dLanguage
theAttr[_mkTag("fo", "country")] = self._dCountry
etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
# Add Paragraph Style
# ===================
theAttr = {}
theAttr[_mkTag("style", "name")] = "Standard"
theAttr[_mkTag("style", "family")] = "paragraph"
theAttr[_mkTag("style", "class")] = "text"
etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
# Add Text Body Style
# ===================
theAttr = {}
theAttr[_mkTag("style", "name")] = "Text_body"
theAttr[_mkTag("style", "display-name")] = "Text Body"
theAttr[_mkTag("style", "family")] = "paragraph"
theAttr[_mkTag("style", "parent-style-name")] = "Standard"
theAttr[_mkTag("style", "class")] = "text"
xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("fo", "margin-top")] = "0cm"
theAttr[_mkTag("fo", "margin-bottom")] = "0.247cm"
theAttr[_mkTag("style", "contextual-spacing")] = "false"
theAttr[_mkTag("fo", "line-height")] = "115%"
etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
return
def _styleHeaders(self):
"""Set the header styles.
"""
# Add Default Heading Style
# =========================
theAttr = {}
theAttr[_mkTag("style", "name")] = "Heading"
theAttr[_mkTag("style", "family")] = "paragraph"
theAttr[_mkTag("style", "parent-style-name")] = "Standard"
theAttr[_mkTag("style", "next-style-name")] = "Text_body"
theAttr[_mkTag("style", "class")] = "text"
xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("fo", "margin-top")] = "0.423cm"
theAttr[_mkTag("fo", "margin-bottom")] = "0.212cm"
theAttr[_mkTag("style", "contextual-spacing")] = "false"
theAttr[_mkTag("fo", "keep-with-next")] = "always"
etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("style", "font-name")] = self._dFontFace
theAttr[_mkTag("fo", "font-family")] = "'%s'" % self._dFontFace
theAttr[_mkTag("style", "font-pitch")] = "variable"
theAttr[_mkTag("fo", "font-size")] = "14pt"
etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
# Add Title Style
# ===============
theAttr = {}
theAttr[_mkTag("style", "name")] = "Title"
theAttr[_mkTag("style", "family")] = "paragraph"
theAttr[_mkTag("style", "parent-style-name")] = "Heading"
theAttr[_mkTag("style", "next-style-name")] = "Text_body"
theAttr[_mkTag("style", "class")] = "chapter"
xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("fo", "text-align")] = "center"
etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("fo", "font-size")] = "28pt"
theAttr[_mkTag("fo", "font-weight")] = "bold"
etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
# Add Heading 1 Style
# ===================
theAttr = {}
theAttr[_mkTag("style", "name")] = "Heading_1"
theAttr[_mkTag("style", "display-name")] = "Heading 1"
theAttr[_mkTag("style", "family")] = "paragraph"
theAttr[_mkTag("style", "parent-style-name")] = "Heading"
theAttr[_mkTag("style", "next-style-name")] = "Text_body"
theAttr[_mkTag("style", "default-outline-level")] = "1"
theAttr[_mkTag("style", "class")] = "text"
xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("fo", "margin-top")] = "0.423cm"
theAttr[_mkTag("fo", "margin-bottom")] = "0.212cm"
theAttr[_mkTag("style", "contextual-spacing")] = "false"
etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("fo", "font-size")] = "130%"
theAttr[_mkTag("fo", "font-weight")] = "bold"
etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
# Add Heading 2 Style
# ===================
theAttr = {}
theAttr[_mkTag("style", "name")] = "Heading_2"
theAttr[_mkTag("style", "display-name")] = "Heading 2"
theAttr[_mkTag("style", "family")] = "paragraph"
theAttr[_mkTag("style", "parent-style-name")] = "Heading"
theAttr[_mkTag("style", "next-style-name")] = "Text_body"
theAttr[_mkTag("style", "default-outline-level")] = "2"
theAttr[_mkTag("style", "class")] = "text"
xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("fo", "margin-top")] = "0.353cm"
theAttr[_mkTag("fo", "margin-bottom")] = "0.212cm"
theAttr[_mkTag("style", "contextual-spacing")] = "false"
etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("fo", "font-size")] = "120%"
theAttr[_mkTag("fo", "font-weight")] = "bold"
etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
# Add Heading 3 Style
# ===================
theAttr = {}
theAttr[_mkTag("style", "name")] = "Heading_3"
theAttr[_mkTag("style", "display-name")] = "Heading 3"
theAttr[_mkTag("style", "family")] = "paragraph"
theAttr[_mkTag("style", "parent-style-name")] = "Heading"
theAttr[_mkTag("style", "next-style-name")] = "Text_body"
theAttr[_mkTag("style", "default-outline-level")] = "3"
theAttr[_mkTag("style", "class")] = "text"
xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("fo", "margin-top")] = "0.247cm"
theAttr[_mkTag("fo", "margin-bottom")] = "0.212cm"
theAttr[_mkTag("style", "contextual-spacing")] = "false"
etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("fo", "font-size")] = "110%"
theAttr[_mkTag("fo", "font-weight")] = "bold"
etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
# Add Heading 4 Style
# ===================
theAttr = {}
theAttr[_mkTag("style", "name")] = "Heading_4"
theAttr[_mkTag("style", "display-name")] = "Heading 4"
theAttr[_mkTag("style", "family")] = "paragraph"
theAttr[_mkTag("style", "parent-style-name")] = "Heading"
theAttr[_mkTag("style", "next-style-name")] = "Text_body"
theAttr[_mkTag("style", "default-outline-level")] = "4"
theAttr[_mkTag("style", "class")] = "text"
xStyl = etree.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("fo", "margin-top")] = "0.247cm"
theAttr[_mkTag("fo", "margin-bottom")] = "0.212cm"
theAttr[_mkTag("style", "contextual-spacing")] = "false"
etree.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
theAttr = {}
theAttr[_mkTag("fo", "font-size")] = "100%"
theAttr[_mkTag("fo", "font-weight")] = "bold"
etree.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
return
# END Class ToOdt
# =========================================================================== #
# Local Functions
# =========================================================================== #
def _mkTag(nsName, tagName):
"""Assemble namespace and tag name.
"""
theNS = XML_NS.get(nsName, "")
if theNS:
return "{%s}%s" % (theNS, tagName)
logger.warning("Missing xml namespace '%s'" % nsName)
return tagName
+17 -1
View File
@@ -20,16 +20,32 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import nw
import pytest
from nw.core import NWProject, NWIndex, ToOdt
@pytest.mark.core
def testCoreToOdt_Convert(dummyGUI):
def testCoreToOdt_Convert(tmpConf, dummyGUI):
"""Test the converter of the ToHtml class.
"""
nw.CONFIG = tmpConf
theProject = NWProject(dummyGUI)
dummyGUI.theIndex = NWIndex(theProject, dummyGUI)
theDoc = ToOdt(theProject, dummyGUI)
# Export Mode
# ===========
theDoc.isNovel = True
# Header 1
theDoc.theText = "# Title\n"
theDoc.tokenizeText()
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.theResult == ""
# END Test testCoreToOdt_Convert