Move document format classes to new folder

This commit is contained in:
Veronica Berglyd Olsen
2024-10-15 19:29:56 +02:00
parent 2f12a8cc93
commit b56095224a
15 changed files with 76 additions and 76 deletions
+4 -4
View File
@@ -30,10 +30,10 @@ import pytest
from novelwriter.core.buildsettings import BuildSettings
from novelwriter.core.docbuild import NWBuildDocument
from novelwriter.core.project import NWProject
from novelwriter.core.tohtml import ToHtml
from novelwriter.core.tomarkdown import ToMarkdown
from novelwriter.core.toodt import ToOdt
from novelwriter.enum import nwBuildFmt
from novelwriter.formats.tohtml import ToHtml
from novelwriter.formats.tomarkdown import ToMarkdown
from novelwriter.formats.toodt import ToOdt
from tests.mocked import causeException, causeOSError
from tests.tools import ODT_IGNORE, C, buildTestProject, cmpFiles
@@ -146,7 +146,7 @@ def testCoreDocBuild_OpenDocument(monkeypatch, mockGUI, prjLipsum, fncPath, tstP
# ==================
with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.toodt.ToOdt.doConvert", causeException)
mp.setattr("novelwriter.formats.toodt.ToOdt.doConvert", causeException)
assert len(docBuild) == 21
count = 0
-737
View File
@@ -1,737 +0,0 @@
"""
novelWriter ToHtml Class Tester
=================================
This file is a part of novelWriter
Copyright 20182024, Veronica Berglyd Olsen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from __future__ import annotations
import json
import pytest
from novelwriter import CONFIG
from novelwriter.core.project import NWProject
from novelwriter.core.tohtml import ToHtml
@pytest.mark.core
def testCoreToHtml_ConvertHeaders(mockGUI):
"""Test header formats in the ToHtml class."""
project = NWProject()
html = ToHtml(project)
# Novel Files Headers
# ===================
html._isNovel = True
html._isFirst = True
# Header 1
html._text = "# Partition\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<h1 class='title' style='text-align: center;'>Partition</h1>\n"
)
# Header 2
html._text = "## Chapter Title\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<h1 style='page-break-before: always;'>Chapter Title</h1>\n"
)
# Header 3
html._text = "### Scene Title\n"
html.tokenizeText()
html.doConvert()
assert html.result == "<h2>Scene Title</h2>\n"
# Header 4
html._text = "#### Section Title\n"
html.tokenizeText()
html.doConvert()
assert html.result == "<h3>Section Title</h3>\n"
# Title
html._text = "#! Title\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<h1 class='title' style='text-align: center; page-break-before: always;'>Title</h1>\n"
)
# Unnumbered
html._text = "##! Prologue\n"
html.tokenizeText()
html.doConvert()
assert html.result == "<h1 style='page-break-before: always;'>Prologue</h1>\n"
# Note Files Headers
# ==================
html._isNovel = False
html._isFirst = True
html._handle = "0000000000000"
html.setLinkHeadings(True)
# Header 1
html._text = "# Heading One\n"
html.tokenizeText()
html.doConvert()
assert html.result == "<h1><a name='0000000000000:T0001'></a>Heading One</h1>\n"
# Header 2
html._text = "## Heading Two\n"
html.tokenizeText()
html.doConvert()
assert html.result == "<h2><a name='0000000000000:T0001'></a>Heading Two</h2>\n"
# Header 3
html._text = "### Heading Three\n"
html.tokenizeText()
html.doConvert()
assert html.result == "<h3><a name='0000000000000:T0001'></a>Heading Three</h3>\n"
# Header 4
html._text = "#### Heading Four\n"
html.tokenizeText()
html.doConvert()
assert html.result == "<h4><a name='0000000000000:T0001'></a>Heading Four</h4>\n"
# Title
html._text = "#! Heading One\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<h1 class='title' style='text-align: center; page-break-before: always;'>"
"<a name='0000000000000:T0001'></a>Heading One</h1>\n"
)
# Unnumbered
html._text = "##! Heading Two\n"
html.tokenizeText()
html.doConvert()
assert html.result == "<h2><a name='0000000000000:T0001'></a>Heading Two</h2>\n"
@pytest.mark.core
def testCoreToHtml_ConvertParagraphs(mockGUI):
"""Test paragraph formats in the ToHtml class."""
project = NWProject()
html = ToHtml(project)
html._isNovel = True
html._isFirst = True
# Paragraphs
# ==========
# Text
html._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p>Some <strong>nested bold and <em>italic</em> and "
"<del>strikethrough</del> text</strong> here</p>\n"
)
# Shortcodes
html._text = (
"Some [b]bold[/b], [i]italic[/i], [s]strike[/s], [u]underline[/u], [m]mark[/m], "
"super[sup]script[/sup], sub[sub]script[/sub] here\n"
)
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p>Some <strong>bold</strong>, <em>italic</em>, <del>strike</del>, "
"<span style='text-decoration: underline;'>underline</span>, <mark>mark</mark>, "
"super<sup>script</sup>, sub<sub>script</sub> here</p>\n"
)
# Text w/Hard Break
html._text = "Line one\nLine two\nLine three\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p>Line one<br>Line two<br>Line three</p>\n"
)
# Synopsis, Short
html._text = "%synopsis: The synopsis ...\n"
html.tokenizeText()
html.doConvert()
assert html.result == ""
html.setSynopsis(True)
html._text = "%synopsis: The synopsis ...\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p class='synopsis'><strong>Synopsis:</strong> The synopsis ...</p>\n"
)
html.setSynopsis(True)
html._text = "%short: A short description ...\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p class='synopsis'><strong>Short Description:</strong> A short description ...</p>\n"
)
# Comment
html._text = "% A comment ...\n"
html.tokenizeText()
html.doConvert()
assert html.result == ""
html.setComments(True)
html._text = "% A comment ...\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p class='comment'><strong>Comment:</strong> A comment ...</p>\n"
)
# Keywords
html._text = "@char: Bod, Jane\n"
html.tokenizeText()
html.doConvert()
assert html.result == ""
html.setKeywords(True)
html._text = "@char: Bod, Jane\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p class='meta meta-char'><span class='keyword'>Characters:</span> "
"<a class='tag' href='#tag_Bod'>Bod</a>, "
"<a class='tag' href='#tag_Jane'>Jane</a></p>\n"
)
# Tags
html._text = "@tag: Bod\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p class='meta meta-tag'><span class='keyword'>Tag:</span> "
"<a class='tag' name='tag_Bod'>Bod</a></p>\n"
)
html._text = "@tag: Bod | Nobody Owens\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p class='meta meta-tag'><span class='keyword'>Tag:</span> "
"<a class='tag' name='tag_Bod'>Bod</a> | <span class='optional'>Nobody Owens</a></p>\n"
)
# Multiple Keywords
html._isFirst = False
html.setKeywords(True)
html._text = "## Chapter\n\n@pov: Bod\n@plot: Main\n@location: Europe\n\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<h1 style='page-break-before: always;'>Chapter</h1>\n"
"<p class='meta meta-pov' style='margin-bottom: 0;'>"
"<span class='keyword'>Point of View:</span> "
"<a class='tag' href='#tag_Bod'>Bod</a></p>\n"
"<p class='meta meta-plot' style='margin-bottom: 0; margin-top: 0;'>"
"<span class='keyword'>Plot:</span> "
"<a class='tag' href='#tag_Main'>Main</a></p>\n"
"<p class='meta meta-location' style='margin-top: 0;'>"
"<span class='keyword'>Locations:</span> "
"<a class='tag' href='#tag_Europe'>Europe</a></p>\n"
)
# Dialogue
html.setDialogueHighlight(True)
html._text = "## Chapter\n\nThis text \u201chas dialogue\u201d in it.\n\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<h1 style='page-break-before: always;'>Chapter</h1>\n"
"<p>This text <span class='dialog'>\u201chas dialogue\u201d</span> in it.</p>\n"
)
# Alt. Dialogue
CONFIG.altDialogOpen = "::"
CONFIG.altDialogClose = "::"
html.setDialogueHighlight(True)
html._text = "## Chapter\n\nThis text ::has alt dialogue:: in it.\n\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<h1 style='page-break-before: always;'>Chapter</h1>\n"
"<p>This text <span class='altdialog'>::has alt dialogue::</span> in it.</p>\n"
)
# Footnotes
# =========
html._text = (
"Text with one[footnote:fa] or two[footnote:fb] footnotes.\n\n"
"%footnote.fa: Footnote text A.\n\n"
)
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p>Text with one<sup><a href='#footnote_1'>1</a></sup> "
"or two<sup>ERR</sup> footnotes.</p>\n"
)
html.appendFootnotes()
assert html.result == (
"<p>Text with one<sup><a href='#footnote_1'>1</a></sup> "
"or two<sup>ERR</sup> footnotes.</p>\n"
"<h3>Footnotes</h3>\n"
"<ol>\n"
"<li id='footnote_1'><p>Footnote text A.</p></li>\n"
"</ol>\n"
)
@pytest.mark.core
def testCoreToHtml_CloseTags(mockGUI):
"""Test automatic closing of HTML tags for shortcodes."""
project = NWProject()
html = ToHtml(project)
html._isNovel = True
html._isFirst = True
# Unclosed Shortcodes
html._text = "Text [b][i][s][u][m][sup][sub]text text text.\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p>Text <strong><em><del><span style='text-decoration: underline;'><mark><sup><sub>"
"text text text.</strong></em></del></span></mark></sup></sub></p>\n"
)
# Double Shortcodes
html._text = "Text [b][i][s][u][m][sup][sub]text [b][i][s][u][m][sup][sub]text text.\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p>Text <strong><em><del><span style='text-decoration: underline;'><mark><sup><sub>"
"text text text.</strong></em></del></span></mark></sup></sub></p>\n"
)
# Redundant Close Shortcodes
html._text = "Text text [/b][/i][/s][/u][/m][/sup][/sub]text text.\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p>Text text text text.</p>\n"
)
@pytest.mark.core
def testCoreToHtml_ConvertDirect(mockGUI):
"""Test the converter directly using the ToHtml class."""
project = NWProject()
html = ToHtml(project)
html._isNovel = True
html._handle = "0000000000000"
html.setLinkHeadings(True)
# Special Titles
# ==============
# Title
html._tokens = [
(html.T_TITLE, 1, "A Title", [], html.A_PBB | html.A_CENTRE),
]
html.doConvert()
assert html.result == (
"<h1 class='title' style='text-align: center; page-break-before: always;'>"
"<a name='0000000000000:T0001'></a>A Title</h1>\n"
)
# Unnumbered
html._tokens = [
(html.T_HEAD2, 1, "Prologue", [], html.A_PBB),
]
html.doConvert()
assert html.result == (
"<h1 style='page-break-before: always;'>"
"<a name='0000000000000:T0001'></a>Prologue</h1>\n"
)
# Separators
# ==========
# Separator
html._tokens = [
(html.T_SEP, 1, "* * *", [], html.A_CENTRE),
]
html.doConvert()
assert html.result == "<p class='sep' style='text-align: center;'>* * *</p>\n"
# Skip
html._tokens = [
(html.T_SKIP, 1, "", [], html.A_NONE),
]
html.doConvert()
assert html.result == "<p class='skip'>&nbsp;</p>\n"
# Alignment
# =========
html.setLinkHeadings(False)
# Align Left
html.setStyles(False)
html._tokens = [
(html.T_HEAD1, 1, "A Title", [], html.A_LEFT),
]
html.doConvert()
assert html.result == (
"<h1 class='title'>A Title</h1>\n"
)
html.setStyles(True)
# Align Left
html._tokens = [
(html.T_HEAD1, 1, "A Title", [], html.A_LEFT),
]
html.doConvert()
assert html.result == (
"<h1 class='title' style='text-align: left;'>A Title</h1>\n"
)
# Align Right
html._tokens = [
(html.T_HEAD1, 1, "A Title", [], html.A_RIGHT),
]
html.doConvert()
assert html.result == (
"<h1 class='title' style='text-align: right;'>A Title</h1>\n"
)
# Align Centre
html._tokens = [
(html.T_HEAD1, 1, "A Title", [], html.A_CENTRE),
]
html.doConvert()
assert html.result == (
"<h1 class='title' style='text-align: center;'>A Title</h1>\n"
)
# Align Justify
html._tokens = [
(html.T_HEAD1, 1, "A Title", [], html.A_JUSTIFY),
]
html.doConvert()
assert html.result == (
"<h1 class='title' style='text-align: justify;'>A Title</h1>\n"
)
# Page Break
# ==========
# Page Break Always
html._tokens = [
(html.T_HEAD1, 1, "A Title", [], html.A_PBB | html.A_PBA),
]
html.doConvert()
assert html.result == (
"<h1 class='title' "
"style='page-break-before: always; page-break-after: always;'>A Title</h1>\n"
)
# Indent
# ======
# Indent Left
html._tokens = [
(html.T_TEXT, 1, "Some text ...", [], html.A_IND_L),
]
html.doConvert()
assert html.result == (
"<p style='margin-left: 4.00em;'>Some text ...</p>\n"
)
# Indent Right
html._tokens = [
(html.T_TEXT, 1, "Some text ...", [], html.A_IND_R),
]
html.doConvert()
assert html.result == (
"<p style='margin-right: 4.00em;'>Some text ...</p>\n"
)
# Text Indent
html._tokens = [
(html.T_TEXT, 1, "Some text ...", [], html.A_IND_T),
]
html.doConvert()
assert html.result == (
"<p style='text-indent: 1.40em;'>Some text ...</p>\n"
)
@pytest.mark.core
def testCoreToHtml_SpecialCases(mockGUI):
"""Test some special cases that have caused errors in the past."""
project = NWProject()
html = ToHtml(project)
html._isNovel = True
# Greater/Lesser than symbols
# ===========================
html._text = "Text with > and < with some **bold text** in it.\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p>Text with &gt; and &lt; with some <strong>bold text</strong> in it.</p>\n"
)
html._text = "Text with some <**bold text**> in it.\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p>Text with some &lt;<strong>bold text</strong>&gt; in it.</p>\n"
)
html._text = "Let's > be > _difficult **shall** > we_?\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p>Let's &gt; be &gt; <em>difficult <strong>shall</strong> &gt; we</em>?</p>\n"
)
html._text = "Test > text _<**bold**>_ and more.\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p>Test &gt; text <em>&lt;<strong>bold</strong>&gt;</em> and more.</p>\n"
)
# Test for issue #950
# ===================
# See: https://github.com/vkbo/novelWriter/issues/950
html.setComments(True)
html._text = "% Test > text _<**bold**>_ and more.\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p class='comment'>"
"<strong>Comment:</strong> Test &gt; text <em>&lt;<strong>bold</strong>&gt;</em> and more."
"</p>\n"
)
html._isFirst = False
html._text = "## Heading <1>\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<h1 style='page-break-before: always;'>Heading &lt;1&gt;</h1>\n"
)
# Test for issue #1412
# ====================
# See: https://github.com/vkbo/novelWriter/issues/1412
html._text = "Test text \\**_bold_** and more.\n"
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p>Test text **<em>bold</em>** and more.</p>\n"
)
@pytest.mark.core
def testCoreToHtml_Save(mockGUI, fncPath):
"""Test the save method of the ToHtml class."""
project = NWProject()
html = ToHtml(project)
html._isNovel = True
# Build Project
# =============
docText = [
"# My Novel\n**By Jane Doh**\n",
"## Chapter 1\n\nThe text of chapter one.\n",
"### Scene 1\n\nThe text of scene one.\n",
"#### A Section\n\nMore text in scene one.\n",
"## Chapter 2\n\nThe text of chapter two.\n",
"### Scene 2\n\nThe text of scene two.\n",
"#### A Section\n\n\tMore text in scene two.\n",
]
resText = [(
"<h1 class='title' style='text-align: center;'>My Novel</h1>\n"
"<p><strong>By Jane Doh</strong></p>\n"
), (
"<h1 style='page-break-before: always;'>Chapter 1</h1>\n"
"<p>The text of chapter one.</p>\n"
), (
"<h2>Scene 1</h2>\n"
"<p>The text of scene one.</p>\n"
), (
"<h3>A Section</h3>\n"
"<p>More text in scene one.</p>\n"
), (
"<h1 style='page-break-before: always;'>Chapter 2</h1>\n"
"<p>The text of chapter two.</p>\n"
), (
"<h2>Scene 2</h2>\n"
"<p>The text of scene two.</p>\n"
), (
"<h3>A Section</h3>\n"
"<p>\tMore text in scene two.</p>\n"
)]
for i in range(len(docText)):
html._text = docText[i]
html.doPreProcessing()
html.tokenizeText()
html.doConvert()
assert html.result == resText[i]
assert html.fullHTML == resText
html.replaceTabs(nSpaces=2, spaceChar="&nbsp;")
resText[6] = "<h3>A Section</h3>\n<p>&nbsp;&nbsp;More text in scene two.</p>\n"
# Check Files
# ===========
# HTML
hStyle = html.getStyleSheet()
htmlDoc = (
"<!DOCTYPE html>\n"
"<html>\n"
"<head>\n"
"<meta charset='utf-8'>\n"
"<title></title>\n"
"</head>\n"
"<style>\n"
"{htmlStyle:s}\n"
"</style>\n"
"<body>\n"
"<article>\n"
"{bodyText:s}\n"
"</article>\n"
"</body>\n"
"</html>\n"
).format(
htmlStyle="\n".join(hStyle),
bodyText="".join(resText).rstrip()
)
saveFile = fncPath / "outFile.htm"
html.saveHtml5(saveFile)
assert saveFile.read_text(encoding="utf-8") == htmlDoc
# JSON + HTML
saveFile = fncPath / "outFile.json"
html.saveHtmlJson(saveFile)
data = json.loads(saveFile.read_text(encoding="utf-8"))
assert data["meta"]["projectName"] == ""
assert data["meta"]["novelAuthor"] == ""
assert data["meta"]["buildTime"] > 0
assert data["meta"]["buildTimeStr"] != ""
assert data["text"]["css"] == hStyle
assert len(data["text"]["html"]) == len(resText)
@pytest.mark.core
def testCoreToHtml_Methods(mockGUI):
"""Test all the other methods of the ToHtml class."""
project = NWProject()
html = ToHtml(project)
html.setKeepMarkdown(True)
# Auto-Replace, keep Unicode
docText = "Text with <brackets> & shortdash, long—dash …\n"
html._text = docText
html.setReplaceUnicode(False)
html.doPreProcessing()
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p>Text with &lt;brackets&gt; &amp; shortdash, long—dash …</p>\n"
)
# Auto-Replace, replace Unicode
docText = "Text with <brackets> & shortdash, long—dash …\n"
html._text = docText
html.setReplaceUnicode(True)
html.doPreProcessing()
html.tokenizeText()
html.doConvert()
assert html.result == (
"<p>Text with &lt;brackets&gt; &amp; short&ndash;dash, long&mdash;dash &hellip;</p>\n"
)
# Result Size
assert html.getFullResultSize() == 147
# CSS
# ===
assert len(html.getStyleSheet()) > 1
assert "p {text-align: left;" in " ".join(html.getStyleSheet())
assert "p {text-align: justify;" not in " ".join(html.getStyleSheet())
html.setJustify(True)
assert "p {text-align: left;" not in " ".join(html.getStyleSheet())
assert "p {text-align: justify;" in " ".join(html.getStyleSheet())
html.setStyles(False)
assert html.getStyleSheet() == []
@pytest.mark.core
def testCoreToHtml_Format(mockGUI):
"""Test all the formatters for the ToHtml class."""
project = NWProject()
html = ToHtml(project)
# Export Mode
# ===========
assert html._formatSynopsis("synopsis text", True) == (
"<p class='synopsis'><strong>Synopsis:</strong> synopsis text</p>\n"
)
assert html._formatSynopsis("short text", False) == (
"<p class='synopsis'><strong>Short Description:</strong> short text</p>\n"
)
assert html._formatComments("comment text") == (
"<p class='comment'><strong>Comment:</strong> comment text</p>\n"
)
assert html._formatKeywords("") == ("", "")
assert html._formatKeywords("tag: Jane") == (
"tag", "<span class='keyword'>Tag:</span> <a class='tag' name='tag_Jane'>Jane</a>"
)
assert html._formatKeywords("char: Bod, Jane") == (
"char",
"<span class='keyword'>Characters:</span> "
"<a class='tag' href='#tag_Bod'>Bod</a>, "
"<a class='tag' href='#tag_Jane'>Jane</a>"
)
File diff suppressed because it is too large Load Diff
-309
View File
@@ -1,309 +0,0 @@
"""
novelWriter ToMd Class Tester
===============================
This file is a part of novelWriter
Copyright 20182024, Veronica Berglyd Olsen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from __future__ import annotations
import pytest
from novelwriter.core.project import NWProject
from novelwriter.core.tomarkdown import ToMarkdown
@pytest.mark.core
def testCoreToMarkdown_ConvertHeaders(mockGUI):
"""Test header formats in the ToMarkdown class."""
project = NWProject()
toMD = ToMarkdown(project)
toMD._isNovel = True
toMD._isFirst = True
# Header 1
toMD._text = "# Partition\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == "# Partition\n\n"
# Header 2
toMD._text = "## Chapter Title\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == "## Chapter Title\n\n"
# Header 3
toMD._text = "### Scene Title\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == "### Scene Title\n\n"
# Header 4
toMD._text = "#### Section Title\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == "#### Section Title\n\n"
# Title
toMD._text = "#! Title\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == "# Title\n\n"
# Unnumbered
toMD._text = "##! Prologue\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == "## Prologue\n\n"
@pytest.mark.core
def testCoreToMarkdown_ConvertParagraphs(mockGUI):
"""Test paragraph formats in the ToMarkdown class."""
project = NWProject()
toMD = ToMarkdown(project)
toMD._isNovel = True
toMD._isFirst = True
# Text for Extended Markdown
toMD.setExtendedMarkdown(True)
toMD._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == (
"Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n\n"
)
# Text for Standard Markdown
toMD.setExtendedMarkdown(False)
toMD._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == (
"Some **nested bold and _italic_ and strikethrough text** here\n\n"
)
# Shortcodes for Extended Markdown
toMD.setExtendedMarkdown(True)
toMD._text = (
"Some [b]bold[/b], [i]italic[/i], [s]strike[/s], [u]underline[/u], [m]mark[/m], "
"super[sup]script[/sup], sub[sub]script[/sub] here\n"
)
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == (
"Some **bold**, _italic_, ~~strike~~, underline, ==mark==, "
"super^script^, sub~script~ here\n\n"
)
# Shortcodes for Standard Markdown
toMD.setExtendedMarkdown(False)
toMD._text = (
"Some [b]bold[/b], [i]italic[/i], [s]strike[/s], [u]underline[/u], [m]mark[/m], "
"super[sup]script[/sup], sub[sub]script[/sub] here\n"
)
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == (
"Some **bold**, _italic_, strike, underline, mark, superscript, subscript here\n\n"
)
# Text w/Hard Break
toMD._text = "Line one\nLine two\nLine three\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == "Line one \nLine two \nLine three\n\n"
# Text wo/Hard Break
toMD._text = "Line one\nLine two\nLine three\n"
toMD.setKeepLineBreaks(False)
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == "Line one Line two Line three\n\n"
# Synopsis, Short
toMD._text = "%synopsis: The synopsis ...\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == ""
toMD.setSynopsis(True)
toMD._text = "%synopsis: The synopsis ...\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == "**Synopsis:** The synopsis ...\n\n"
toMD.setSynopsis(True)
toMD._text = "%short: A description ...\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == "**Short Description:** A description ...\n\n"
# Comment
toMD._text = "% A comment ...\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == ""
toMD.setComments(True)
toMD._text = "% A comment ...\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == "**Comment:** A comment ...\n\n"
# Keywords
toMD._text = "@char: Bod, Jane\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == ""
toMD.setKeywords(True)
toMD._text = "@char: Bod, Jane\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == "**Characters:** Bod, Jane\n\n"
# Multiple Keywords
toMD.setKeywords(True)
toMD._text = "## Chapter\n\n@pov: Bod\n@plot: Main\n@location: Europe\n\n"
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == (
"## Chapter\n\n"
"**Point of View:** Bod \n"
"**Plot:** Main \n"
"**Locations:** Europe\n\n"
)
# Footnotes
toMD._text = (
"Text with one[footnote:fa] or two[footnote:fb] footnotes.\n\n"
"%footnote.fa: Footnote text A.\n\n"
)
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == "Text with one[1] or two[ERR] footnotes.\n\n"
toMD.appendFootnotes()
assert toMD.result == (
"Text with one[1] or two[ERR] footnotes.\n\n"
"### Footnotes\n\n"
"1. Footnote text A.\n\n"
)
@pytest.mark.core
def testCoreToMarkdown_ConvertDirect(mockGUI):
"""Test the converter directly using the ToMarkdown class."""
project = NWProject()
toMD = ToMarkdown(project)
toMD._isNovel = True
toMD.setExtendedMarkdown(False)
# Special Titles
# ==============
# Title
toMD._tokens = [
(toMD.T_TITLE, 1, "A Title", [], toMD.A_PBB | toMD.A_CENTRE),
]
toMD.doConvert()
assert toMD.result == "# A Title\n\n"
# Separators
# ==========
# Separator
toMD._tokens = [
(toMD.T_SEP, 1, "* * *", [], toMD.A_CENTRE),
]
toMD.doConvert()
assert toMD.result == "* * *\n\n"
# Skip
toMD._tokens = [
(toMD.T_SKIP, 1, "", [], toMD.A_NONE),
]
toMD.doConvert()
assert toMD.result == "\n\n"
@pytest.mark.core
def testCoreToMarkdown_Save(mockGUI, fncPath):
"""Test the save method of the ToMarkdown class."""
project = NWProject()
toMD = ToMarkdown(project)
toMD.setKeepMarkdown(True)
toMD._isNovel = True
# Build Project
# =============
docText = [
"# My Novel\n\n**By Jane Doh**\n",
"## Chapter 1\n\nThe text of chapter one.\n",
"### Scene 1\n\nThe text of scene one.\n",
"#### A Section\n\nMore text in scene one.\n",
"## Chapter 2\n\nThe text of chapter two.\n",
"### Scene 2\n\nThe text of scene two.\n",
"#### A Section\n\n\tMore text in scene two.\n",
]
resText = [
"# My Novel\n\n**By Jane Doh**\n\n",
"## Chapter 1\n\nThe text of chapter one.\n\n",
"### Scene 1\n\nThe text of scene one.\n\n",
"#### A Section\n\nMore text in scene one.\n\n",
"## Chapter 2\n\nThe text of chapter two.\n\n",
"### Scene 2\n\nThe text of scene two.\n\n",
"#### A Section\n\n\tMore text in scene two.\n\n",
]
for i in range(len(docText)):
toMD._text = docText[i]
toMD.doPreProcessing()
toMD.tokenizeText()
toMD.doConvert()
assert toMD.result == resText[i]
assert toMD.fullMD == resText
assert toMD.getFullResultSize() == len("".join(resText))
toMD.replaceTabs(nSpaces=4, spaceChar=" ")
resText[6] = "#### A Section\n\n More text in scene two.\n\n"
assert toMD.allMarkdown == resText
# Check File
# ==========
saveFile = fncPath / "outFile.md"
toMD.saveMarkdown(saveFile)
assert saveFile.read_text(encoding="utf-8") == "".join(resText)
@pytest.mark.core
def testCoreToMarkdown_Format(mockGUI):
"""Test all the formatters for the ToMarkdown class."""
project = NWProject()
toMD = ToMarkdown(project)
assert toMD._formatKeywords("", toMD.A_NONE) == ""
assert toMD._formatKeywords("tag: Jane", toMD.A_NONE) == "**Tag:** Jane\n\n"
assert toMD._formatKeywords("tag: Jane, John", toMD.A_NONE) == "**Tag:** Jane, John\n\n"
assert toMD._formatKeywords("tag: Jane", toMD.A_Z_BTMMRG) == "**Tag:** Jane \n"
File diff suppressed because it is too large Load Diff
-612
View File
@@ -1,612 +0,0 @@
"""
novelWriter ToQTextDocument Class Tester
==========================================
This file is a part of novelWriter
Copyright 20182024, Veronica Berglyd Olsen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from __future__ import annotations
import pytest
from PyQt5.QtGui import QColor, QTextBlock, QTextCharFormat, QTextCursor
from novelwriter import CONFIG
from novelwriter.constants import nwUnicode
from novelwriter.core.project import NWProject
from novelwriter.core.toqdoc import TextDocumentTheme, ToQTextDocument
from novelwriter.types import (
QtAlignAbsolute, QtAlignCenter, QtAlignJustify, QtAlignLeft, QtAlignRight,
QtPageBreakAfter, QtTransparent, QtVAlignNormal, QtVAlignSub, QtVAlignSuper
)
THEME = TextDocumentTheme()
THEME.text = QColor(0, 0, 0)
THEME.highlight = QColor(255, 255, 166)
THEME.head = QColor(66, 113, 174)
THEME.comment = QColor(100, 100, 100)
THEME.note = QColor(129, 55, 9)
THEME.code = QColor(66, 113, 174)
THEME.modifier = QColor(129, 55, 9)
THEME.keyword = QColor(245, 135, 31)
THEME.tag = QColor(66, 113, 174)
THEME.optional = QColor(66, 113, 174)
THEME.dialog = QColor(113, 140, 0)
THEME.altdialog = QColor(234, 183, 0)
def charFmtInBlock(block: QTextBlock, pos: int) -> QTextCharFormat:
"""Get the character format at a given place in a block."""
cursor = QTextCursor(block)
cursor.setPosition(block.position() + pos)
return cursor.charFormat()
@pytest.mark.core
def testCoreToQTextDocument_ConvertHeaders(mockGUI):
"""Test header formats in the ToQTextDocument class."""
project = NWProject()
qdoc = ToQTextDocument(project)
qdoc.initDocument(CONFIG.textFont, THEME)
qdoc._isNovel = True
qdoc._isFirst = True
qdoc._text = (
"#! Title\n"
"# Partition\n"
"## Chapter\n"
"### Scene\n"
"#### Section\n"
)
qdoc.tokenizeText()
qdoc.doConvert()
assert qdoc.document.blockCount() == 5
# Title
block = qdoc.document.findBlockByNumber(0)
assert block.text() == "Title"
bFmt = block.blockFormat()
assert bFmt.topMargin() == qdoc._mHead[qdoc.T_TITLE][0]
assert bFmt.bottomMargin() == qdoc._mHead[qdoc.T_TITLE][1]
cFmt = charFmtInBlock(block, 1)
assert cFmt.fontWeight() == qdoc._bold
assert cFmt.fontPointSize() == qdoc._sHead[qdoc.T_TITLE]
assert cFmt.foreground().color() == THEME.text
# Partition
block = qdoc.document.findBlockByNumber(1)
assert block.text() == "Partition"
bFmt = block.blockFormat()
assert bFmt.topMargin() == qdoc._mHead[qdoc.T_HEAD1][0]
assert bFmt.bottomMargin() == qdoc._mHead[qdoc.T_HEAD1][1]
cFmt = charFmtInBlock(block, 1)
assert cFmt.fontWeight() == qdoc._bold
assert cFmt.fontPointSize() == qdoc._sHead[qdoc.T_HEAD1]
assert cFmt.foreground().color() == THEME.head
# Chapter
block = qdoc.document.findBlockByNumber(2)
assert block.text() == "Chapter"
bFmt = block.blockFormat()
assert bFmt.topMargin() == qdoc._mHead[qdoc.T_HEAD2][0]
assert bFmt.bottomMargin() == qdoc._mHead[qdoc.T_HEAD2][1]
cFmt = charFmtInBlock(block, 1)
assert cFmt.fontWeight() == qdoc._bold
assert cFmt.fontPointSize() == qdoc._sHead[qdoc.T_HEAD2]
assert cFmt.foreground().color() == THEME.head
# Scene
block = qdoc.document.findBlockByNumber(3)
assert block.text() == "Scene"
bFmt = block.blockFormat()
assert bFmt.topMargin() == qdoc._mHead[qdoc.T_HEAD3][0]
assert bFmt.bottomMargin() == qdoc._mHead[qdoc.T_HEAD3][1]
cFmt = charFmtInBlock(block, 1)
assert cFmt.fontWeight() == qdoc._bold
assert cFmt.fontPointSize() == qdoc._sHead[qdoc.T_HEAD3]
assert cFmt.foreground().color() == THEME.head
# Section
block = qdoc.document.findBlockByNumber(4)
assert block.text() == "Section"
bFmt = block.blockFormat()
assert bFmt.topMargin() == qdoc._mHead[qdoc.T_HEAD4][0]
assert bFmt.bottomMargin() == qdoc._mHead[qdoc.T_HEAD4][1]
cFmt = charFmtInBlock(block, 1)
assert cFmt.fontWeight() == qdoc._bold
assert cFmt.fontPointSize() == qdoc._sHead[qdoc.T_HEAD4]
assert cFmt.foreground().color() == THEME.head
@pytest.mark.core
def testCoreToQTextDocument_SeparatorSkip(mockGUI):
"""Test separator and skip in the ToQTextDocument class."""
project = NWProject()
qdoc = ToQTextDocument(project)
qdoc.initDocument(CONFIG.textFont, THEME)
qdoc._isNovel = True
qdoc._isFirst = True
qdoc._text = (
"#! Title\n"
"## Chapter\n"
"### Scene 1\n"
"Text 1\n"
"### Scene 2\n"
"Text 2\n"
"#### Section\n"
"Text 3\n"
)
qdoc.setSceneFormat("* * *", False)
qdoc.setSectionFormat("", False)
qdoc.tokenizeText()
qdoc.doConvert()
assert qdoc.document.blockCount() == 7
# 0: Title
block = qdoc.document.findBlockByNumber(0)
assert block.text() == "Title"
# 1: Chapter
block = qdoc.document.findBlockByNumber(1)
assert block.text() == "Chapter"
# Hidden: Scene 1
# 2: Text 1
block = qdoc.document.findBlockByNumber(2)
assert block.text() == "Text 1"
# 3: Scene 2
block = qdoc.document.findBlockByNumber(3)
assert block.text() == "* * *"
bFmt = block.blockFormat()
assert bFmt.topMargin() == qdoc._mSep[0]
assert bFmt.bottomMargin() == qdoc._mSep[1]
cFmt = charFmtInBlock(block, 1)
assert cFmt.foreground().color() == THEME.text
# 4: Text 2
block = qdoc.document.findBlockByNumber(4)
assert block.text() == "Text 2"
# 5: Section
block = qdoc.document.findBlockByNumber(5)
assert block.text() == nwUnicode.U_NBSP
bFmt = block.blockFormat()
assert bFmt.topMargin() == qdoc._mText[0]
assert bFmt.bottomMargin() == qdoc._mText[1]
cFmt = charFmtInBlock(block, 1)
assert cFmt.foreground().color() == THEME.text
# 6: Text 3
block = qdoc.document.findBlockByNumber(6)
assert block.text() == "Text 3"
@pytest.mark.core
def testCoreToQTextDocument_NovelMeta(mockGUI):
"""Test novel meta formats in the ToQTextDocument class."""
project = NWProject()
qdoc = ToQTextDocument(project)
qdoc.initDocument(CONFIG.textFont, THEME)
qdoc._isNovel = True
qdoc._isFirst = True
qdoc.setComments(True)
qdoc.setSynopsis(True)
qdoc.setKeywords(True)
qdoc._text = (
"### Scene\n\n"
"@pov: Jane\n"
"@char: John, Bob\n\n"
"%Synopsis: Stuff that happened\n\n"
"% A regular comment\n\n"
"Text\n\n"
)
qdoc.tokenizeText()
qdoc.doConvert()
assert qdoc.document.blockCount() == 6
# 0: Scene
block = qdoc.document.findBlockByNumber(0)
assert block.text() == "Scene"
# 1: Jane
block = qdoc.document.findBlockByNumber(1)
assert block.text() == "Point of View: Jane"
bFmt = block.blockFormat()
assert bFmt.topMargin() == qdoc._mMeta[0]
assert bFmt.bottomMargin() == 0.0
cFmt = charFmtInBlock(block, 1)
assert cFmt.foreground().color() == THEME.keyword
cFmt = charFmtInBlock(block, 16)
assert cFmt.foreground().color() == THEME.tag
# 2: John, Bob
block = qdoc.document.findBlockByNumber(2)
assert block.text() == "Characters: John, Bob"
bFmt = block.blockFormat()
assert bFmt.topMargin() == 0.0
assert bFmt.bottomMargin() == qdoc._mMeta[1]
cFmt = charFmtInBlock(block, 1)
assert cFmt.foreground().color() == THEME.keyword
cFmt = charFmtInBlock(block, 13)
assert cFmt.foreground().color() == THEME.tag
# 3: Synopsis
block = qdoc.document.findBlockByNumber(3)
assert block.text() == "Synopsis: Stuff that happened"
bFmt = block.blockFormat()
assert bFmt.topMargin() == qdoc._mText[0]
assert bFmt.bottomMargin() == qdoc._mText[1]
cFmt = charFmtInBlock(block, 1)
assert cFmt.foreground().color() == THEME.modifier
cFmt = charFmtInBlock(block, 11)
assert cFmt.foreground().color() == THEME.note
# 4: Comment
block = qdoc.document.findBlockByNumber(4)
assert block.text() == "Comment: A regular comment"
bFmt = block.blockFormat()
assert bFmt.topMargin() == qdoc._mText[0]
assert bFmt.bottomMargin() == qdoc._mText[1]
cFmt = charFmtInBlock(block, 1)
assert cFmt.foreground().color() == THEME.comment
cFmt = charFmtInBlock(block, 10)
assert cFmt.foreground().color() == THEME.comment
# 5: Text
block = qdoc.document.findBlockByNumber(5)
assert block.text() == "Text"
@pytest.mark.core
def testCoreToQTextDocument_NoteMeta(mockGUI):
"""Test note meta formats in the ToQTextDocument class."""
project = NWProject()
qdoc = ToQTextDocument(project)
qdoc.initDocument(CONFIG.textFont, THEME)
qdoc._isNovel = False
qdoc._isFirst = True
qdoc.setComments(True)
qdoc.setSynopsis(True)
qdoc.setKeywords(True)
qdoc._text = (
"# Jane Smith\n\n"
"@tag: Jane | Jane Smith\n"
"%Short: All about Jane\n\n"
"Text\n\n"
)
qdoc.tokenizeText()
qdoc.doConvert()
assert qdoc.document.blockCount() == 4
# 0: Title
block = qdoc.document.findBlockByNumber(0)
assert block.text() == "Jane Smith"
# 1: Tag
block = qdoc.document.findBlockByNumber(1)
assert block.text() == "Tag: Jane | Jane Smith"
bFmt = block.blockFormat()
assert bFmt.topMargin() == qdoc._mMeta[0]
assert bFmt.bottomMargin() == qdoc._mMeta[1]
cFmt = charFmtInBlock(block, 1)
assert cFmt.foreground().color() == THEME.keyword
cFmt = charFmtInBlock(block, 6)
assert cFmt.foreground().color() == THEME.tag
cFmt = charFmtInBlock(block, 11)
assert cFmt.foreground().color() == THEME.text
cFmt = charFmtInBlock(block, 13)
assert cFmt.foreground().color() == THEME.optional
# 2: Short
block = qdoc.document.findBlockByNumber(2)
assert block.text() == "Short Description: All about Jane"
bFmt = block.blockFormat()
assert bFmt.topMargin() == qdoc._mText[0]
assert bFmt.bottomMargin() == qdoc._mText[1]
cFmt = charFmtInBlock(block, 1)
assert cFmt.foreground().color() == THEME.modifier
cFmt = charFmtInBlock(block, 20)
assert cFmt.foreground().color() == THEME.note
# 3: Text
block = qdoc.document.findBlockByNumber(3)
assert block.text() == "Text"
@pytest.mark.core
def testCoreToQTextDocument_TextBlockFormats(mockGUI):
"""Test text block formats in the ToQTextDocument class."""
project = NWProject()
qdoc = ToQTextDocument(project)
qdoc.setFirstLineIndent(True, 2.0, False)
qdoc.initDocument(CONFIG.textFont, THEME)
qdoc._isNovel = True
qdoc._isFirst = True
# Alignment & Indent
# ==================
qdoc.document.clear()
qdoc._text = (
"### Scene\n\n"
"Left <<\n\n"
">> Center <<\n\n"
">> Right\n\n"
"> Left Indent\n\n"
"Right Indent <\n\n"
"> Double Indent <\n\n"
"Text Indent\n\n"
)
qdoc.tokenizeText()
qdoc.doConvert()
assert qdoc.document.blockCount() == 8
# 0: Scene
block = qdoc.document.findBlockByNumber(0)
assert block.text() == "Scene"
# 1: Left
block = qdoc.document.findBlockByNumber(1)
assert block.text() == "Left"
bFmt = block.blockFormat()
assert bFmt.alignment() == QtAlignLeft
# 2: Center
block = qdoc.document.findBlockByNumber(2)
assert block.text() == "Center"
bFmt = block.blockFormat()
assert bFmt.alignment() == QtAlignCenter
# 3: Right
block = qdoc.document.findBlockByNumber(3)
assert block.text() == "Right"
bFmt = block.blockFormat()
assert bFmt.alignment() == QtAlignRight
# 4: Left Indent
block = qdoc.document.findBlockByNumber(4)
assert block.text() == "Left Indent"
bFmt = block.blockFormat()
assert bFmt.alignment() == QtAlignAbsolute
assert bFmt.leftMargin() == qdoc._mIndent
assert bFmt.rightMargin() == 0.0
# 5: Right Indent
block = qdoc.document.findBlockByNumber(5)
assert block.text() == "Right Indent"
bFmt = block.blockFormat()
assert bFmt.alignment() == QtAlignAbsolute
assert bFmt.leftMargin() == 0.0
assert bFmt.rightMargin() == qdoc._mIndent
# 6: Double Indent
block = qdoc.document.findBlockByNumber(6)
assert block.text() == "Double Indent"
bFmt = block.blockFormat()
assert bFmt.alignment() == QtAlignAbsolute
assert bFmt.leftMargin() == qdoc._mIndent
assert bFmt.rightMargin() == qdoc._mIndent
# 7: Text Indent
block = qdoc.document.findBlockByNumber(7)
assert block.text() == "Text Indent"
bFmt = block.blockFormat()
assert bFmt.alignment() == QtAlignAbsolute
assert bFmt.textIndent() == qdoc._tIndent
assert bFmt.leftMargin() == 0.0
assert bFmt.rightMargin() == 0.0
# Unreachable
# ===========
# Some formatting markers are currently not reachable
qdoc.document.clear()
qdoc._tokens = [
(qdoc.T_TEXT, 1, "This is justified", [], qdoc.A_JUSTIFY),
(qdoc.T_TEXT, 1, "This has a page break", [], qdoc.A_PBA),
]
qdoc.doConvert()
assert qdoc.document.blockCount() == 2
# 0: Justify
block = qdoc.document.findBlockByNumber(0)
assert block.text() == "This is justified"
bFmt = block.blockFormat()
assert bFmt.alignment() == QtAlignJustify
# 1: Page Break After
block = qdoc.document.findBlockByNumber(1)
assert block.text() == "This has a page break"
bFmt = block.blockFormat()
assert bFmt.pageBreakPolicy() == QtPageBreakAfter
@pytest.mark.core
def testCoreToQTextDocument_TextCharFormats(mockGUI):
"""Test text char formats in the ToQTextDocument class."""
CONFIG.fmtDQuoteOpen = nwUnicode.U_LDQUO
CONFIG.fmtDQuoteClose = nwUnicode.U_RDQUO
CONFIG.altDialogOpen = "|<"
CONFIG.altDialogClose = ">|"
project = NWProject()
qdoc = ToQTextDocument(project)
# Convert before init
qdoc._text = "Blabla"
qdoc.setDialogueHighlight(True)
qdoc.doConvert()
qdoc.tokenizeText()
assert qdoc.document.toPlainText() == ""
# Init
qdoc.initDocument(CONFIG.textFont, THEME)
qdoc._isNovel = True
qdoc._isFirst = True
qdoc._text = (
"### Scene\n\n"
"With [b]bold[/b] text\n\n"
"With [i]italic[/i] text\n\n"
"With [s]deleted[/s] text\n\n"
"With [u]underlined[/u] text\n\n"
"With [m]highlighted[/m] text\n\n"
"With super[sup]script[/sup] text\n\n"
"With sub[sub]script[/sub] text\n\n"
"With \u201cdialog\u201d text\n\n"
"With |<alternative dialog>| text\n\n"
)
qdoc.tokenizeText()
qdoc.doConvert()
assert qdoc.document.blockCount() == 10
# 0: Scene
block = qdoc.document.findBlockByNumber(0)
assert block.text() == "Scene"
# 1: Bold
block = qdoc.document.findBlockByNumber(1)
assert block.text() == "With bold text"
cFmt = charFmtInBlock(block, 1)
assert cFmt.fontWeight() == qdoc._normal
cFmt = charFmtInBlock(block, 6)
assert cFmt.fontWeight() == qdoc._bold
cFmt = charFmtInBlock(block, 10)
assert cFmt.fontWeight() == qdoc._normal
# 2: Italic
block = qdoc.document.findBlockByNumber(2)
assert block.text() == "With italic text"
cFmt = charFmtInBlock(block, 1)
assert cFmt.fontItalic() is False
cFmt = charFmtInBlock(block, 6)
assert cFmt.fontItalic() is True
cFmt = charFmtInBlock(block, 12)
assert cFmt.fontItalic() is False
# 3: Deleted
block = qdoc.document.findBlockByNumber(3)
assert block.text() == "With deleted text"
cFmt = charFmtInBlock(block, 1)
assert cFmt.fontStrikeOut() is False
cFmt = charFmtInBlock(block, 6)
assert cFmt.fontStrikeOut() is True
cFmt = charFmtInBlock(block, 13)
assert cFmt.fontStrikeOut() is False
# 4: Underlined
block = qdoc.document.findBlockByNumber(4)
assert block.text() == "With underlined text"
cFmt = charFmtInBlock(block, 1)
assert cFmt.fontUnderline() is False
cFmt = charFmtInBlock(block, 6)
assert cFmt.fontUnderline() is True
cFmt = charFmtInBlock(block, 16)
assert cFmt.fontUnderline() is False
# 5: Highlighted
block = qdoc.document.findBlockByNumber(5)
assert block.text() == "With highlighted text"
cFmt = charFmtInBlock(block, 1)
assert cFmt.background() == QtTransparent
cFmt = charFmtInBlock(block, 6)
assert cFmt.background() == THEME.highlight
cFmt = charFmtInBlock(block, 17)
assert cFmt.background() == QtTransparent
# 6: Superscript
block = qdoc.document.findBlockByNumber(6)
assert block.text() == "With superscript text"
cFmt = charFmtInBlock(block, 1)
assert cFmt.verticalAlignment() == QtVAlignNormal
cFmt = charFmtInBlock(block, 11)
assert cFmt.verticalAlignment() == QtVAlignSuper
cFmt = charFmtInBlock(block, 17)
assert cFmt.verticalAlignment() == QtVAlignNormal
# 7: Subscript
block = qdoc.document.findBlockByNumber(7)
assert block.text() == "With subscript text"
cFmt = charFmtInBlock(block, 1)
assert cFmt.verticalAlignment() == QtVAlignNormal
cFmt = charFmtInBlock(block, 9)
assert cFmt.verticalAlignment() == QtVAlignSub
cFmt = charFmtInBlock(block, 15)
assert cFmt.verticalAlignment() == QtVAlignNormal
# 8: Dialogue
block = qdoc.document.findBlockByNumber(8)
assert block.text() == "With \u201cdialog\u201d text"
cFmt = charFmtInBlock(block, 1)
assert cFmt.foreground() == THEME.text
cFmt = charFmtInBlock(block, 6)
assert cFmt.foreground() == THEME.dialog
cFmt = charFmtInBlock(block, 14)
assert cFmt.foreground() == THEME.text
# 9: Alt. Dialogue
block = qdoc.document.findBlockByNumber(9)
assert block.text() == "With |<alternative dialog>| text"
cFmt = charFmtInBlock(block, 1)
assert cFmt.foreground() == THEME.text
cFmt = charFmtInBlock(block, 6)
assert cFmt.foreground() == THEME.altdialog
cFmt = charFmtInBlock(block, 28)
assert cFmt.foreground() == THEME.text
@pytest.mark.core
def testCoreToQTextDocument_Footnotes(mockGUI):
"""Test footnotes in the ToQTextDocument class."""
project = NWProject()
qdoc = ToQTextDocument(project)
qdoc.initDocument(CONFIG.textFont, THEME)
qdoc._isNovel = True
qdoc._isFirst = True
qdoc._text = (
"### Scene\n\n"
"Text with valid[footnote:fn1] and invalid[footnote:fn2] footnotes.\n\n"
"%Footnote.fn1: Here's the first note.\n\n"
)
qdoc.tokenizeText()
qdoc.doConvert()
qdoc.appendFootnotes()
assert qdoc.document.blockCount() == 4
# 0: Scene
block = qdoc.document.findBlockByNumber(0)
assert block.text() == "Scene"
# 1: Text
block = qdoc.document.findBlockByNumber(1)
assert block.text() == "Text with valid[1] and invalid[ERR] footnotes."
# 2: Footnotes
block = qdoc.document.findBlockByNumber(2)
assert block.text() == "Footnotes"
# 3: Footnote 1
block = qdoc.document.findBlockByNumber(3)
assert block.text() == "1. Here's the first note."