diff --git a/novelwriter/formats/todocx.py b/novelwriter/formats/todocx.py index c60dd5b6..2f37d5cd 100644 --- a/novelwriter/formats/todocx.py +++ b/novelwriter/formats/todocx.py @@ -87,6 +87,17 @@ def _docXCol(color: QColor) -> str: return color.name(QtHexRgb).lstrip("#") +def _wText(parent: ET.Element, text: str) -> ET.Element: + """Create a text element and add the preserve flag if necessary.""" + attrib = {} + if len(text) > len(text.strip()): + attrib[_mkTag("xml", "space")] = "preserve" + return xmlSubElem(parent, _wTag("t"), text, attrib=attrib) + + +# Cached +W_VAL = _wTag("val") + # Formatting Codes X_BLD = 0x001 # Bold format X_ITA = 0x002 # Italic format @@ -145,9 +156,9 @@ class DocXParStyle(NamedTuple): nextStyle: str | None = None before: float | None = None after: float | None = None + left: float | None = None line: float | None = None indentFirst: float | None = None - hanging: float | None = None align: str | None = None default: bool = False level: int | None = None @@ -191,7 +202,7 @@ class ToDocX(Tokenizer): def setLanguage(self, language: str | None) -> None: """Set language for the document.""" if language: - self._dLanguage = language + self._dLanguage = language.replace("_", "-") return def setPageLayout( @@ -296,6 +307,7 @@ class ToDocX(Tokenizer): self._coreXml() self._appXml() self._stylesXml() + self._fontTableXml() fId = None dId = None @@ -451,32 +463,30 @@ class ToDocX(Tokenizer): if fmt & X_ITA: xmlSubElem(rPr, _wTag("i")) if fmt & X_UND: - xmlSubElem(rPr, _wTag("u"), attrib={_wTag("val"): "single"}) + xmlSubElem(rPr, _wTag("u"), attrib={W_VAL: "single"}) if fmt & X_MRK: xmlSubElem(rPr, _wTag("shd"), attrib={ - _wTag("fill"): _docXCol(self._theme.highlight), _wTag("val"): "clear", + _wTag("fill"): _docXCol(self._theme.highlight), W_VAL: "clear", }) if fmt & X_DEL: xmlSubElem(rPr, _wTag("strike")) if fmt & X_SUP: - xmlSubElem(rPr, _wTag("vertAlign"), attrib={_wTag("val"): "superscript"}) + xmlSubElem(rPr, _wTag("vertAlign"), attrib={W_VAL: "superscript"}) if fmt & X_SUB: - xmlSubElem(rPr, _wTag("vertAlign"), attrib={_wTag("val"): "subscript"}) + xmlSubElem(rPr, _wTag("vertAlign"), attrib={W_VAL: "subscript"}) if fmt & X_COL and (color := self._classes.get(fClass)): - xmlSubElem(rPr, _wTag("color"), attrib={_wTag("val"): _docXCol(color)}) + xmlSubElem(rPr, _wTag("color"), attrib={W_VAL: _docXCol(color)}) for segment in RX_TEXT.split(text): if segment == "\n": xmlSubElem(xR, _wTag("br")) elif segment == "\t": xmlSubElem(xR, _wTag("tab")) - elif len(segment) != len(segment.strip()): - xmlSubElem(xR, _wTag("t"), segment, attrib={_mkTag("xml", "space"): "preserve"}) elif segment: - xmlSubElem(xR, _wTag("t"), segment) + _wText(xR, segment) if fmt & X_HRF and fLink: - xmlSubElem(rPr, _wTag("rStyle"), attrib={_wTag("val"): "InternetLink"}) + xmlSubElem(rPr, _wTag("rStyle"), attrib={W_VAL: "InternetLink"}) rId = self._appendExternalRel(fLink) xH = ET.Element(_wTag("hyperlink"), attrib={_mkTag("r", "id"): rId}) xH.append(xR) @@ -492,12 +502,12 @@ class ToDocX(Tokenizer): """Generate a footnote XML object.""" if key in self._footnotes: idx = len(self._usedNotes) + 1 - run = ET.Element(_wTag("r")) - rPr = xmlSubElem(run, _wTag("rPr")) - xmlSubElem(rPr, _wTag("vertAlign"), attrib={_wTag("val"): "superscript"}) - xmlSubElem(run, _wTag("footnoteReference"), attrib={_wTag("id"): str(idx)}) + xR = ET.Element(_wTag("r")) + rPr = xmlSubElem(xR, _wTag("rPr")) + xmlSubElem(rPr, _wTag("vertAlign"), attrib={W_VAL: "superscript"}) + xmlSubElem(xR, _wTag("footnoteReference"), attrib={_wTag("id"): str(idx)}) self._usedNotes[key] = idx - return run + return xR return None def _generateStyles(self) -> None: @@ -643,8 +653,8 @@ class ToDocX(Tokenizer): basedOn=S_NORM, before=0.0, after=fnSz * self._marginFoot[1], + left=fnSz * self._marginFoot[0], line=fnSz * self._lineHeight, - hanging=fnSz * self._marginFoot[0], )) # Add to Cache @@ -701,7 +711,7 @@ class ToDocX(Tokenizer): def _coreXml(self) -> str: """Populate app.xml.""" rId = self._nextRelId() - xRoot = ET.Element("coreProperties") + xRoot = ET.Element(_mkTag("cp", "coreProperties")) self._rels["core.xml"] = DocXXmlRel( rId=rId, relType=f"{OOXML_SCM}/package/2006/relationships/metadata/core-properties", @@ -718,7 +728,6 @@ class ToDocX(Tokenizer): xmlSubElem(xRoot, _mkTag("dcterms", "modified"), timeStamp, attrib=tsAttr) xmlSubElem(xRoot, _mkTag("dc", "creator"), self._project.data.author) xmlSubElem(xRoot, _mkTag("dc", "title"), self._project.data.name) - xmlSubElem(xRoot, _mkTag("dc", "creator"), self._project.data.author) xmlSubElem(xRoot, _mkTag("dc", "language"), self._dLanguage) xmlSubElem(xRoot, _mkTag("cp", "revision"), str(self._project.data.saveCount)) xmlSubElem(xRoot, _mkTag("cp", "lastModifiedBy"), self._project.data.author) @@ -754,9 +763,9 @@ class ToDocX(Tokenizer): _wTag("hAnsi"): self._fontFamily, _wTag("cs"): self._fontFamily, }) - xmlSubElem(xRPr, _wTag("sz"), attrib={_wTag("val"): size}) - xmlSubElem(xRPr, _wTag("szCs"), attrib={_wTag("val"): size}) - xmlSubElem(xRPr, _wTag("lang"), attrib={_wTag("val"): self._dLanguage}) + xmlSubElem(xRPr, _wTag("sz"), attrib={W_VAL: size}) + xmlSubElem(xRPr, _wTag("szCs"), attrib={W_VAL: size}) + xmlSubElem(xRPr, _wTag("lang"), attrib={W_VAL: self._dLanguage}) xmlSubElem(xPPr, _wTag("spacing"), attrib={_wTag("line"): line}) # Paragraph Styles @@ -770,11 +779,11 @@ class ToDocX(Tokenizer): size = firstFloat(style.size, self._fontSize) xStyl = xmlSubElem(xRoot, _wTag("style"), attrib=sAttr) - xmlSubElem(xStyl, _wTag("name"), attrib={_wTag("val"): style.name}) + xmlSubElem(xStyl, _wTag("name"), attrib={W_VAL: style.name}) if style.basedOn: - xmlSubElem(xStyl, _wTag("basedOn"), attrib={_wTag("val"): style.basedOn}) + xmlSubElem(xStyl, _wTag("basedOn"), attrib={W_VAL: style.basedOn}) if style.nextStyle: - xmlSubElem(xStyl, _wTag("next"), attrib={_wTag("val"): style.nextStyle}) + xmlSubElem(xStyl, _wTag("next"), attrib={W_VAL: style.nextStyle}) # pPr Node pPr = xmlSubElem(xStyl, _wTag("pPr")) @@ -783,34 +792,33 @@ class ToDocX(Tokenizer): _wTag("after"): str(int(20.0 * firstFloat(style.after))), _wTag("line"): str(int(20.0 * firstFloat(style.line, size))), }) - if style.hanging is not None: + if style.left is not None: xmlSubElem(pPr, _wTag("ind"), attrib={ - _wTag("left"): str(int(20.0 * style.hanging)), - _wTag("hanging"): str(int(20.0 * style.hanging)), + _wTag("left"): str(int(20.0 * style.left)), }) if style.align: - xmlSubElem(pPr, _wTag("jc"), attrib={_wTag("val"): style.align}) + xmlSubElem(pPr, _wTag("jc"), attrib={W_VAL: style.align}) if style.level is not None: - xmlSubElem(pPr, _wTag("outlineLvl"), attrib={_wTag("val"): str(style.level)}) + xmlSubElem(pPr, _wTag("outlineLvl"), attrib={W_VAL: str(style.level)}) # rPr Node rPr = xmlSubElem(xStyl, _wTag("rPr")) if style.bold: xmlSubElem(rPr, _wTag("b")) if style.color: - xmlSubElem(rPr, _wTag("color"), attrib={_wTag("val"): style.color}) - xmlSubElem(rPr, _wTag("sz"), attrib={_wTag("val"): str(int(2.0 * size))}) - xmlSubElem(rPr, _wTag("szCs"), attrib={_wTag("val"): str(int(2.0 * size))}) + xmlSubElem(rPr, _wTag("color"), attrib={W_VAL: style.color}) + xmlSubElem(rPr, _wTag("sz"), attrib={W_VAL: str(int(2.0 * size))}) + xmlSubElem(rPr, _wTag("szCs"), attrib={W_VAL: str(int(2.0 * size))}) # Character Style xStyl = xmlSubElem(xRoot, _wTag("style"), attrib={ _wTag("type"): "character", _wTag("styleId"): "InternetLink" }) - xmlSubElem(xStyl, _wTag("name"), attrib={_wTag("val"): "Hyperlink"}) + xmlSubElem(xStyl, _wTag("name"), attrib={W_VAL: "Hyperlink"}) rPr = xmlSubElem(xStyl, _wTag("rPr")) - xmlSubElem(rPr, _wTag("color"), attrib={_wTag("val"): _docXCol(self._theme.link)}) - xmlSubElem(rPr, _wTag("u"), attrib={_wTag("val"): "single"}) + xmlSubElem(rPr, _wTag("color"), attrib={W_VAL: _docXCol(self._theme.link)}) + xmlSubElem(rPr, _wTag("u"), attrib={W_VAL: "single"}) return rId @@ -830,8 +838,8 @@ class ToDocX(Tokenizer): xP = xmlSubElem(xRoot, _wTag("p")) xPPr = xmlSubElem(xP, _wTag("pPr")) - xmlSubElem(xPPr, _wTag("pStyle"), attrib={_wTag("val"): S_HEAD}) - xmlSubElem(xPPr, _wTag("jc"), attrib={_wTag("val"): "right"}) + xmlSubElem(xPPr, _wTag("pStyle"), attrib={W_VAL: S_HEAD}) + xmlSubElem(xPPr, _wTag("jc"), attrib={W_VAL: "right"}) xmlSubElem(xPPr, _wTag("rPr")) pre, page, post = self._headerFormat.partition(nwHeadFmt.DOC_PAGE) @@ -840,25 +848,24 @@ class ToDocX(Tokenizer): post = post.replace(nwHeadFmt.DOC_PROJECT, self._project.data.name) post = post.replace(nwHeadFmt.DOC_AUTHOR, self._project.data.author) - xSpace = _mkTag("xml", "space") wFldCT = _wTag("fldCharType") - - parts: list[tuple[str, str | None, str, str]] = [] if pre: - parts.append(("t", pre, xSpace, "preserve")) - if page: - parts.append(("fldChar", None, wFldCT, "begin")) - parts.append(("t", " PAGE ", xSpace, "preserve")) - parts.append(("fldChar", None, wFldCT, "separate")) - parts.append(("t", "2", xSpace, "preserve")) - parts.append(("fldChar", None, wFldCT, "end")) - if post: - parts.append(("t", post, xSpace, "preserve")) - - for part in parts: xR = xmlSubElem(xP, _wTag("r")) - xmlSubElem(xR, _wTag("rPr")) - xmlSubElem(xR, _wTag(part[0]), part[1], attrib={part[2]: part[3]}) + _wText(xR, pre) + if page: + xR = xmlSubElem(xP, _wTag("r")) + xmlSubElem(xR, _wTag("fldChar"), attrib={wFldCT: "begin"}) + xR = xmlSubElem(xP, _wTag("r")) + _wText(xR, " PAGE ") + xR = xmlSubElem(xP, _wTag("r")) + xmlSubElem(xR, _wTag("fldChar"), attrib={wFldCT: "separate"}) + xR = xmlSubElem(xP, _wTag("r")) + _wText(xR, "0") + xR = xmlSubElem(xP, _wTag("r")) + xmlSubElem(xR, _wTag("fldChar"), attrib={wFldCT: "end"}) + if post: + xR = xmlSubElem(xP, _wTag("r")) + _wText(xR, post) return rId @@ -878,8 +885,8 @@ class ToDocX(Tokenizer): xP = xmlSubElem(xRoot, _wTag("p")) xPPr = xmlSubElem(xP, _wTag("pPr")) - xmlSubElem(xPPr, _wTag("pStyle"), attrib={_wTag("val"): S_HEAD}) - xmlSubElem(xPPr, _wTag("jc"), attrib={_wTag("val"): "right"}) + xmlSubElem(xPPr, _wTag("pStyle"), attrib={W_VAL: S_HEAD}) + xmlSubElem(xPPr, _wTag("jc"), attrib={W_VAL: "right"}) xmlSubElem(xPPr, _wTag("rPr")) xR = xmlSubElem(xP, _wTag("r")) @@ -891,6 +898,7 @@ class ToDocX(Tokenizer): """Populate document.xml.""" rId = self._nextRelId() xRoot = ET.Element(_wTag("document")) + xRoot.set("xmlns:w14", "http://schemas.microsoft.com/office/word/2010/wordml") xBody = xmlSubElem(xRoot, _wTag("body")) self._rels["document.xml"] = DocXXmlRel( rId=rId, @@ -931,7 +939,7 @@ class ToDocX(Tokenizer): xFn = xmlSubElem(xSect, _wTag("footnotePr")) xmlSubElem(xFn, _wTag("numFmt"), attrib={ - _wTag("val"): "decimal", + W_VAL: "decimal", }) xmlSubElem(xSect, _wTag("pgSz"), attrib={ @@ -972,12 +980,36 @@ class ToDocX(Tokenizer): for key, idx in self._usedNotes.items(): par = DocXParagraph() + par.setIsFootnote(True) if content := self._footnotes.get(key): self._processFragments(par, S_FNOTE, content[0], content[1]) par.toXml(xmlSubElem(xRoot, _wTag("footnote"), attrib={_wTag("id"): str(idx)})) return rId + def _fontTableXml(self) -> str: + """Populate fontTable.xml.""" + rId = self._nextRelId() + xRoot = ET.Element(_wTag("fonts")) + self._rels["fontTable.xml"] = DocXXmlRel( + rId=rId, + relType=f"{RELS_BASE}/fontTable", + ) + self._files["fontTable.xml"] = DocXXmlFile( + xml=xRoot, + path="word", + contentType=f"{WORD_BASE}.fontTable+xml", + ) + + xFont = xmlSubElem(xRoot, _wTag("font"), attrib={ + _wTag("name"): self._textFont.family(), + }) + xmlSubElem(xFont, _wTag("pitch"), attrib={ + W_VAL: "fixed" if self._textFont.fixedPitch() else "variable", + }) + + return rId + def _settingsXml(self) -> str: """Populate settings.xml.""" rId = self._nextRelId() @@ -992,15 +1024,22 @@ class ToDocX(Tokenizer): contentType=f"{WORD_BASE}.settings+xml", ) - xFn = xmlSubElem(xRoot, _wTag("footnotePr")) - xmlSubElem(xFn, _wTag("numFmt"), attrib={_wTag("val"): "decimal"}) + xSet = xmlSubElem(xRoot, _wTag("footnotePr")) + xmlSubElem(xSet, _wTag("numFmt"), attrib={W_VAL: "decimal"}) + + xSet = xmlSubElem(xRoot, _wTag("compat")) + xmlSubElem(xSet, _wTag("compatSetting"), attrib={ + _wTag("name"): "compatibilityMode", + _wTag("uri"): "http://schemas.microsoft.com/office/word", + W_VAL: "12", + }) if self._counts: xVars = xmlSubElem(xRoot, _wTag("docVars")) for key, value in self._counts.items(): xmlSubElem(xVars, _wTag("docVar"), attrib={ _wTag("name"): f"Manuscript{key[:1].upper()}{key[1:]}", - _wTag("val"): str(value), + W_VAL: str(value), }) return rId @@ -1011,7 +1050,7 @@ class DocXParagraph: __slots__ = ( "_content", "_style", "_textAlign", "_topMargin", "_bottomMargin", "_leftMargin", "_rightMargin", - "_indentFirst", "_breakBefore", "_breakAfter", + "_indentFirst", "_breakBefore", "_breakAfter", "_footnoteRef", ) def __init__(self) -> None: @@ -1025,6 +1064,7 @@ class DocXParagraph: self._indentFirst = False self._breakBefore = False self._breakAfter = False + self._footnoteRef = False return ## @@ -1086,6 +1126,11 @@ class DocXParagraph: self._breakAfter = state return + def setIsFootnote(self, state: bool) -> None: + """Set is footnote flag.""" + self._footnoteRef = state + return + ## # Methods ## @@ -1098,7 +1143,7 @@ class DocXParagraph: def toXml(self, body: ET.Element) -> None: """Called after all content is set.""" if style := self._style: - par = xmlSubElem(body, _wTag("p")) + xP = xmlSubElem(body, _wTag("p")) # Values indent = {} @@ -1110,8 +1155,8 @@ class DocXParagraph: indent[_wTag("right")] = str(int(20.0 * self._rightMargin)) # Paragraph - pPr = xmlSubElem(par, _wTag("pPr")) - xmlSubElem(pPr, _wTag("pStyle"), attrib={_wTag("val"): style.styleId}) + pPr = xmlSubElem(xP, _wTag("pPr")) + xmlSubElem(pPr, _wTag("pStyle"), attrib={W_VAL: style.styleId}) if self._topMargin is not None or self._bottomMargin is not None: xmlSubElem(pPr, _wTag("spacing"), attrib={ _wTag("before"): str(int(20.0 * firstFloat(self._topMargin, style.before))), @@ -1121,16 +1166,21 @@ class DocXParagraph: if indent: xmlSubElem(pPr, _wTag("ind"), attrib=indent) if self._textAlign: - xmlSubElem(pPr, _wTag("jc"), attrib={_wTag("val"): self._textAlign}) + xmlSubElem(pPr, _wTag("jc"), attrib={W_VAL: self._textAlign}) # Text + if self._footnoteRef: + xR = xmlSubElem(xP, _wTag("r")) + rPr = xmlSubElem(xR, _wTag("rPr")) + xmlSubElem(rPr, _wTag("vertAlign"), attrib={W_VAL: "superscript"}) + xmlSubElem(xR, _wTag("footnoteRef")) if self._breakBefore: - wr = xmlSubElem(par, _wTag("r")) - xmlSubElem(wr, _wTag("br"), attrib={_wTag("type"): "page"}) - for run in self._content: - par.append(run) + xR = xmlSubElem(xP, _wTag("r")) + xmlSubElem(xR, _wTag("br"), attrib={_wTag("type"): "page"}) + for xR in self._content: + xP.append(xR) if self._breakAfter: - wr = xmlSubElem(par, _wTag("r")) - xmlSubElem(wr, _wTag("br"), attrib={_wTag("type"): "page"}) + xR = xmlSubElem(xP, _wTag("r")) + xmlSubElem(xR, _wTag("br"), attrib={_wTag("type"): "page"}) return diff --git a/sample/content/636b6aa9b697b.nwd b/sample/content/636b6aa9b697b.nwd index ec7fca24..aa2a13ce 100644 --- a/sample/content/636b6aa9b697b.nwd +++ b/sample/content/636b6aa9b697b.nwd @@ -1,14 +1,14 @@ %%~name: Making a Scene %%~path: 6a2d6d5f4f401/636b6aa9b697b %%~kind: NOVEL/DOCUMENT -%%~hash: 89d562ae05727028d74bd10cfd6953882d1cd140 -%%~date: Unknown/2024-10-25 12:41:02 +%%~hash: 8d245fa740926779d19741ff7f75ef387b55130c +%%~date: Unknown/2024-10-25 23:54:52 ### Making a Scene @pov: Jane @char: John, Jane @location: Earth -@mention: Bob, Space +@mention: Space A scene is defined by a level three heading, like the one at the top of this page. The scene will be assigned to the chapter preceding it in the project tree. The scene document can be sorted after the chapter document, or as a child of the chapter. Both result in the same output in the end, so it is a matter of preference. diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx index decdea2f..b8252bfc 100644 --- a/sample/nwProject.nwx +++ b/sample/nwProject.nwx @@ -1,6 +1,6 @@ - - + + Sample Project Jane Smith @@ -58,7 +58,7 @@ Chapter One - + Making a Scene diff --git a/tests/reference/fmtToDocX_SaveDocument_Content_Types.xml b/tests/reference/fmtToDocX_SaveDocument_Content_Types.xml index 2d38ec4c..f78c331c 100644 --- a/tests/reference/fmtToDocX_SaveDocument_Content_Types.xml +++ b/tests/reference/fmtToDocX_SaveDocument_Content_Types.xml @@ -7,6 +7,7 @@ + diff --git a/tests/reference/fmtToDocX_SaveDocument_core.xml b/tests/reference/fmtToDocX_SaveDocument_core.xml index 54d5a6dd..298cdff1 100644 --- a/tests/reference/fmtToDocX_SaveDocument_core.xml +++ b/tests/reference/fmtToDocX_SaveDocument_core.xml @@ -1,11 +1,10 @@ - - 2024-10-25T19:23:34 - 2024-10-25T19:23:34 + + 2024-10-26T17:01:14 + 2024-10-26T17:01:14 lipsum.com Lorem Ipsum - lipsum.com - en_GB + en-GB 48 lipsum.com - + diff --git a/tests/reference/fmtToDocX_SaveDocument_document.xml b/tests/reference/fmtToDocX_SaveDocument_document.xml index 1ee76b16..a464186f 100644 --- a/tests/reference/fmtToDocX_SaveDocument_document.xml +++ b/tests/reference/fmtToDocX_SaveDocument_document.xml @@ -1398,8 +1398,8 @@ - - + + diff --git a/tests/reference/fmtToDocX_SaveDocument_document.xml.rels b/tests/reference/fmtToDocX_SaveDocument_document.xml.rels index 53d161f0..a0a8d388 100644 --- a/tests/reference/fmtToDocX_SaveDocument_document.xml.rels +++ b/tests/reference/fmtToDocX_SaveDocument_document.xml.rels @@ -2,8 +2,9 @@ - - - - + + + + + diff --git a/tests/reference/fmtToDocX_SaveDocument_fontTable.xml b/tests/reference/fmtToDocX_SaveDocument_fontTable.xml new file mode 100644 index 00000000..620d21c9 --- /dev/null +++ b/tests/reference/fmtToDocX_SaveDocument_fontTable.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/reference/fmtToDocX_SaveDocument_footnotes.xml b/tests/reference/fmtToDocX_SaveDocument_footnotes.xml index 7203ae35..12edd5df 100644 --- a/tests/reference/fmtToDocX_SaveDocument_footnotes.xml +++ b/tests/reference/fmtToDocX_SaveDocument_footnotes.xml @@ -5,6 +5,12 @@ + + + + + + diff --git a/tests/reference/fmtToDocX_SaveDocument_header1.xml b/tests/reference/fmtToDocX_SaveDocument_header1.xml index 929f2610..1135d853 100644 --- a/tests/reference/fmtToDocX_SaveDocument_header1.xml +++ b/tests/reference/fmtToDocX_SaveDocument_header1.xml @@ -7,31 +7,24 @@ - Page - - PAGE - - - 2 + 0 - - - Lorem Ipsum (lipsum.com) diff --git a/tests/reference/fmtToDocX_SaveDocument_rels b/tests/reference/fmtToDocX_SaveDocument_rels index 329b610c..1bad7949 100644 --- a/tests/reference/fmtToDocX_SaveDocument_rels +++ b/tests/reference/fmtToDocX_SaveDocument_rels @@ -2,5 +2,5 @@ - + diff --git a/tests/reference/fmtToDocX_SaveDocument_settings.xml b/tests/reference/fmtToDocX_SaveDocument_settings.xml index 139f62a2..3d8dd1db 100644 --- a/tests/reference/fmtToDocX_SaveDocument_settings.xml +++ b/tests/reference/fmtToDocX_SaveDocument_settings.xml @@ -3,6 +3,9 @@ + + + diff --git a/tests/reference/fmtToDocX_SaveDocument_styles.xml b/tests/reference/fmtToDocX_SaveDocument_styles.xml index 9033096d..e2a654e1 100644 --- a/tests/reference/fmtToDocX_SaveDocument_styles.xml +++ b/tests/reference/fmtToDocX_SaveDocument_styles.xml @@ -6,7 +6,7 @@ - + @@ -142,7 +142,7 @@ - + diff --git a/tests/test_formats/test_fmt_todocx.py b/tests/test_formats/test_fmt_todocx.py index d395eaee..26567dde 100644 --- a/tests/test_formats/test_fmt_todocx.py +++ b/tests/test_formats/test_fmt_todocx.py @@ -556,10 +556,13 @@ def testFmtToDocX_Footnotes(mockGUI): assert xmlToText(doc._files["footnotes.xml"].xml) == ( '' '' + '' 'Footnote text A.' '' + '' 'Another footnote.' '' + '' 'Again?' '' ) @@ -619,6 +622,7 @@ def testFmtToDocX_SaveDocument(mockGUI, prjLipsum, fncPath, tstPaths): fncPath / "extract" / "word" / "header2.xml", fncPath / "extract" / "word" / "settings.xml", fncPath / "extract" / "word" / "styles.xml", + fncPath / "extract" / "word" / "fontTable.xml", ] outDir = tstPaths.outDir / "fmtToDocX_SaveDocument"