Add test coverage of title line breaks, and don't break markdown titles

This commit is contained in:
Veronica Berglyd Olsen
2024-10-23 21:12:25 +02:00
parent f77cd1c752
commit bfa82f6bb3
5 changed files with 185 additions and 109 deletions
+5 -5
View File
@@ -113,23 +113,23 @@ class ToMarkdown(Tokenizer):
lines.append(f"{tTemp}\n\n") lines.append(f"{tTemp}\n\n")
elif tType == BlockTyp.TITLE: elif tType == BlockTyp.TITLE:
tHead = tText.replace(nwHeadFmt.BR, "\n") tHead = tText.replace(nwHeadFmt.BR, " - ")
lines.append(f"# {tHead}\n\n") lines.append(f"# {tHead}\n\n")
elif tType == BlockTyp.HEAD1: elif tType == BlockTyp.HEAD1:
tHead = tText.replace(nwHeadFmt.BR, "\n") tHead = tText.replace(nwHeadFmt.BR, " - ")
lines.append(f"# {tHead}\n\n") lines.append(f"# {tHead}\n\n")
elif tType == BlockTyp.HEAD2: elif tType == BlockTyp.HEAD2:
tHead = tText.replace(nwHeadFmt.BR, "\n") tHead = tText.replace(nwHeadFmt.BR, " - ")
lines.append(f"## {tHead}\n\n") lines.append(f"## {tHead}\n\n")
elif tType == BlockTyp.HEAD3: elif tType == BlockTyp.HEAD3:
tHead = tText.replace(nwHeadFmt.BR, "\n") tHead = tText.replace(nwHeadFmt.BR, " - ")
lines.append(f"### {tHead}\n\n") lines.append(f"### {tHead}\n\n")
elif tType == BlockTyp.HEAD4: elif tType == BlockTyp.HEAD4:
tHead = tText.replace(nwHeadFmt.BR, "\n") tHead = tText.replace(nwHeadFmt.BR, " - ")
lines.append(f"#### {tHead}\n\n") lines.append(f"#### {tHead}\n\n")
elif tType == BlockTyp.SEP: elif tType == BlockTyp.SEP:
+145 -83
View File
@@ -32,10 +32,7 @@ from novelwriter.core.docbuild import NWBuildDocument
from novelwriter.core.project import NWProject from novelwriter.core.project import NWProject
from novelwriter.enum import nwBuildFmt from novelwriter.enum import nwBuildFmt
from novelwriter.formats.shared import BlockFmt, BlockTyp from novelwriter.formats.shared import BlockFmt, BlockTyp
from novelwriter.formats.todocx import ( from novelwriter.formats.todocx import ToDocX, _mkTag, _wTag
S_FNOTE, S_HEAD1, S_HEAD2, S_HEAD3, S_HEAD4, S_META, S_NORM, S_SEP,
S_TITLE, ToDocX, _mkTag, _wTag
)
from tests.tools import DOCX_IGNORE, cmpFiles from tests.tools import DOCX_IGNORE, cmpFiles
@@ -59,6 +56,120 @@ def xmlToText(xElem):
return rTxt return rTxt
@pytest.mark.core
def testFmtToDocX_HeadingStyles(mockGUI):
"""Test formatting of headings."""
project = NWProject()
doc = ToDocX(project)
doc._isNovel = True
doc.initDocument()
# Title
# =====
xTest = ET.Element(_wTag("body"))
doc._text = "#! Hello World"
doc.tokenizeText()
doc.doConvert()
doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == (
'<w:body><w:p><w:pPr><w:pStyle w:val="Title" /><w:jc w:val="center" /></w:pPr>'
'<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>'
)
# Heading Level 1
# ===============
doc._text = "# Hello World"
# Plain
xTest = ET.Element(_wTag("body"))
doc.tokenizeText()
doc.doConvert()
doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == (
'<w:body><w:p><w:pPr><w:pStyle w:val="Heading1" /><w:jc w:val="center" /></w:pPr>'
'<w:r><w:br w:type="page" /></w:r>'
'<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>'
)
# Formatted
xTest = ET.Element(_wTag("body"))
doc.setPartitionFormat(f"Part{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
doc.tokenizeText()
doc.doConvert()
doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == (
'<w:body><w:p><w:pPr><w:pStyle w:val="Heading1" /><w:jc w:val="center" /></w:pPr>'
'<w:r><w:br w:type="page" /></w:r>'
'<w:r><w:rPr /><w:t>Part</w:t><w:br /><w:t>Hello World</w:t></w:r></w:p></w:body>'
)
# Heading Level 2
# ===============
doc._text = "## Hello World"
# Plain
xTest = ET.Element(_wTag("body"))
doc.tokenizeText()
doc.doConvert()
doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == (
'<w:body><w:p><w:pPr><w:pStyle w:val="Heading2" /></w:pPr>'
'<w:r><w:br w:type="page" /></w:r>'
'<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>'
)
# Formatted
xTest = ET.Element(_wTag("body"))
doc.setChapterFormat(f"Chapter {nwHeadFmt.CH_NUM}{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
doc.tokenizeText()
doc.doConvert()
doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == (
'<w:body><w:p><w:pPr><w:pStyle w:val="Heading2" /></w:pPr>'
'<w:r><w:br w:type="page" /></w:r>'
'<w:r><w:rPr /><w:t>Chapter 2</w:t><w:br /><w:t>Hello World</w:t></w:r></w:p></w:body>'
)
# Heading Level 3
# ===============
doc._text = "### Hello World"
# Plain
xTest = ET.Element(_wTag("body"))
doc.tokenizeText()
doc.doConvert()
doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == (
'<w:body><w:p><w:pPr><w:pStyle w:val="Heading3" /></w:pPr><w:r><w:rPr />'
'<w:t>Hello World</w:t></w:r></w:p></w:body>'
)
# Formatted
xTest = ET.Element(_wTag("body"))
doc.setSceneFormat(f"Scene {nwHeadFmt.SC_ABS}{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
doc.tokenizeText()
doc.doConvert()
doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == (
'<w:body><w:p><w:pPr><w:pStyle w:val="Heading3" /></w:pPr>'
'<w:r><w:rPr /><w:t>Scene 2</w:t><w:br /><w:t>Hello World</w:t></w:r></w:p></w:body>'
)
# Heading Level 4
# ===============
doc._text = "#### Hello World"
xTest = ET.Element(_wTag("body"))
doc.tokenizeText()
doc.doConvert()
doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == (
'<w:body><w:p><w:pPr><w:pStyle w:val="Heading4" /></w:pPr><w:r><w:rPr />'
'<w:t>Hello World</w:t></w:r></w:p></w:body>'
)
@pytest.mark.core @pytest.mark.core
def testFmtToDocX_ParagraphStyles(mockGUI): def testFmtToDocX_ParagraphStyles(mockGUI):
"""Test formatting of paragraphs.""" """Test formatting of paragraphs."""
@@ -71,61 +182,12 @@ def testFmtToDocX_ParagraphStyles(mockGUI):
# Normal Text # Normal Text
xTest = ET.Element(_wTag("body")) xTest = ET.Element(_wTag("body"))
doc._blocks = [(BlockTyp.TEXT, "", "Hello World", [], BlockFmt.NONE)] doc._text = "Hello World"
doc.tokenizeText()
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /></w:pPr><w:r><w:rPr />' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /></w:pPr><w:r><w:rPr />'
'<w:t>Hello World</w:t></w:r></w:p></w:body>'
)
# Title
xTest = ET.Element(_wTag("body"))
doc._blocks = [(BlockTyp.TITLE, "", "Hello World", [], BlockFmt.NONE)]
doc.doConvert()
doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_TITLE}" /></w:pPr><w:r><w:rPr />'
'<w:t>Hello World</w:t></w:r></w:p></w:body>'
)
# Heading Level 1
xTest = ET.Element(_wTag("body"))
doc._blocks = [(BlockTyp.HEAD1, "", "Hello World", [], BlockFmt.NONE)]
doc.doConvert()
doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_HEAD1}" /></w:pPr><w:r><w:rPr />'
'<w:t>Hello World</w:t></w:r></w:p></w:body>'
)
# Heading Level 2
xTest = ET.Element(_wTag("body"))
doc._blocks = [(BlockTyp.HEAD2, "", "Hello World", [], BlockFmt.NONE)]
doc.doConvert()
doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_HEAD2}" /></w:pPr><w:r><w:rPr />'
'<w:t>Hello World</w:t></w:r></w:p></w:body>'
)
# Heading Level 3
xTest = ET.Element(_wTag("body"))
doc._blocks = [(BlockTyp.HEAD3, "", "Hello World", [], BlockFmt.NONE)]
doc.doConvert()
doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_HEAD3}" /></w:pPr><w:r><w:rPr />'
'<w:t>Hello World</w:t></w:r></w:p></w:body>'
)
# Heading Level 4
xTest = ET.Element(_wTag("body"))
doc._blocks = [(BlockTyp.HEAD4, "", "Hello World", [], BlockFmt.NONE)]
doc.doConvert()
doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_HEAD4}" /></w:pPr><w:r><w:rPr />'
'<w:t>Hello World</w:t></w:r></w:p></w:body>' '<w:t>Hello World</w:t></w:r></w:p></w:body>'
) )
@@ -135,7 +197,7 @@ def testFmtToDocX_ParagraphStyles(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_SEP}" /></w:pPr><w:r><w:rPr />' '<w:body><w:p><w:pPr><w:pStyle w:val="Separator" /></w:pPr><w:r><w:rPr />'
'<w:t>* * *</w:t></w:r></w:p></w:body>' '<w:t>* * *</w:t></w:r></w:p></w:body>'
) )
@@ -145,7 +207,7 @@ def testFmtToDocX_ParagraphStyles(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /></w:pPr></w:p></w:body>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /></w:pPr></w:p></w:body>'
) )
# Synopsis # Synopsis
@@ -155,7 +217,7 @@ def testFmtToDocX_ParagraphStyles(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_META}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="MetaText" /></w:pPr>'
'<w:r><w:rPr><w:b /><w:color w:val="813709" /></w:rPr><w:t>Synopsis:</w:t></w:r>' '<w:r><w:rPr><w:b /><w:color w:val="813709" /></w:rPr><w:t>Synopsis:</w:t></w:r>'
'<w:r><w:rPr /><w:t xml:space="preserve"> </w:t></w:r>' '<w:r><w:rPr /><w:t xml:space="preserve"> </w:t></w:r>'
'<w:r><w:rPr><w:color w:val="813709" /></w:rPr><w:t>Hello World</w:t></w:r>' '<w:r><w:rPr><w:color w:val="813709" /></w:rPr><w:t>Hello World</w:t></w:r>'
@@ -169,7 +231,7 @@ def testFmtToDocX_ParagraphStyles(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_META}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="MetaText" /></w:pPr>'
'<w:r><w:rPr><w:b /><w:color w:val="813709" /></w:rPr><w:t>Short Description:</w:t></w:r>' '<w:r><w:rPr><w:b /><w:color w:val="813709" /></w:rPr><w:t>Short Description:</w:t></w:r>'
'<w:r><w:rPr /><w:t xml:space="preserve"> </w:t></w:r>' '<w:r><w:rPr /><w:t xml:space="preserve"> </w:t></w:r>'
'<w:r><w:rPr><w:color w:val="813709" /></w:rPr><w:t>Hello World</w:t></w:r>' '<w:r><w:rPr><w:color w:val="813709" /></w:rPr><w:t>Hello World</w:t></w:r>'
@@ -183,7 +245,7 @@ def testFmtToDocX_ParagraphStyles(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_META}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="MetaText" /></w:pPr>'
'<w:r><w:rPr><w:b /><w:color w:val="646464" /></w:rPr><w:t>Comment:</w:t></w:r>' '<w:r><w:rPr><w:b /><w:color w:val="646464" /></w:rPr><w:t>Comment:</w:t></w:r>'
'<w:r><w:rPr /><w:t xml:space="preserve"> </w:t></w:r>' '<w:r><w:rPr /><w:t xml:space="preserve"> </w:t></w:r>'
'<w:r><w:rPr><w:color w:val="646464" /></w:rPr><w:t>Hello World</w:t></w:r>' '<w:r><w:rPr><w:color w:val="646464" /></w:rPr><w:t>Hello World</w:t></w:r>'
@@ -197,7 +259,7 @@ def testFmtToDocX_ParagraphStyles(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_META}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="MetaText" /></w:pPr>'
'<w:r><w:rPr><w:b /><w:color w:val="f5871f" /></w:rPr><w:t>Tag:</w:t></w:r>' '<w:r><w:rPr><w:b /><w:color w:val="f5871f" /></w:rPr><w:t>Tag:</w:t></w:r>'
'<w:r><w:rPr /><w:t xml:space="preserve"> </w:t></w:r>' '<w:r><w:rPr /><w:t xml:space="preserve"> </w:t></w:r>'
'<w:r><w:rPr><w:color w:val="4271ae" /></w:rPr><w:t>Stuff</w:t></w:r>' '<w:r><w:rPr><w:color w:val="4271ae" /></w:rPr><w:t>Stuff</w:t></w:r>'
@@ -211,7 +273,7 @@ def testFmtToDocX_ParagraphStyles(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_META}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="MetaText" /></w:pPr>'
'<w:r><w:rPr><w:b /><w:color w:val="f5871f" /></w:rPr><w:t>Characters:</w:t></w:r>' '<w:r><w:rPr><w:b /><w:color w:val="f5871f" /></w:rPr><w:t>Characters:</w:t></w:r>'
'<w:r><w:rPr /><w:t xml:space="preserve"> </w:t></w:r>' '<w:r><w:rPr /><w:t xml:space="preserve"> </w:t></w:r>'
'<w:r><w:rPr><w:color w:val="4271ae" /></w:rPr><w:t>Jane</w:t></w:r>' '<w:r><w:rPr><w:color w:val="4271ae" /></w:rPr><w:t>Jane</w:t></w:r>'
@@ -245,7 +307,7 @@ def testFmtToDocX_ParagraphFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /><w:jc w:val="left" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /><w:jc w:val="left" /></w:pPr>'
'<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>' '<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>'
) )
@@ -255,7 +317,7 @@ def testFmtToDocX_ParagraphFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /><w:jc w:val="right" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /><w:jc w:val="right" /></w:pPr>'
'<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>' '<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>'
) )
@@ -265,7 +327,7 @@ def testFmtToDocX_ParagraphFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /><w:jc w:val="center" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /><w:jc w:val="center" /></w:pPr>'
'<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>' '<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>'
) )
@@ -275,7 +337,7 @@ def testFmtToDocX_ParagraphFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /><w:jc w:val="both" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /><w:jc w:val="both" /></w:pPr>'
'<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>' '<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>'
) )
@@ -285,7 +347,7 @@ def testFmtToDocX_ParagraphFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /></w:pPr>'
'<w:r><w:br w:type="page" /></w:r>' '<w:r><w:br w:type="page" /></w:r>'
'<w:r><w:rPr /><w:t>Hello World</w:t></w:r>' '<w:r><w:rPr /><w:t>Hello World</w:t></w:r>'
'</w:p></w:body>' '</w:p></w:body>'
@@ -297,7 +359,7 @@ def testFmtToDocX_ParagraphFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /></w:pPr>'
'<w:r><w:rPr /><w:t>Hello World</w:t></w:r>' '<w:r><w:rPr /><w:t>Hello World</w:t></w:r>'
'<w:r><w:br w:type="page" /></w:r>' '<w:r><w:br w:type="page" /></w:r>'
'</w:p></w:body>' '</w:p></w:body>'
@@ -309,7 +371,7 @@ def testFmtToDocX_ParagraphFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" />' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" />'
'<w:spacing w:before="0" w:after="0" w:line="252" /></w:pPr>' '<w:spacing w:before="0" w:after="0" w:line="252" /></w:pPr>'
'<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>' '<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>'
) )
@@ -320,7 +382,7 @@ def testFmtToDocX_ParagraphFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" />' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" />'
'<w:ind w:left="880" w:right="880" /></w:pPr>' '<w:ind w:left="880" w:right="880" /></w:pPr>'
'<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>' '<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>'
) )
@@ -331,7 +393,7 @@ def testFmtToDocX_ParagraphFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" />' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" />'
'<w:ind w:firstLine="308" /></w:pPr>' '<w:ind w:firstLine="308" /></w:pPr>'
'<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>' '<w:r><w:rPr /><w:t>Hello World</w:t></w:r></w:p></w:body>'
) )
@@ -351,7 +413,7 @@ def testFmtToDocX_TextFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /></w:pPr>'
'<w:r><w:rPr /><w:t xml:space="preserve">Text </w:t></w:r>' '<w:r><w:rPr /><w:t xml:space="preserve">Text </w:t></w:r>'
'<w:r><w:rPr><w:b /></w:rPr><w:t>bold</w:t></w:r>' '<w:r><w:rPr><w:b /></w:rPr><w:t>bold</w:t></w:r>'
'<w:r><w:rPr /><w:t xml:space="preserve">, </w:t></w:r>' '<w:r><w:rPr /><w:t xml:space="preserve">, </w:t></w:r>'
@@ -369,7 +431,7 @@ def testFmtToDocX_TextFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /></w:pPr>'
'<w:r><w:rPr /><w:t xml:space="preserve">Some </w:t></w:r>' '<w:r><w:rPr /><w:t xml:space="preserve">Some </w:t></w:r>'
'<w:r><w:rPr><w:strike /></w:rPr><w:t xml:space="preserve">nested </w:t></w:r>' '<w:r><w:rPr><w:strike /></w:rPr><w:t xml:space="preserve">nested </w:t></w:r>'
'<w:r><w:rPr><w:b /><w:strike /></w:rPr><w:t>bold</w:t></w:r>' '<w:r><w:rPr><w:b /><w:strike /></w:rPr><w:t>bold</w:t></w:r>'
@@ -389,7 +451,7 @@ def testFmtToDocX_TextFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /></w:pPr>'
'<w:r><w:rPr /><w:t>Some super</w:t></w:r>' '<w:r><w:rPr /><w:t>Some super</w:t></w:r>'
'<w:r><w:rPr><w:vertAlign w:val="superscript" /></w:rPr><w:t>script</w:t></w:r>' '<w:r><w:rPr><w:vertAlign w:val="superscript" /></w:rPr><w:t>script</w:t></w:r>'
'<w:r><w:rPr /><w:t xml:space="preserve"> and sub</w:t></w:r>' '<w:r><w:rPr /><w:t xml:space="preserve"> and sub</w:t></w:r>'
@@ -405,7 +467,7 @@ def testFmtToDocX_TextFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /></w:pPr>'
'<w:r><w:rPr /><w:t xml:space="preserve">Some </w:t></w:r>' '<w:r><w:rPr /><w:t xml:space="preserve">Some </w:t></w:r>'
'<w:r><w:rPr><w:u w:val="single" /></w:rPr>' '<w:r><w:rPr><w:u w:val="single" /></w:rPr>'
'<w:t xml:space="preserve">underlined and </w:t></w:r>' '<w:t xml:space="preserve">underlined and </w:t></w:r>'
@@ -422,7 +484,7 @@ def testFmtToDocX_TextFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /></w:pPr>'
'<w:r><w:rPr /><w:t>Some text.</w:t><w:br /><w:t>Next line</w:t></w:r>' '<w:r><w:rPr /><w:t>Some text.</w:t><w:br /><w:t>Next line</w:t></w:r>'
'</w:p></w:body>' '</w:p></w:body>'
) )
@@ -434,7 +496,7 @@ def testFmtToDocX_TextFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /></w:pPr>'
'<w:r><w:rPr /><w:tab /><w:t>Item 1</w:t><w:tab /><w:t>Item 2</w:t></w:r>' '<w:r><w:rPr /><w:tab /><w:t>Item 1</w:t><w:tab /><w:t>Item 2</w:t></w:r>'
'</w:p></w:body>' '</w:p></w:body>'
) )
@@ -446,7 +508,7 @@ def testFmtToDocX_TextFormatting(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /></w:pPr>'
'<w:r><w:rPr /><w:t xml:space="preserve">Some </w:t></w:r>' '<w:r><w:rPr /><w:t xml:space="preserve">Some </w:t></w:r>'
'<w:r><w:rPr><w:b /></w:rPr><w:t>bold</w:t><w:tab /><w:t>text</w:t></w:r>' '<w:r><w:rPr><w:b /></w:rPr><w:t>bold</w:t><w:tab /><w:t>text</w:t></w:r>'
'</w:p></w:body>' '</w:p></w:body>'
@@ -474,7 +536,7 @@ def testFmtToDocX_Footnotes(mockGUI):
doc.doConvert() doc.doConvert()
doc._pars[-1].toXml(xTest) doc._pars[-1].toXml(xTest)
assert xmlToText(xTest) == ( assert xmlToText(xTest) == (
f'<w:body><w:p><w:pPr><w:pStyle w:val="{S_NORM}" /></w:pPr>' '<w:body><w:p><w:pPr><w:pStyle w:val="Normal" /></w:pPr>'
'<w:r><w:rPr /><w:t>Text with one</w:t></w:r>' '<w:r><w:rPr /><w:t>Text with one</w:t></w:r>'
'<w:r><w:rPr><w:vertAlign w:val="superscript" /></w:rPr>' '<w:r><w:rPr><w:vertAlign w:val="superscript" /></w:rPr>'
'<w:footnoteReference w:id="1" /></w:r>' '<w:footnoteReference w:id="1" /></w:r>'
@@ -493,11 +555,11 @@ def testFmtToDocX_Footnotes(mockGUI):
doc._footnotesXml() doc._footnotesXml()
assert xmlToText(doc._files["footnotes.xml"].xml) == ( assert xmlToText(doc._files["footnotes.xml"].xml) == (
'<w:footnotes>' '<w:footnotes>'
f'<w:footnote w:id="1"><w:p><w:pPr><w:pStyle w:val="{S_FNOTE}" /></w:pPr>' '<w:footnote w:id="1"><w:p><w:pPr><w:pStyle w:val="FootnoteText" /></w:pPr>'
'<w:r><w:rPr /><w:t>Footnote text A.</w:t></w:r></w:p></w:footnote>' '<w:r><w:rPr /><w:t>Footnote text A.</w:t></w:r></w:p></w:footnote>'
f'<w:footnote w:id="2"><w:p><w:pPr><w:pStyle w:val="{S_FNOTE}" /></w:pPr>' '<w:footnote w:id="2"><w:p><w:pPr><w:pStyle w:val="FootnoteText" /></w:pPr>'
'<w:r><w:rPr /><w:t>Another footnote.</w:t></w:r></w:p></w:footnote>' '<w:r><w:rPr /><w:t>Another footnote.</w:t></w:r></w:p></w:footnote>'
f'<w:footnote w:id="3"><w:p><w:pPr><w:pStyle w:val="{S_FNOTE}" /></w:pPr>' '<w:footnote w:id="3"><w:p><w:pPr><w:pStyle w:val="FootnoteText" /></w:pPr>'
'<w:r><w:rPr /><w:t>Again?</w:t></w:r></w:p></w:footnote>' '<w:r><w:rPr /><w:t>Again?</w:t></w:r></w:p></w:footnote>'
'</w:footnotes>' '</w:footnotes>'
) )
+12 -8
View File
@@ -25,6 +25,7 @@ import json
import pytest import pytest
from novelwriter import CONFIG from novelwriter import CONFIG
from novelwriter.constants import nwHeadFmt
from novelwriter.core.project import NWProject from novelwriter.core.project import NWProject
from novelwriter.formats.shared import BlockFmt, BlockTyp from novelwriter.formats.shared import BlockFmt, BlockTyp
from novelwriter.formats.tohtml import ToHtml from novelwriter.formats.tohtml import ToHtml
@@ -44,32 +45,35 @@ def testFmtToHtml_ConvertHeaders(mockGUI):
html._isFirst = True html._isFirst = True
# Header 1 # Header 1
html._text = "# Partition\n" html._text = "# Title\n"
html.setPartitionFormat(f"Part{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html._pages[-1] == ( assert html._pages[-1] == (
"<h1 class='title' style='text-align: center;'>Partition</h1>\n" "<h1 class='title' style='text-align: center;'>Part<br>Title</h1>\n"
) )
# Header 2 # Header 2
html._text = "## Chapter Title\n" html._text = "## Title\n"
html.setChapterFormat(f"Chapter {nwHeadFmt.CH_NUM}{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html._pages[-1] == ( assert html._pages[-1] == (
"<h1 style='page-break-before: always;'>Chapter Title</h1>\n" "<h1 style='page-break-before: always;'>Chapter 1<br>Title</h1>\n"
) )
# Header 3 # Header 3
html._text = "### Scene Title\n" html._text = "### Title\n"
html.setSceneFormat(f"Scene {nwHeadFmt.SC_ABS}{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html._pages[-1] == "<h2>Scene Title</h2>\n" assert html._pages[-1] == "<h2>Scene 1<br>Title</h2>\n"
# Header 4 # Header 4
html._text = "#### Section Title\n" html._text = "#### Title\n"
html.tokenizeText() html.tokenizeText()
html.doConvert() html.doConvert()
assert html._pages[-1] == "<h3>Section Title</h3>\n" assert html._pages[-1] == "<h3>Title</h3>\n"
# Title # Title
html._text = "#! Title\n" html._text = "#! Title\n"
+10 -6
View File
@@ -22,6 +22,7 @@ from __future__ import annotations
import pytest import pytest
from novelwriter.constants import nwHeadFmt
from novelwriter.core.project import NWProject from novelwriter.core.project import NWProject
from novelwriter.formats.shared import BlockFmt, BlockTyp from novelwriter.formats.shared import BlockFmt, BlockTyp
from novelwriter.formats.tomarkdown import ToMarkdown from novelwriter.formats.tomarkdown import ToMarkdown
@@ -37,22 +38,25 @@ def testFmtToMarkdown_ConvertHeaders(mockGUI):
md._isFirst = True md._isFirst = True
# Header 1 # Header 1
md._text = "# Partition\n" md._text = "# Title\n"
md.setPartitionFormat(f"Part{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
md.tokenizeText() md.tokenizeText()
md.doConvert() md.doConvert()
assert md._pages[-1] == "# Partition\n\n" assert md._pages[-1] == "# Part - Title\n\n"
# Header 2 # Header 2
md._text = "## Chapter Title\n" md._text = "## Title\n"
md.setChapterFormat(f"Chapter {nwHeadFmt.CH_NUM}{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
md.tokenizeText() md.tokenizeText()
md.doConvert() md.doConvert()
assert md._pages[-1] == "## Chapter Title\n\n" assert md._pages[-1] == "## Chapter 1 - Title\n\n"
# Header 3 # Header 3
md._text = "### Scene Title\n" md._text = "### Title\n"
md.setSceneFormat(f"Scene {nwHeadFmt.SC_ABS}{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
md.tokenizeText() md.tokenizeText()
md.doConvert() md.doConvert()
assert md._pages[-1] == "### Scene Title\n\n" assert md._pages[-1] == "### Scene 1 - Title\n\n"
# Header 4 # Header 4
md._text = "#### Section Title\n" md._text = "#### Section Title\n"
+13 -7
View File
@@ -281,6 +281,7 @@ def testFmtToOdt_ConvertHeaders(mockGUI):
# Header 1 # Header 1
odt._text = "# Title\n" odt._text = "# Title\n"
odt.setPartitionFormat(f"Part{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
odt.tokenizeText() odt.tokenizeText()
odt.initDocument() odt.initDocument()
odt.doConvert() odt.doConvert()
@@ -288,12 +289,14 @@ def testFmtToOdt_ConvertHeaders(mockGUI):
assert odt.errData == [] assert odt.errData == []
assert xmlToText(odt._xText) == ( assert xmlToText(odt._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">Part'
'<text:line-break />Title</text:h>'
'</office:text>' '</office:text>'
) )
# Header 2 # Header 2
odt._text = "## Chapter\n" odt._text = "## Title\n"
odt.setChapterFormat(f"Chapter {nwHeadFmt.CH_NUM}{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
odt.tokenizeText() odt.tokenizeText()
odt.initDocument() odt.initDocument()
odt.doConvert() odt.doConvert()
@@ -301,12 +304,14 @@ def testFmtToOdt_ConvertHeaders(mockGUI):
assert odt.errData == [] assert odt.errData == []
assert xmlToText(odt._xText) == ( assert xmlToText(odt._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 1'
'<text:line-break />Title</text:h>'
'</office:text>' '</office:text>'
) )
# Header 3 # Header 3
odt._text = "### Scene\n" odt._text = "### Title\n"
odt.setSceneFormat(f"Scene {nwHeadFmt.SC_ABS}{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
odt.tokenizeText() odt.tokenizeText()
odt.initDocument() odt.initDocument()
odt.doConvert() odt.doConvert()
@@ -314,12 +319,13 @@ def testFmtToOdt_ConvertHeaders(mockGUI):
assert odt.errData == [] assert odt.errData == []
assert xmlToText(odt._xText) == ( assert xmlToText(odt._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 1'
'<text:line-break />Title</text:h>'
'</office:text>' '</office:text>'
) )
# Header 4 # Header 4
odt._text = "#### Section\n" odt._text = "#### Title\n"
odt.tokenizeText() odt.tokenizeText()
odt.initDocument() odt.initDocument()
odt.doConvert() odt.doConvert()
@@ -327,7 +333,7 @@ def testFmtToOdt_ConvertHeaders(mockGUI):
assert odt.errData == [] assert odt.errData == []
assert xmlToText(odt._xText) == ( assert xmlToText(odt._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">Title</text:h>'
'</office:text>' '</office:text>'
) )