Add annotations to odt class

This commit is contained in:
Veronica Berglyd Olsen
2023-06-06 22:12:56 +02:00
parent 6b6c517b1f
commit b09068ab99
6 changed files with 322 additions and 333 deletions
+5 -1
View File
@@ -1,7 +1,6 @@
"""
novelWriter HTML Text Converter
=================================
Extends the Tokenizer class to generate HTML output
File History:
Created: 2019-05-07 [0.0.1]
@@ -37,6 +36,11 @@ logger = logging.getLogger(__name__)
class ToHtml(Tokenizer):
"""Core: HTML Document Writer
Extend the Tokenizer class to writer HTML output. This class is
also used by the Document Viewer, and Manuscript Build Preview.
"""
M_PREVIEW = 0 # Tweak output for the DocViewer
M_EXPORT = 1 # Tweak output for saving to HTML or printing
+12 -4
View File
@@ -1,7 +1,6 @@
"""
novelWriter Text Tokenizer
============================
Split novelWriter plain text into its elements
File History:
Created: 2019-05-05 [0.0.1] Tokenizer
@@ -55,6 +54,13 @@ def stripEscape(text):
class Tokenizer(ABC):
"""Core: Text Tokenizer Abstract Base Class
This is the base class for all document build classes. It parses the
novelWriter markup format and generates a registry of tokens and
text that can be further processed into other output formats by
subclasses.
"""
# In-Text Format
FMT_B_B = 1 # Begin bold
@@ -309,6 +315,9 @@ class Tokenizer(ABC):
"""Add a heading at the start of a new root folder."""
if not self._project.tree.checkType(tHandle, nwItemType.ROOT):
return False
theItem = self._project.tree[tHandle]
if not theItem:
return False
if self._isFirst:
textAlign = self.A_CENTRE
@@ -316,7 +325,6 @@ class Tokenizer(ABC):
else:
textAlign = self.A_PBB | self.A_CENTRE
theItem = self._project.tree[tHandle]
locNotes = self._localLookup("Notes")
theTitle = f"{locNotes}: {theItem.itemName}"
self._tokens = []
@@ -781,10 +789,10 @@ class HeadingFormatter:
chWord = self._project.localLookup(self._chCount)
hFormat = hFormat.replace(nwHeadFmt.CH_WORD, chWord)
if nwHeadFmt.CH_ROML in hFormat:
chRom = numberToRoman(self._chCount, True)
chRom = numberToRoman(self._chCount, toLower=True)
hFormat = hFormat.replace(nwHeadFmt.CH_ROML, chRom)
if nwHeadFmt.CH_ROMU in hFormat:
chRom = numberToRoman(self._chCount, False)
chRom = numberToRoman(self._chCount, toLower=False)
hFormat = hFormat.replace(nwHeadFmt.CH_ROMU, chRom)
return hFormat
+6 -1
View File
@@ -1,7 +1,6 @@
"""
novelWriter Markdown Text Converter
=====================================
Extends the Tokenizer class to generate Makrdown output
File History:
Created: 2021-02-06 [1.2b1]
@@ -36,6 +35,12 @@ logger = logging.getLogger(__name__)
class ToMarkdown(Tokenizer):
"""Core: Markdown Document Writer
Extend the Tokenizer class to writer Markdown output. It supports
both Standard Markdown and GitHub Flavour Markdown (Extended). The
class also supports concatenating novelWriter markup files.
"""
M_STD = 0 # Standard Markdown
M_GH = 1 # GitHub Markdown
+248 -268
View File
@@ -1,7 +1,6 @@
"""
novelWriter ODT Text Converter
================================
Extends the Tokenizer class to generate ODT and FODT files
File History:
Created: 2021-01-26 [1.2b1] ToOdt
@@ -25,8 +24,10 @@ General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from __future__ import annotations
import logging
from pathlib import Path
import xml.etree.ElementTree as ET
from hashlib import sha256
@@ -36,6 +37,7 @@ from datetime import datetime
from novelwriter import __version__
from novelwriter.common import xmlIndent
from novelwriter.constants import nwKeyWords, nwLabels
from novelwriter.core.project import NWProject
from novelwriter.core.tokenizer import Tokenizer, stripEscape
logger = logging.getLogger(__name__)
@@ -55,9 +57,8 @@ for ns, uri in XML_NS.items():
ET.register_namespace(ns, uri)
def _mkTag(ns, tag):
"""Assemble namespace and tag name.
"""
def _mkTag(ns: str, tag: str) -> str:
"""Assemble namespace and tag name."""
uri = XML_NS.get(ns, "")
if uri:
return f"{{{uri}}}{tag}"
@@ -89,9 +90,16 @@ M_DEL = ~X_DEL
class ToOdt(Tokenizer):
"""Core: Open Document Writer
def __init__(self, theProject, isFlat):
super().__init__(theProject)
Extend the Tokenizer class to writer Open Document files. The output
should conform to the 1.3 Extended standard.
Test with: https://odfvalidator.org/
"""
def __init__(self, project: NWProject, isFlat: bool):
super().__init__(project)
self._isFlat = isFlat # Flat: .fodt, otherwise .odt
@@ -178,36 +186,26 @@ class ToOdt(Tokenizer):
# Setters
##
def setLanguage(self, theLang):
"""Set language for the document.
"""
if theLang is None:
return False
def setLanguage(self, language: str):
"""Set language for the document."""
if language:
langBits = language.split("_")
self._dLanguage = langBits[0]
if len(langBits) > 1:
self._dCountry = langBits[1]
return
langBits = theLang.split("_")
self._dLanguage = langBits[0]
if len(langBits) > 1:
self._dCountry = langBits[1]
return True
def setColourHeaders(self, doColour):
"""Enable/disable coloured headings and comments.
"""
self._colourHead = doColour
def setColourHeaders(self, state: bool):
"""Enable/disable coloured headings and comments."""
self._colourHead = state
return
##
# Class Methods
##
def getErrors(self):
"""Return the list of errors."""
return self._errData
def initDocument(self):
"""Initialises a new open document XML tree.
"""
"""Initialises a new open document XML tree."""
# Initialise Variables
# ====================
@@ -369,8 +367,7 @@ class ToOdt(Tokenizer):
return
def doConvert(self):
"""Convert the list of text tokens into XML elements.
"""
"""Convert the list of text tokens into XML elements."""
self._result = "" # Not used, but cleared just in case
odtTags = {
@@ -421,12 +418,12 @@ class ToOdt(Tokenizer):
if self._doJustify:
parStyle.setTextAlign("left")
if len(thisPar) > 0:
if len(thisPar) > 0 and parStyle is not None:
tTemp = "\n".join(thisPar)
fTemp = " ".join(thisFmt)
tTxt = tTemp.rstrip()
tFmt = fTemp[:len(tTxt)]
self._addTextPar("Text_20_body", parStyle, tTxt, theFmt=tFmt)
self._addTextPar("Text_20_body", parStyle, tTxt, tFmt=tFmt)
thisPar = []
thisFmt = []
@@ -477,41 +474,37 @@ class ToOdt(Tokenizer):
elif tType == self.T_SYNOPSIS and self._doSynopsis:
tTemp, fTemp = self._formatSynopsis(tText)
self._addTextPar("Text_20_Meta", oStyle, tTemp, theFmt=fTemp)
self._addTextPar("Text_20_Meta", oStyle, tTemp, tFmt=fTemp)
elif tType == self.T_COMMENT and self._doComments:
tTemp, fTemp = self._formatComments(tText)
self._addTextPar("Text_20_Meta", oStyle, tTemp, theFmt=fTemp)
self._addTextPar("Text_20_Meta", oStyle, tTemp, tFmt=fTemp)
elif tType == self.T_KEYWORD and self._doKeywords:
tTemp, fTemp = self._formatKeywords(tText)
self._addTextPar("Text_20_Meta", oStyle, tTemp, theFmt=fTemp)
self._addTextPar("Text_20_Meta", oStyle, tTemp, tFmt=fTemp)
return
def closeDocument(self):
"""Return the serialised XML document
"""
"""Return the serialised XML document"""
# Build the auto-generated styles
for styleName, styleObj in self._autoPara.values():
styleObj.packXML(self._xAuto, styleName)
for styleName, styleObj in self._autoText.values():
styleObj.packXML(self._xAuto, styleName)
return
def saveFlatXML(self, savePath):
"""Save the data to an .fodt file.
"""
with open(savePath, mode="wb") as outFile:
def saveFlatXML(self, path: str | Path):
"""Save the data to an .fodt file."""
with open(path, mode="wb") as fObj:
xml = ET.ElementTree(self._dFlat)
xmlIndent(xml)
xml.write(outFile, encoding="utf-8", xml_declaration=True)
xml.write(fObj, encoding="utf-8", xml_declaration=True)
return
def saveOpenDocText(self, savePath):
"""Save the data to an .odt file.
"""
def saveOpenDocText(self, path: str | Path):
"""Save the data to an .odt file."""
mMani = _mkTag("manifest", "manifest")
mVers = _mkTag("manifest", "version")
mPath = _mkTag("manifest", "full-path")
@@ -534,7 +527,7 @@ class ToOdt(Tokenizer):
xml = ET.ElementTree(xObj)
xml.write(fObj, encoding="utf-8", xml_declaration=True)
with ZipFile(savePath, mode="w") as outZip:
with ZipFile(path, mode="w") as outZip:
outZip.writestr("mimetype", X_MIME)
putInZip("META-INF/manifest.xml", xMani, outZip)
putInZip("settings.xml", xSett, outZip)
@@ -548,49 +541,48 @@ class ToOdt(Tokenizer):
# Internal Functions
##
def _formatSynopsis(self, tText):
"""Apply formatting to synopsis lines.
"""
def _formatSynopsis(self, text: str) -> tuple[str, str]:
"""Apply formatting to synopsis lines."""
sSynop = self._localLookup("Synopsis")
rTxt = "**{0}:** {1}".format(sSynop, tText)
rFmt = "_B{0} b_ {1}".format(" "*len(sSynop), " "*len(tText))
rTxt = "**{0}:** {1}".format(sSynop, text)
rFmt = "_B{0} b_ {1}".format(" "*len(sSynop), " "*len(text))
return rTxt, rFmt
def _formatComments(self, tText):
"""Apply formatting to comments.
"""
def _formatComments(self, text: str) -> tuple[str, str]:
"""Apply formatting to comments."""
sComm = self._localLookup("Comment")
rTxt = "**{0}:** {1}".format(sComm, tText)
rFmt = "_B{0} b_ {1}".format(" "*len(sComm), " "*len(tText))
rTxt = "**{0}:** {1}".format(sComm, text)
rFmt = "_B{0} b_ {1}".format(" "*len(sComm), " "*len(text))
return rTxt, rFmt
def _formatKeywords(self, tText):
"""Apply formatting to keywords.
"""
isValid, theBits, _ = self._project.index.scanThis("@"+tText)
if not isValid or not theBits:
return ""
def _formatKeywords(self, text: str) -> tuple[str, str]:
"""Apply formatting to keywords."""
valid, bits, _ = self._project.index.scanThis("@"+text)
if not valid or not bits:
return "", ""
rTxt = ""
rFmt = ""
if theBits[0] in nwLabels.KEY_NAME:
tText = nwLabels.KEY_NAME[theBits[0]]
rTxt += "**{0}:** ".format(tText)
rFmt += "_B{0} b_ ".format(" "*len(tText))
if len(theBits) > 1:
if theBits[0] == nwKeyWords.TAG_KEY:
rTxt += theBits[1]
rFmt += " "*len(theBits[1])
if bits[0] in nwLabels.KEY_NAME:
text = nwLabels.KEY_NAME[bits[0]]
rTxt += "**{0}:** ".format(text)
rFmt += "_B{0} b_ ".format(" "*len(text))
if len(bits) > 1:
if bits[0] == nwKeyWords.TAG_KEY:
rTxt += bits[1]
rFmt += " "*len(bits[1])
else:
tTags = ", ".join(theBits[1:])
tTags = ", ".join(bits[1:])
rTxt += tTags
rFmt += (" "*len(tTags))
return rTxt, rFmt
def _addTextPar(self, styleName, oStyle, theText, theFmt="", isHead=False, oLevel=None):
"""Add a text paragraph to the text XML element.
"""
def _addTextPar(
self, styleName: str, oStyle: ODTParagraphStyle, tText: str, tFmt: str = "",
isHead: bool = False, oLevel: str | None = None
):
"""Add a text paragraph to the text XML element."""
tAttr = {}
tAttr[_mkTag("text", "style-name")] = self._paraStyle(styleName, oStyle)
if oLevel is not None:
@@ -603,16 +595,16 @@ class ToOdt(Tokenizer):
# xmlIndent will add a line break if the first subelement is a span.
xElem.text = ""
if not theText:
if not tText:
return
##
# Process Formatting
##
if len(theText) != len(theFmt):
if len(tText) != len(tFmt):
# Generate an empty format if there isn't any or it doesn't match
theFmt = " "*len(theText)
tFmt = " "*len(tText)
# The formatting loop
tTemp = ""
@@ -622,23 +614,23 @@ class ToOdt(Tokenizer):
parProc = XMLParagraph(xElem)
for i, c in enumerate(theText):
for i, c in enumerate(tText):
if theFmt[i] == " ":
if tFmt[i] == " ":
tTemp += c
elif theFmt[i] == "_":
elif tFmt[i] == "_":
continue
elif theFmt[i] == "B":
elif tFmt[i] == "B":
xFmt |= X_BLD
elif theFmt[i] == "b":
elif tFmt[i] == "b":
xFmt &= M_BLD
elif theFmt[i] == "I":
elif tFmt[i] == "I":
xFmt |= X_ITA
elif theFmt[i] == "i":
elif tFmt[i] == "i":
xFmt &= M_ITA
elif theFmt[i] == "S":
elif tFmt[i] == "S":
xFmt |= X_DEL
elif theFmt[i] == "s":
elif tFmt[i] == "s":
xFmt &= M_DEL
else:
pErr += 1
@@ -669,9 +661,8 @@ class ToOdt(Tokenizer):
return
def _paraStyle(self, parName, oStyle):
"""Return a name for a style object.
"""
def _paraStyle(self, parName: str, oStyle: ODTParagraphStyle) -> str:
"""Return a name for a style object."""
refStyle = self._mainPara.get(parName, None)
if refStyle is None:
logger.error("Unknown paragraph style '%s'", parName)
@@ -690,29 +681,27 @@ class ToOdt(Tokenizer):
return newName
def _textStyle(self, tFmt):
"""Return a text style for a given style code.
"""
if tFmt in self._autoText:
return self._autoText[tFmt][0]
def _textStyle(self, hFmt: int) -> str:
"""Return a text style for a given style code."""
if hFmt in self._autoText:
return self._autoText[hFmt][0]
newName = "T%d" % (len(self._autoText) + 1)
newStyle = ODTTextStyle()
if tFmt & X_BLD:
if hFmt & X_BLD:
newStyle.setFontWeight("bold")
if tFmt & X_ITA:
if hFmt & X_ITA:
newStyle.setFontStyle("italic")
if tFmt & X_DEL:
if hFmt & X_DEL:
newStyle.setStrikeStyle("solid")
newStyle.setStrikeType("single")
self._autoText[tFmt] = (newName, newStyle)
self._autoText[hFmt] = (newName, newStyle)
return newName
def _emToCm(self, emVal):
"""Converts an em value to centimetres.
"""
def _emToCm(self, emVal: float) -> str:
"""Converts an em value to centimetres."""
return f"{emVal*2.54/72*self._textSize:.3f}cm"
##
@@ -720,110 +709,107 @@ class ToOdt(Tokenizer):
##
def _pageStyles(self):
"""Set the default page style.
"""
theAttr = {}
theAttr[_mkTag("style", "name")] = "PM1"
"""Set the default page style."""
tAttr = {}
tAttr[_mkTag("style", "name")] = "PM1"
if self._isFlat:
xPage = ET.SubElement(self._xAuto, _mkTag("style", "page-layout"), attrib=theAttr)
xPage = ET.SubElement(self._xAuto, _mkTag("style", "page-layout"), attrib=tAttr)
else:
xPage = ET.SubElement(self._xAut2, _mkTag("style", "page-layout"), attrib=theAttr)
xPage = ET.SubElement(self._xAut2, _mkTag("style", "page-layout"), attrib=tAttr)
theAttr = {}
theAttr[_mkTag("fo", "margin-top")] = self._mDocTop
theAttr[_mkTag("fo", "margin-bottom")] = self._mDocBtm
theAttr[_mkTag("fo", "margin-left")] = self._mDocLeft
theAttr[_mkTag("fo", "margin-right")] = self._mDocRight
ET.SubElement(xPage, _mkTag("style", "page-layout-properties"), attrib=theAttr)
tAttr = {}
tAttr[_mkTag("fo", "margin-top")] = self._mDocTop
tAttr[_mkTag("fo", "margin-bottom")] = self._mDocBtm
tAttr[_mkTag("fo", "margin-left")] = self._mDocLeft
tAttr[_mkTag("fo", "margin-right")] = self._mDocRight
ET.SubElement(xPage, _mkTag("style", "page-layout-properties"), attrib=tAttr)
xHead = ET.SubElement(xPage, _mkTag("style", "header-style"))
theAttr = {}
theAttr[_mkTag("fo", "min-height")] = "0.600cm"
theAttr[_mkTag("fo", "margin-left")] = "0.000cm"
theAttr[_mkTag("fo", "margin-right")] = "0.000cm"
theAttr[_mkTag("fo", "margin-bottom")] = "0.500cm"
ET.SubElement(xHead, _mkTag("style", "header-footer-properties"), attrib=theAttr)
tAttr = {}
tAttr[_mkTag("fo", "min-height")] = "0.600cm"
tAttr[_mkTag("fo", "margin-left")] = "0.000cm"
tAttr[_mkTag("fo", "margin-right")] = "0.000cm"
tAttr[_mkTag("fo", "margin-bottom")] = "0.500cm"
ET.SubElement(xHead, _mkTag("style", "header-footer-properties"), attrib=tAttr)
return
def _defaultStyles(self):
"""Set the default styles.
"""
"""Set the default styles."""
# Add Paragraph Family Style
# ==========================
theAttr = {}
theAttr[_mkTag("style", "family")] = "paragraph"
xStyl = ET.SubElement(self._xStyl, _mkTag("style", "default-style"), attrib=theAttr)
tAttr = {}
tAttr[_mkTag("style", "family")] = "paragraph"
xStyl = ET.SubElement(self._xStyl, _mkTag("style", "default-style"), attrib=tAttr)
theAttr = {}
theAttr[_mkTag("style", "line-break")] = "strict"
theAttr[_mkTag("style", "tab-stop-distance")] = "1.251cm"
theAttr[_mkTag("style", "writing-mode")] = "page"
ET.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
tAttr = {}
tAttr[_mkTag("style", "line-break")] = "strict"
tAttr[_mkTag("style", "tab-stop-distance")] = "1.251cm"
tAttr[_mkTag("style", "writing-mode")] = "page"
ET.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=tAttr)
theAttr = {}
theAttr[_mkTag("style", "font-name")] = self._textFont
theAttr[_mkTag("fo", "font-family")] = self._fontFamily
theAttr[_mkTag("fo", "font-size")] = self._fSizeText
theAttr[_mkTag("fo", "language")] = self._dLanguage
theAttr[_mkTag("fo", "country")] = self._dCountry
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
tAttr = {}
tAttr[_mkTag("style", "font-name")] = self._textFont
tAttr[_mkTag("fo", "font-family")] = self._fontFamily
tAttr[_mkTag("fo", "font-size")] = self._fSizeText
tAttr[_mkTag("fo", "language")] = self._dLanguage
tAttr[_mkTag("fo", "country")] = self._dCountry
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=tAttr)
# Add Standard Paragraph Style
# ============================
theAttr = {}
theAttr[_mkTag("style", "name")] = "Standard"
theAttr[_mkTag("style", "family")] = "paragraph"
theAttr[_mkTag("style", "class")] = "text"
xStyl = ET.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
tAttr = {}
tAttr[_mkTag("style", "name")] = "Standard"
tAttr[_mkTag("style", "family")] = "paragraph"
tAttr[_mkTag("style", "class")] = "text"
xStyl = ET.SubElement(self._xStyl, _mkTag("style", "style"), attrib=tAttr)
theAttr = {}
theAttr[_mkTag("style", "font-name")] = self._textFont
theAttr[_mkTag("fo", "font-family")] = self._fontFamily
theAttr[_mkTag("fo", "font-size")] = self._fSizeText
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
tAttr = {}
tAttr[_mkTag("style", "font-name")] = self._textFont
tAttr[_mkTag("fo", "font-family")] = self._fontFamily
tAttr[_mkTag("fo", "font-size")] = self._fSizeText
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=tAttr)
# 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_20_body"
theAttr[_mkTag("style", "class")] = "text"
xStyl = ET.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
tAttr = {}
tAttr[_mkTag("style", "name")] = "Heading"
tAttr[_mkTag("style", "family")] = "paragraph"
tAttr[_mkTag("style", "parent-style-name")] = "Standard"
tAttr[_mkTag("style", "next-style-name")] = "Text_20_body"
tAttr[_mkTag("style", "class")] = "text"
xStyl = ET.SubElement(self._xStyl, _mkTag("style", "style"), attrib=tAttr)
theAttr = {}
theAttr[_mkTag("fo", "margin-top")] = self._mTopHead
theAttr[_mkTag("fo", "margin-bottom")] = self._mBotHead
theAttr[_mkTag("fo", "keep-with-next")] = "always"
ET.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=theAttr)
tAttr = {}
tAttr[_mkTag("fo", "margin-top")] = self._mTopHead
tAttr[_mkTag("fo", "margin-bottom")] = self._mBotHead
tAttr[_mkTag("fo", "keep-with-next")] = "always"
ET.SubElement(xStyl, _mkTag("style", "paragraph-properties"), attrib=tAttr)
theAttr = {}
theAttr[_mkTag("style", "font-name")] = self._textFont
theAttr[_mkTag("fo", "font-family")] = self._fontFamily
theAttr[_mkTag("fo", "font-size")] = self._fSizeHead
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=theAttr)
tAttr = {}
tAttr[_mkTag("style", "font-name")] = self._textFont
tAttr[_mkTag("fo", "font-family")] = self._fontFamily
tAttr[_mkTag("fo", "font-size")] = self._fSizeHead
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib=tAttr)
# Add Header and Footer Styles
# ============================
theAttr = {}
theAttr[_mkTag("style", "name")] = "Header_20_and_20_Footer"
theAttr[_mkTag("style", "display-name")] = "Header and Footer"
theAttr[_mkTag("style", "family")] = "paragraph"
theAttr[_mkTag("style", "parent-style-name")] = "Standard"
theAttr[_mkTag("style", "class")] = "extra"
ET.SubElement(self._xStyl, _mkTag("style", "style"), attrib=theAttr)
tAttr = {}
tAttr[_mkTag("style", "name")] = "Header_20_and_20_Footer"
tAttr[_mkTag("style", "display-name")] = "Header and Footer"
tAttr[_mkTag("style", "family")] = "paragraph"
tAttr[_mkTag("style", "parent-style-name")] = "Standard"
tAttr[_mkTag("style", "class")] = "extra"
ET.SubElement(self._xStyl, _mkTag("style", "style"), attrib=tAttr)
return
def _useableStyles(self):
"""Set the usable styles.
"""
"""Set the usable styles."""
# Add Text Body Style
# ===================
@@ -977,12 +963,11 @@ class ToOdt(Tokenizer):
return
def _writeHeader(self):
"""Write the header elements.
"""
theAttr = {}
theAttr[_mkTag("style", "name")] = "Standard"
theAttr[_mkTag("style", "page-layout-name")] = "PM1"
xPage = ET.SubElement(self._xMast, _mkTag("style", "master-page"), attrib=theAttr)
"""Write the header elements."""
tAttr = {}
tAttr[_mkTag("style", "name")] = "Standard"
tAttr[_mkTag("style", "page-layout-name")] = "PM1"
xPage = ET.SubElement(self._xMast, _mkTag("style", "master-page"), attrib=tAttr)
# Standard Page Header
xHead = ET.SubElement(xPage, _mkTag("style", "header"))
@@ -1062,28 +1047,28 @@ class ODTParagraphStyle:
# Attribute Setters
##
def setDisplayName(self, theValue):
self._mAttr["display-name"][1] = str(theValue)
def setDisplayName(self, value: str | None):
self._mAttr["display-name"][1] = value
return
def setParentStyleName(self, theValue):
self._mAttr["parent-style-name"][1] = str(theValue)
def setParentStyleName(self, value: str | None):
self._mAttr["parent-style-name"][1] = value
return
def setNextStyleName(self, theValue):
self._mAttr["next-style-name"][1] = str(theValue)
def setNextStyleName(self, value: str | None):
self._mAttr["next-style-name"][1] = value
return
def setOutlineLevel(self, theValue):
if theValue in self.VALID_LEVEL:
self._mAttr["default-outline-level"][1] = str(theValue)
def setOutlineLevel(self, value: str | None):
if value in self.VALID_LEVEL:
self._mAttr["default-outline-level"][1] = value
else:
self._mAttr["default-outline-level"][1] = None
return
def setClass(self, theValue):
if theValue in self.VALID_CLASS:
self._mAttr["class"][1] = str(theValue)
def setClass(self, value: str | None):
if value in self.VALID_CLASS:
self._mAttr["class"][1] = value
else:
self._mAttr["class"][1] = None
return
@@ -1092,43 +1077,43 @@ class ODTParagraphStyle:
# Paragraph Setters
##
def setMarginTop(self, theValue):
self._pAttr["margin-top"][1] = str(theValue)
def setMarginTop(self, value: str | None):
self._pAttr["margin-top"][1] = value
return
def setMarginBottom(self, theValue):
self._pAttr["margin-bottom"][1] = str(theValue)
def setMarginBottom(self, value: str | None):
self._pAttr["margin-bottom"][1] = value
return
def setMarginLeft(self, theValue):
self._pAttr["margin-left"][1] = str(theValue)
def setMarginLeft(self, value: str | None):
self._pAttr["margin-left"][1] = value
return
def setMarginRight(self, theValue):
self._pAttr["margin-right"][1] = str(theValue)
def setMarginRight(self, value: str | None):
self._pAttr["margin-right"][1] = value
return
def setLineHeight(self, theValue):
self._pAttr["line-height"][1] = str(theValue)
def setLineHeight(self, value: str | None):
self._pAttr["line-height"][1] = value
return
def setTextAlign(self, theValue):
if theValue in self.VALID_ALIGN:
self._pAttr["text-align"][1] = str(theValue)
def setTextAlign(self, value: str | None):
if value in self.VALID_ALIGN:
self._pAttr["text-align"][1] = value
else:
self._pAttr["text-align"][1] = None
return
def setBreakBefore(self, theValue):
if theValue in self.VALID_BREAK:
self._pAttr["break-before"][1] = str(theValue)
def setBreakBefore(self, value: str | None):
if value in self.VALID_BREAK:
self._pAttr["break-before"][1] = value
else:
self._pAttr["break-before"][1] = None
return
def setBreakAfter(self, theValue):
if theValue in self.VALID_BREAK:
self._pAttr["break-after"][1] = str(theValue)
def setBreakAfter(self, value: str | None):
if value in self.VALID_BREAK:
self._pAttr["break-after"][1] = value
else:
self._pAttr["break-after"][1] = None
return
@@ -1137,38 +1122,38 @@ class ODTParagraphStyle:
# Text Setters
##
def setFontName(self, theValue):
self._tAttr["font-name"][1] = str(theValue)
def setFontName(self, value: str | None):
self._tAttr["font-name"][1] = value
return
def setFontFamily(self, theValue):
self._tAttr["font-family"][1] = str(theValue)
def setFontFamily(self, value: str | None):
self._tAttr["font-family"][1] = value
return
def setFontSize(self, theValue):
self._tAttr["font-size"][1] = str(theValue)
def setFontSize(self, value: str | None):
self._tAttr["font-size"][1] = value
return
def setFontWeight(self, theValue):
if theValue in self.VALID_WEIGHT:
self._tAttr["font-weight"][1] = str(theValue)
def setFontWeight(self, value: str | None):
if value in self.VALID_WEIGHT:
self._tAttr["font-weight"][1] = value
else:
self._tAttr["font-weight"][1] = None
return
def setColor(self, theValue):
self._tAttr["color"][1] = str(theValue)
def setColor(self, value: str | None):
self._tAttr["color"][1] = value
return
def setOpacity(self, theValue):
self._tAttr["opacity"][1] = str(theValue)
def setOpacity(self, value: str | None):
self._tAttr["opacity"][1] = value
return
##
# Methods
##
def checkNew(self, refStyle):
def checkNew(self, refStyle: ODTParagraphStyle):
"""Check if there are new settings in refStyle that differ from
those in the current object.
"""
@@ -1183,9 +1168,8 @@ class ODTParagraphStyle:
return True
return False
def getID(self):
"""Generate a unique ID from the settings.
"""
def getID(self) -> str:
"""Generate a unique ID from the settings."""
theString = (
f"Paragraph:Main:{str(self._mAttr)}:"
f"Paragraph:Para:{str(self._pAttr)}:"
@@ -1193,11 +1177,10 @@ class ODTParagraphStyle:
)
return sha256(theString.encode()).hexdigest()
def packXML(self, xParent, xName):
"""Pack the content into an xml element.
"""
def packXML(self, xParent: ET.Element, name: str):
"""Pack the content into an xml element."""
theAttr = {}
theAttr[_mkTag("style", "name")] = xName
theAttr[_mkTag("style", "name")] = name
theAttr[_mkTag("style", "family")] = "paragraph"
for aName, (aNm, aVal) in self._mAttr.items():
if aVal is not None:
@@ -1252,30 +1235,30 @@ class ODTTextStyle:
# Setters
##
def setFontWeight(self, theValue):
if theValue in self.VALID_WEIGHT:
self._tAttr["font-weight"][1] = str(theValue)
def setFontWeight(self, value: str | None):
if value in self.VALID_WEIGHT:
self._tAttr["font-weight"][1] = value
else:
self._tAttr["font-weight"][1] = None
return
def setFontStyle(self, theValue):
if theValue in self.VALID_STYLE:
self._tAttr["font-style"][1] = str(theValue)
def setFontStyle(self, value: str | None):
if value in self.VALID_STYLE:
self._tAttr["font-style"][1] = value
else:
self._tAttr["font-style"][1] = None
return
def setStrikeStyle(self, theValue):
if theValue in self.VALID_LSTYLE:
self._tAttr["text-line-through-style"][1] = str(theValue)
def setStrikeStyle(self, value: str | None):
if value in self.VALID_LSTYLE:
self._tAttr["text-line-through-style"][1] = value
else:
self._tAttr["text-line-through-style"][1] = None
return
def setStrikeType(self, theValue):
if theValue in self.VALID_LTYPE:
self._tAttr["text-line-through-type"][1] = str(theValue)
def setStrikeType(self, value: str | None):
if value in self.VALID_LTYPE:
self._tAttr["text-line-through-type"][1] = value
else:
self._tAttr["text-line-through-type"][1] = None
return
@@ -1284,11 +1267,10 @@ class ODTTextStyle:
# Methods
##
def packXML(self, xParent, xName):
"""Pack the content into an xml element.
"""
def packXML(self, xParent: ET.Element, name: str):
"""Pack the content into an xml element."""
theAttr = {}
theAttr[_mkTag("style", "name")] = xName
theAttr[_mkTag("style", "name")] = name
theAttr[_mkTag("style", "family")] = "text"
xEntry = ET.SubElement(xParent, _mkTag("style", "style"), attrib=theAttr)
@@ -1335,7 +1317,7 @@ class XMLParagraph:
object and attribute is written to,
"""
def __init__(self, xRoot):
def __init__(self, xRoot: ET.Element):
self._xRoot = xRoot
self._xTail = ET.Element("")
@@ -1348,17 +1330,17 @@ class XMLParagraph:
return
def appendText(self, text):
def appendText(self, tText: str):
"""Append text to the XML element. We do this one character at
the time in order to be able to process line breaks, tabs and
spaces separately. Multiple spaces above one are concatenated
into a single tag, and must therefore be processed separately.
spaces separately. Multiple spaces are concatenated into a
single tag, and must therefore be processed separately.
"""
text = stripEscape(text)
tText = stripEscape(tText)
nSpaces = 0
self._rawTxt += text
self._rawTxt += tText
for c in text:
for c in tText:
if c == " ":
nSpaces += 1
continue
@@ -1395,38 +1377,36 @@ class XMLParagraph:
else:
if self._nState == X_ROOT_TEXT:
self._xRoot.text += c
self._xRoot.text = (self._xRoot.text or "") + c
self._chrPos += 1
elif self._nState == X_ROOT_TAIL:
self._xTail.tail += c
self._xTail.tail = (self._xTail.tail or "") + c
self._chrPos += 1
elif self._nState == X_SPAN_TEXT:
self._xTail.text += c
self._xTail.text = (self._xTail.text or "") + c
self._chrPos += 1
elif self._nState == X_SPAN_SING:
self._xSing.tail += c
self._xSing.tail = (self._xSing.tail or "") + c
self._chrPos += 1
if nSpaces > 0:
# Handle trailing spaces
self._processSpaces(nSpaces)
return
def appendSpan(self, tText, tFmt):
def appendSpan(self, tText: str, tFmt: str):
"""Append a text span to the XML element. The span is always
closed since we do not allow nested spans (like Libre Office).
Therefore we return to the root element level when we're done
processing the text of the span.
"""
self._xTail = ET.SubElement(self._xRoot, TAG_SPAN, attrib={
TAG_STNM: tFmt
})
self._xTail = ET.SubElement(self._xRoot, TAG_SPAN, attrib={TAG_STNM: tFmt})
self._xTail.text = "" # Defaults to None
self._xTail.tail = "" # Defaults to None
self._nState = X_SPAN_TEXT
self.appendText(tText)
self._nState = X_ROOT_TAIL
return
def checkError(self):
@@ -1443,7 +1423,7 @@ class XMLParagraph:
# Internal Functions
##
def _processSpaces(self, nSpaces):
def _processSpaces(self, nSpaces: int):
"""Add spaces to paragraph. The first space is always written
as-is (unless it's the first character of the paragraph). The
second space uses the dedicated tag for spaces, and from the
@@ -1455,16 +1435,16 @@ class XMLParagraph:
if nSpaces > 0:
if self._chrPos > 0:
if self._nState == X_ROOT_TEXT:
self._xRoot.text += " "
self._xRoot.text = (self._xRoot.text or "") + " "
self._chrPos += 1
elif self._nState == X_ROOT_TAIL:
self._xTail.tail += " "
self._xTail.tail = (self._xTail.tail or "") + " "
self._chrPos += 1
elif self._nState == X_SPAN_TEXT:
self._xTail.text += " "
self._xTail.text = (self._xTail.text or "") + " "
self._chrPos += 1
elif self._nState == X_SPAN_SING:
self._xSing.tail += " "
self._xSing.tail = (self._xSing.tail or "") + " "
self._chrPos += 1
else:
nSpaces += 1
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<office:document-styles xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" office:version="1.3">
<office:document-styles xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" office:version="1.3">
<office:font-face-decls>
<style:font-face style:name="Liberation Serif" style:font-pitch="variable" />
</office:font-face-decls>
@@ -22,7 +22,7 @@
</style:style>
<style:style style:name="Text_20_Meta" style:family="paragraph" style:display-name="Text Meta" style:parent-style-name="Standard" style:class="text">
<style:paragraph-properties fo:margin-top="0.000cm" fo:margin-bottom="0.247cm" fo:line-height="115%" />
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="12pt" fo:color="None" loext:opacity="None" />
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="12pt" />
</style:style>
<style:style style:name="Title" style:family="paragraph" style:display-name="Title" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter">
<style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" fo:text-align="center" />
@@ -30,19 +30,19 @@
</style:style>
<style:style style:name="Heading_20_1" style:family="paragraph" style:display-name="Heading 1" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text">
<style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" />
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="24pt" fo:font-weight="bold" fo:color="None" loext:opacity="None" />
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="24pt" fo:font-weight="bold" />
</style:style>
<style:style style:name="Heading_20_2" style:family="paragraph" style:display-name="Heading 2" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text">
<style:paragraph-properties fo:margin-top="0.353cm" fo:margin-bottom="0.212cm" />
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="19pt" fo:font-weight="bold" fo:color="None" loext:opacity="None" />
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="19pt" fo:font-weight="bold" />
</style:style>
<style:style style:name="Heading_20_3" style:family="paragraph" style:display-name="Heading 3" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text">
<style:paragraph-properties fo:margin-top="0.247cm" fo:margin-bottom="0.212cm" />
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="16pt" fo:font-weight="bold" fo:color="None" loext:opacity="None" />
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="16pt" fo:font-weight="bold" />
</style:style>
<style:style style:name="Heading_20_4" style:family="paragraph" style:display-name="Heading 4" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="4" style:class="text">
<style:paragraph-properties fo:margin-top="0.247cm" fo:margin-bottom="0.212cm" />
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="14pt" fo:font-weight="bold" fo:color="None" loext:opacity="None" />
<style:text-properties style:font-name="Liberation Serif" fo:font-family="'Liberation Serif'" fo:font-size="14pt" fo:font-weight="bold" />
</style:style>
<style:style style:name="Header" style:family="paragraph" style:display-name="Header" style:parent-style-name="Header_20_and_20_Footer">
<style:paragraph-properties fo:text-align="right" />
+45 -53
View File
@@ -43,8 +43,7 @@ XML_NS = [
def xmlToText(xElem):
"""Get the text content of an XML element.
"""
"""Get the text content of an XML element."""
rTxt = ET.tostring(xElem, encoding="utf-8", xml_declaration=False).decode()
for nSpace in XML_NS:
rTxt = rTxt.replace(nSpace, "")
@@ -53,8 +52,7 @@ def xmlToText(xElem):
@pytest.mark.core
def testCoreToOdt_Init(mockGUI):
"""Test initialisation of the ODT document.
"""
"""Test initialisation of the ODT document."""
theProject = NWProject(mockGUI)
# Flat Doc
@@ -109,8 +107,7 @@ def testCoreToOdt_Init(mockGUI):
@pytest.mark.core
def testCoreToOdt_TextFormatting(mockGUI):
"""Test formatting of paragraphs.
"""
"""Test formatting of paragraphs."""
theProject = NWProject(mockGUI)
theDoc = ToOdt(theProject, isFlat=True)
@@ -156,7 +153,7 @@ def testCoreToOdt_TextFormatting(mockGUI):
# No Format
theDoc.initDocument()
theDoc._addTextPar("Standard", oStyle, "Hello World")
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
"<office:text>"
"<text:p text:style-name=\"Standard\">Hello World</text:p>"
@@ -166,7 +163,7 @@ def testCoreToOdt_TextFormatting(mockGUI):
# Heading Level None
theDoc.initDocument()
theDoc._addTextPar("Standard", oStyle, "Hello World", isHead=True)
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
"<office:text>"
"<text:h text:style-name=\"Standard\">Hello World</text:h>"
@@ -176,7 +173,7 @@ def testCoreToOdt_TextFormatting(mockGUI):
# Heading Level 1
theDoc.initDocument()
theDoc._addTextPar("Standard", oStyle, "Hello World", isHead=True, oLevel="1")
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
"<office:text>"
"<text:h text:style-name=\"Standard\" text:outline-level=\"1\">Hello World</text:h>"
@@ -187,8 +184,8 @@ def testCoreToOdt_TextFormatting(mockGUI):
theDoc.initDocument()
theTxt = "A **few** _words_ from ~~our~~ sponsor"
theFmt = " _B b_ I i _S s_ "
theDoc._addTextPar("Standard", oStyle, theTxt, theFmt=theFmt)
assert theDoc.getErrors() == []
theDoc._addTextPar("Standard", oStyle, theTxt, tFmt=theFmt)
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
"<office:text>"
"<text:p text:style-name=\"Standard\">A <text:span text:style-name=\"T1\">few</text:span> "
@@ -201,8 +198,8 @@ def testCoreToOdt_TextFormatting(mockGUI):
theDoc.initDocument()
theTxt = "A **few** _wordsXXX"
theFmt = " _b b_ I XXX"
theDoc._addTextPar("Standard", oStyle, theTxt, theFmt=theFmt)
assert theDoc.getErrors() == ["Unknown format tag encountered"]
theDoc._addTextPar("Standard", oStyle, theTxt, tFmt=theFmt)
assert theDoc.errData == ["Unknown format tag encountered"]
assert xmlToText(theDoc._xText) == (
"<office:text>"
"<text:p text:style-name=\"Standard\">"
@@ -215,8 +212,8 @@ def testCoreToOdt_TextFormatting(mockGUI):
theDoc.initDocument()
theTxt = "Hello\n\tWorld"
theFmt = " "
theDoc._addTextPar("Standard", oStyle, theTxt, theFmt=theFmt)
assert theDoc.getErrors() == []
theDoc._addTextPar("Standard", oStyle, theTxt, tFmt=theFmt)
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
"<office:text>"
"<text:p text:style-name=\"Standard\">Hello<text:line-break /><text:tab />World</text:p>"
@@ -230,8 +227,8 @@ def testCoreToOdt_TextFormatting(mockGUI):
theDoc.initDocument()
theTxt = "Test text \\**_bold_** and more."
theFmt = " I i "
theDoc._addTextPar("Standard", oStyle, theTxt, theFmt=theFmt)
assert theDoc.getErrors() == []
theDoc._addTextPar("Standard", oStyle, theTxt, tFmt=theFmt)
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
"<office:text>"
"<text:p text:style-name=\"Standard\">Test text **<text:span text:style-name=\"T2\">"
@@ -244,8 +241,7 @@ def testCoreToOdt_TextFormatting(mockGUI):
@pytest.mark.core
def testCoreToOdt_Convert(mockGUI):
"""Test the converter of the ToOdt class.
"""
"""Test the converter of the ToOdt class."""
theProject = NWProject(mockGUI)
theDoc = ToOdt(theProject, isFlat=True)
@@ -266,7 +262,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:h text:style-name="P1" text:outline-level="1">Title</text:h>'
@@ -279,7 +275,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:h text:style-name="P2" text:outline-level="2">Chapter</text:h>'
@@ -292,7 +288,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:h text:style-name="Heading_20_3" text:outline-level="3">Scene</text:h>'
@@ -305,7 +301,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:h text:style-name="Heading_20_4" text:outline-level="4">Section</text:h>'
@@ -318,7 +314,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:p text:style-name="Title">Title</text:p>'
@@ -331,7 +327,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:h text:style-name="P2" text:outline-level="2">Prologue</text:h>'
@@ -347,7 +343,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:p text:style-name="Text_20_body">Some '
@@ -365,7 +361,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:p text:style-name="Text_20_body">Some text.<text:line-break />Next line</text:p>'
@@ -378,7 +374,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:p text:style-name="Text_20_body"><text:tab />Item 1<text:tab />Item 2</text:p>'
@@ -391,7 +387,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:p text:style-name="Text_20_body">Some <text:span text:style-name="T4">'
@@ -410,7 +406,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:h text:style-name="Heading_20_3" text:outline-level="3">Scene</text:h>'
@@ -434,7 +430,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:h text:style-name="Heading_20_3" text:outline-level="3">Scene</text:h>'
@@ -455,7 +451,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:p text:style-name="P3">* * *</text:p>'
@@ -473,7 +469,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:p text:style-name="Text_20_body" />'
@@ -500,7 +496,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:h text:style-name="Heading_20_3" text:outline-level="3">Scene</text:h>'
@@ -537,7 +533,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:h text:style-name="Heading_20_3" text:outline-level="3">Scene</text:h>'
@@ -559,7 +555,7 @@ def testCoreToOdt_Convert(mockGUI):
theDoc.initDocument()
theDoc.doConvert()
theDoc.closeDocument()
assert theDoc.getErrors() == []
assert theDoc.errData == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:h text:style-name="P2" text:outline-level="2">Chapter One</text:h>'
@@ -629,8 +625,7 @@ def testCoreToOdt_ConvertDirect(mockGUI):
@pytest.mark.core
def testCoreToOdt_SaveFlat(mockGUI, fncPath, tstPaths):
"""Test the document save functions.
"""
"""Test the document save functions."""
theProject = NWProject(mockGUI)
theProject.data.setAuthor("Jane Smith")
theProject.data.setName("Test Project")
@@ -639,8 +634,11 @@ def testCoreToOdt_SaveFlat(mockGUI, fncPath, tstPaths):
theDoc = ToOdt(theProject, isFlat=True)
theDoc._isNovel = True
assert theDoc.setLanguage(None) is False
assert theDoc.setLanguage("nb_NO") is True
theDoc._dLanguage = ""
theDoc.setLanguage(None)
assert theDoc._dLanguage == ""
theDoc.setLanguage("nb_NO")
assert theDoc._dLanguage == "nb"
theDoc.setColourHeaders(True)
theDoc._text = (
@@ -669,8 +667,7 @@ def testCoreToOdt_SaveFlat(mockGUI, fncPath, tstPaths):
@pytest.mark.core
def testCoreToOdt_SaveFull(mockGUI, fncPath, tstPaths):
"""Test the document save functions.
"""
"""Test the document save functions."""
theProject = NWProject(mockGUI)
theProject.data.setAuthor("Jane Smith")
theProject.data.setName("Test Project")
@@ -747,8 +744,7 @@ def testCoreToOdt_SaveFull(mockGUI, fncPath, tstPaths):
@pytest.mark.core
def testCoreToOdt_Format(mockGUI):
"""Test the formatters for the ToOdt class.
"""
"""Test the formatters for the ToOdt class."""
theProject = NWProject(mockGUI)
theDoc = ToOdt(theProject, isFlat=True)
@@ -761,7 +757,7 @@ def testCoreToOdt_Format(mockGUI):
"_B b_ "
)
assert theDoc._formatKeywords("") == ""
assert theDoc._formatKeywords("") == ("", "")
assert theDoc._formatKeywords("tag: Jane") == (
"**Tag:** Jane",
"_B b_ "
@@ -776,8 +772,7 @@ def testCoreToOdt_Format(mockGUI):
@pytest.mark.core
def testCoreToOdt_ODTParagraphStyle():
"""Test the ODTParagraphStyle class.
"""
"""Test the ODTParagraphStyle class."""
parStyle = ODTParagraphStyle()
# Set Attributes
@@ -992,8 +987,7 @@ def testCoreToOdt_ODTParagraphStyle():
@pytest.mark.core
def testCoreToOdt_ODTTextStyle():
"""Test the ODTTextStyle class.
"""
"""Test the ODTTextStyle class."""
txtStyle = ODTTextStyle()
# Font Weight
@@ -1065,8 +1059,7 @@ def testCoreToOdt_ODTTextStyle():
@pytest.mark.core
def testCoreToOdt_XMLParagraph():
"""Test XML encoding of paragraph.
"""
"""Test XML encoding of paragraph."""
# Stage 1 : Text
# ==============
@@ -1257,8 +1250,7 @@ def testCoreToOdt_XMLParagraph():
@pytest.mark.core
def testCoreToOdt_MkTag():
"""Test the tag maker function.
"""
"""Test the tag maker function."""
assert _mkTag("office", "text") == "{urn:oasis:names:tc:opendocument:xmlns:office:1.0}text"
assert _mkTag("style", "text") == "{urn:oasis:names:tc:opendocument:xmlns:style:1.0}text"
assert _mkTag("blabla", "text") == "text"