Add font table, fix core.xml bug, clean up code, update tests, for DocX

This commit is contained in:
Veronica Berglyd Olsen
2024-10-26 17:09:50 +02:00
parent 6c217c2450
commit ceabc666c3
14 changed files with 163 additions and 100 deletions
+121 -71
View File
@@ -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
+3 -3
View File
@@ -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.
+3 -3
View File
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.6a2" hexVersion="0x020600a2" fileVersion="1.5" fileRevision="4" timeStamp="2024-10-25 23:19:07">
<project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="2122" autoCount="279" editTime="94855">
<novelWriterXML appVersion="2.6a2" hexVersion="0x020600a2" fileVersion="1.5" fileRevision="4" timeStamp="2024-10-26 16:59:09">
<project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="2132" autoCount="279" editTime="95062">
<name>Sample Project</name>
<author>Jane Smith</author>
</project>
@@ -58,7 +58,7 @@
<name status="sf24ce6" import="ia857f0" active="yes">Chapter One</name>
</item>
<item handle="636b6aa9b697b" parent="6a2d6d5f4f401" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H3" charCount="2999" wordCount="530" paraCount="16" cursorPos="1663" />
<meta expanded="no" heading="H3" charCount="2999" wordCount="530" paraCount="16" cursorPos="357" />
<name status="s90e6c9" import="ia857f0" active="yes">Making a Scene</name>
</item>
<item handle="bc0cbd2a407f3" parent="6a2d6d5f4f401" root="7031beac91f75" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
@@ -7,6 +7,7 @@
<ns0:Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml" />
<ns0:Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml" />
<ns0:Override PartName="/word/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" />
<ns0:Override PartName="/word/fontTable.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" />
<ns0:Override PartName="/word/header1.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml" />
<ns0:Override PartName="/word/header2.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml" />
<ns0:Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" />
@@ -1,11 +1,10 @@
<?xml version='1.0' encoding='utf-8'?>
<coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dcterms:created xsi:type="dcterms:W3CDTF">2024-10-25T19:23:34</dcterms:created>
<dcterms:modified xsi:type="dcterms:W3CDTF">2024-10-25T19:23:34</dcterms:modified>
<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dcterms:created xsi:type="dcterms:W3CDTF">2024-10-26T17:01:14</dcterms:created>
<dcterms:modified xsi:type="dcterms:W3CDTF">2024-10-26T17:01:14</dcterms:modified>
<dc:creator>lipsum.com</dc:creator>
<dc:title>Lorem Ipsum</dc:title>
<dc:creator>lipsum.com</dc:creator>
<dc:language>en_GB</dc:language>
<dc:language>en-GB</dc:language>
<cp:revision>48</cp:revision>
<cp:lastModifiedBy>lipsum.com</cp:lastModifiedBy>
</coreProperties>
</cp:coreProperties>
@@ -1398,8 +1398,8 @@
</w:r>
</w:p>
<w:sectPr>
<w:headerReference w:type="first" r:id="rId6" />
<w:headerReference w:type="default" r:id="rId5" />
<w:headerReference w:type="first" r:id="rId7" />
<w:headerReference w:type="default" r:id="rId6" />
<w:footnotePr>
<w:numFmt w:val="decimal" />
</w:footnotePr>
@@ -2,8 +2,9 @@
<ns0:Relationships xmlns:ns0="http://schemas.openxmlformats.org/package/2006/relationships">
<ns0:Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Target="http://lipsum.com" TargetMode="External" />
<ns0:Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml" />
<ns0:Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/header" Target="header1.xml" />
<ns0:Relationship Id="rId6" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/header" Target="header2.xml" />
<ns0:Relationship Id="rId8" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Target="settings.xml" />
<ns0:Relationship Id="rId9" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes" Target="footnotes.xml" />
<ns0:Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" Target="fontTable.xml" />
<ns0:Relationship Id="rId6" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/header" Target="header1.xml" />
<ns0:Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/header" Target="header2.xml" />
<ns0:Relationship Id="rId9" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Target="settings.xml" />
<ns0:Relationship Id="rId10" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes" Target="footnotes.xml" />
</ns0:Relationships>
@@ -0,0 +1,6 @@
<?xml version='1.0' encoding='utf-8'?>
<w:fonts xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:font w:name="Source Sans Pro">
<w:pitch w:val="variable" />
</w:font>
</w:fonts>
@@ -5,6 +5,12 @@
<w:pPr>
<w:pStyle w:val="FootnoteText" />
</w:pPr>
<w:r>
<w:rPr>
<w:vertAlign w:val="superscript" />
</w:rPr>
<w:footnoteRef />
</w:r>
<w:r>
<w:rPr>
<w:i />
@@ -7,31 +7,24 @@
<w:rPr />
</w:pPr>
<w:r>
<w:rPr />
<w:t xml:space="preserve">Page </w:t>
</w:r>
<w:r>
<w:rPr />
<w:fldChar w:fldCharType="begin" />
</w:r>
<w:r>
<w:rPr />
<w:t xml:space="preserve"> PAGE </w:t>
</w:r>
<w:r>
<w:rPr />
<w:fldChar w:fldCharType="separate" />
</w:r>
<w:r>
<w:rPr />
<w:t xml:space="preserve">2</w:t>
<w:t>0</w:t>
</w:r>
<w:r>
<w:rPr />
<w:fldChar w:fldCharType="end" />
</w:r>
<w:r>
<w:rPr />
<w:t xml:space="preserve"> - Lorem Ipsum (lipsum.com)</w:t>
</w:r>
</w:p>
+1 -1
View File
@@ -2,5 +2,5 @@
<ns0:Relationships xmlns:ns0="http://schemas.openxmlformats.org/package/2006/relationships">
<ns0:Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml" />
<ns0:Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml" />
<ns0:Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml" />
<ns0:Relationship Id="rId8" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml" />
</ns0:Relationships>
@@ -3,6 +3,9 @@
<w:footnotePr>
<w:numFmt w:val="decimal" />
</w:footnotePr>
<w:compat>
<w:compatSetting w:name="compatibilityMode" w:uri="http://schemas.microsoft.com/office/word" w:val="12" />
</w:compat>
<w:docVars>
<w:docVar w:name="ManuscriptTitleCount" w:val="11" />
<w:docVar w:name="ManuscriptParagraphCount" w:val="43" />
@@ -6,7 +6,7 @@
<w:rFonts w:ascii="Source Sans Pro" w:hAnsi="Source Sans Pro" w:cs="Source Sans Pro" />
<w:sz w:val="24" />
<w:szCs w:val="24" />
<w:lang w:val="en_GB" />
<w:lang w:val="en-GB" />
</w:rPr>
</w:rPrDefault>
<w:pPrDefault>
@@ -142,7 +142,7 @@
<w:basedOn w:val="Normal" />
<w:pPr>
<w:spacing w:before="0" w:after="90" w:line="220" />
<w:ind w:left="272" w:hanging="272" />
<w:ind w:left="272" />
</w:pPr>
<w:rPr>
<w:sz w:val="19" />
+4
View File
@@ -556,10 +556,13 @@ def testFmtToDocX_Footnotes(mockGUI):
assert xmlToText(doc._files["footnotes.xml"].xml) == (
'<w:footnotes>'
'<w:footnote w:id="1"><w:p><w:pPr><w:pStyle w:val="FootnoteText" /></w:pPr>'
'<w:r><w:rPr><w:vertAlign w:val="superscript" /></w:rPr><w:footnoteRef /></w:r>'
'<w:r><w:rPr /><w:t>Footnote text A.</w:t></w:r></w:p></w:footnote>'
'<w:footnote w:id="2"><w:p><w:pPr><w:pStyle w:val="FootnoteText" /></w:pPr>'
'<w:r><w:rPr><w:vertAlign w:val="superscript" /></w:rPr><w:footnoteRef /></w:r>'
'<w:r><w:rPr /><w:t>Another footnote.</w:t></w:r></w:p></w:footnote>'
'<w:footnote w:id="3"><w:p><w:pPr><w:pStyle w:val="FootnoteText" /></w:pPr>'
'<w:r><w:rPr><w:vertAlign w:val="superscript" /></w:rPr><w:footnoteRef /></w:r>'
'<w:r><w:rPr /><w:t>Again?</w:t></w:r></w:p></w:footnote>'
'</w:footnotes>'
)
@@ -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"