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