New test for ToHtml class
This commit is contained in:
+11
-9
@@ -68,16 +68,16 @@ class ToHtml(Tokenizer):
|
||||
# Setters
|
||||
##
|
||||
|
||||
def setPreview(self, forPreview, doComments, doSynopsis):
|
||||
def setPreview(self, doComments, doSynopsis):
|
||||
"""If we're using this class to generate markdown preview, we
|
||||
need to make a few changes to formatting, which is managed by
|
||||
these flags.
|
||||
"""
|
||||
if forPreview:
|
||||
self.genMode = self.M_PREVIEW
|
||||
self.doKeywords = True
|
||||
self.doComments = doComments
|
||||
self.doSynopsis = doSynopsis
|
||||
self.genMode = self.M_PREVIEW
|
||||
self.doKeywords = True
|
||||
self.doComments = doComments
|
||||
self.doSynopsis = doSynopsis
|
||||
|
||||
return
|
||||
|
||||
def setStyles(self, cssStyles):
|
||||
@@ -141,11 +141,13 @@ class ToHtml(Tokenizer):
|
||||
# For novel files for export, we bump the titles one level
|
||||
# up as this is more useful for printing and word processor
|
||||
# imports.
|
||||
h1 = "h1 class='title'"
|
||||
h1Cl = " class='title'"
|
||||
h1 = "h1"
|
||||
h2 = "h1"
|
||||
h3 = "h2"
|
||||
h4 = "h3"
|
||||
else:
|
||||
h1Cl = ""
|
||||
h1 = "h1"
|
||||
h2 = "h2"
|
||||
h3 = "h3"
|
||||
@@ -193,7 +195,7 @@ class ToHtml(Tokenizer):
|
||||
else:
|
||||
aNm = ""
|
||||
|
||||
# Process TextType
|
||||
# Process Text Type
|
||||
if tType == self.T_EMPTY:
|
||||
if parStyle is None:
|
||||
parStyle = ""
|
||||
@@ -214,7 +216,7 @@ class ToHtml(Tokenizer):
|
||||
|
||||
elif tType == self.T_HEAD1:
|
||||
tHead = tText.replace(r"\\", "<br/>")
|
||||
tmpResult.append("<%s%s>%s%s</%s>\n" % (h1, hStyle, aNm, tHead, h1))
|
||||
tmpResult.append("<%s%s%s>%s%s</%s>\n" % (h1, h1Cl, hStyle, aNm, tHead, h1))
|
||||
|
||||
elif tType == self.T_HEAD2:
|
||||
tHead = tText.replace(r"\\", "<br/>")
|
||||
|
||||
+1
-1
@@ -169,7 +169,7 @@ class GuiDocViewer(QTextBrowser):
|
||||
|
||||
sPos = self.verticalScrollBar().value()
|
||||
aDoc = ToHtml(self.theProject, self.theParent)
|
||||
aDoc.setPreview(True, self.mainConf.viewComments, self.mainConf.viewSynopsis)
|
||||
aDoc.setPreview(self.mainConf.viewComments, self.mainConf.viewSynopsis)
|
||||
aDoc.setLinkHeaders(True)
|
||||
|
||||
# Be extra careful here to prevent crashes when first opening a
|
||||
|
||||
+4
-4
@@ -81,14 +81,14 @@ class GuiMain(QMainWindow):
|
||||
# Core Classes
|
||||
# ============
|
||||
|
||||
# Core Classes and settings
|
||||
# Core Classes and Settings
|
||||
self.theTheme = GuiTheme(self)
|
||||
self.theProject = NWProject(self)
|
||||
self.theIndex = NWIndex(self.theProject, self)
|
||||
self.hasProject = False
|
||||
self.isFocusMode = False
|
||||
|
||||
# Prepare main window
|
||||
# Prepare Main Window
|
||||
self.resize(*self.mainConf.getWinSize())
|
||||
self._setWindowTitle()
|
||||
self.setWindowIcon(QIcon(self.mainConf.appIcon))
|
||||
@@ -1073,10 +1073,10 @@ class GuiMain(QMainWindow):
|
||||
|
||||
self.isFocusMode = not self.isFocusMode
|
||||
if self.isFocusMode:
|
||||
logger.debug("Activating Focus mode")
|
||||
logger.debug("Activating Focus Mode")
|
||||
self.tabWidget.setCurrentWidget(self.splitDocs)
|
||||
else:
|
||||
logger.debug("Deactivating Focus mode")
|
||||
logger.debug("Deactivating Focus Mode")
|
||||
|
||||
isVisible = not self.isFocusMode
|
||||
self.treePane.setVisible(isVisible)
|
||||
|
||||
@@ -11,6 +11,8 @@ class DummyMain():
|
||||
def __init__(self):
|
||||
self.mainConf = None
|
||||
self.hasProject = True
|
||||
self.theIndex = None
|
||||
self.theProject = None
|
||||
self.statusBar = StatusBar()
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,373 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""novelWriter ToHtml Class Tester
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from nw.core import NWProject, NWIndex, ToHtml
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreToHtml_Format(dummyGUI):
|
||||
"""Test all the formatters for the ToHtml class.
|
||||
"""
|
||||
theProject = NWProject(dummyGUI)
|
||||
dummyGUI.theIndex = NWIndex(theProject, dummyGUI)
|
||||
theHtml = ToHtml(theProject, dummyGUI)
|
||||
|
||||
# Export Mode
|
||||
# ===========
|
||||
|
||||
assert theHtml._formatSynopsis("synopsis text") == (
|
||||
"<p class='synopsis'><strong>Synopsis: </strong>synopsis text</p>\n"
|
||||
)
|
||||
assert theHtml._formatComments("comment text") == (
|
||||
"<p class='comment'><strong>Comment: </strong>comment text</p>\n"
|
||||
)
|
||||
|
||||
assert theHtml._formatKeywords("") == ""
|
||||
assert theHtml._formatKeywords("tag: Jane") == (
|
||||
"<div><span class='tags'>Tag:</span> <a name='tag_Jane'>Jane</a></div>"
|
||||
)
|
||||
assert theHtml._formatKeywords("char: Bod, Jane") == (
|
||||
"<div>"
|
||||
"<span class='tags'>Characters:</span> "
|
||||
"<a href='#tag_Bod'>Bod</a>, "
|
||||
"<a href='#tag_Jane'>Jane</a>"
|
||||
"</div>"
|
||||
)
|
||||
|
||||
# Preview Mode
|
||||
# ============
|
||||
|
||||
theHtml.setPreview(True, True)
|
||||
|
||||
assert theHtml._formatSynopsis("synopsis text") == (
|
||||
"<p class='comment'><span class='synopsis'>Synopsis: </span>synopsis text</p>\n"
|
||||
)
|
||||
assert theHtml._formatComments("comment text") == (
|
||||
"<p class='comment'>comment text</p>\n"
|
||||
)
|
||||
|
||||
assert theHtml._formatKeywords("") == ""
|
||||
assert theHtml._formatKeywords("tag: Jane") == (
|
||||
"<div><span class='tags'>Tag:</span> <a name='tag_Jane'>Jane</a></div>"
|
||||
)
|
||||
assert theHtml._formatKeywords("char: Bod, Jane") == (
|
||||
"<div>"
|
||||
"<span class='tags'>Characters:</span> "
|
||||
"<a href='#char=Bod'>Bod</a>, "
|
||||
"<a href='#char=Jane'>Jane</a>"
|
||||
"</div>"
|
||||
)
|
||||
|
||||
# END Test testCoreToHtml_Format
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreToHtml_Convert(dummyGUI):
|
||||
"""Test the converter of the ToHtml class.
|
||||
"""
|
||||
theProject = NWProject(dummyGUI)
|
||||
dummyGUI.theIndex = NWIndex(theProject, dummyGUI)
|
||||
theHtml = ToHtml(theProject, dummyGUI)
|
||||
|
||||
# Export Mode
|
||||
# ===========
|
||||
|
||||
theHtml.isNovel = True
|
||||
|
||||
# Header 1
|
||||
theHtml.theText = "# Title\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<h1 class='title'>Title</h1>\n"
|
||||
|
||||
# Header 2
|
||||
theHtml.theText = "## Chapter Title\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<h1>Chapter Title</h1>\n"
|
||||
|
||||
# Header 3
|
||||
theHtml.theText = "### Scene Title\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<h2>Scene Title</h2>\n"
|
||||
|
||||
# Header 4
|
||||
theHtml.theText = "#### Section Title\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<h3>Section Title</h3>\n"
|
||||
|
||||
theHtml.isNovel = False
|
||||
theHtml.setLinkHeaders(True)
|
||||
|
||||
# Header 1
|
||||
theHtml.theText = "# Heading One\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<h1><a name='T000001'></a>Heading One</h1>\n"
|
||||
|
||||
# Header 2
|
||||
theHtml.theText = "## Heading Two\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<h2><a name='T000001'></a>Heading Two</h2>\n"
|
||||
|
||||
# Header 3
|
||||
theHtml.theText = "### Heading Three\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<h3><a name='T000001'></a>Heading Three</h3>\n"
|
||||
|
||||
# Header 4
|
||||
theHtml.theText = "#### Heading Four\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<h4><a name='T000001'></a>Heading Four</h4>\n"
|
||||
|
||||
# Text
|
||||
theHtml.theText = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<p>Some <strong>nested bold and <em>italic</em> and "
|
||||
"<del>strikethrough</del> text</strong> here</p>\n"
|
||||
)
|
||||
|
||||
# Text w/Hard Break
|
||||
theHtml.theText = "Line one \nLine two \nLine three\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<p class='break'>Line one<br/>Line two<br/>Line three</p>\n"
|
||||
)
|
||||
|
||||
# Synopsis
|
||||
theHtml.theText = "%synopsis: The synopsis ...\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == ""
|
||||
|
||||
theHtml.setSynopsis(True)
|
||||
theHtml.theText = "%synopsis: The synopsis ...\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<p class='synopsis'><strong>Synopsis: </strong>The synopsis ...</p>\n"
|
||||
)
|
||||
|
||||
# Comment
|
||||
theHtml.theText = "% A comment ...\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == ""
|
||||
|
||||
theHtml.setComments(True)
|
||||
theHtml.theText = "% A comment ...\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<p class='comment'><strong>Comment: </strong>A comment ...</p>\n"
|
||||
)
|
||||
|
||||
# Keywords
|
||||
theHtml.theText = "@char: Bod, Jane\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == ""
|
||||
|
||||
theHtml.setKeywords(True)
|
||||
theHtml.theText = "@char: Bod, Jane\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<div><span class='tags'>Characters:</span> "
|
||||
"<a href='#tag_Bod'>Bod</a>, <a href='#tag_Jane'>Jane</a></div>"
|
||||
)
|
||||
|
||||
# Direct Tests
|
||||
# ============
|
||||
|
||||
theHtml.isNovel = True
|
||||
|
||||
# Title
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_TITLE, 1, "A Title", None, theHtml.A_PBB_NO | theHtml.A_CENTRE),
|
||||
(theHtml.T_EMPTY, 1, "", None, theHtml.A_NONE),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<h1 class='title' style='text-align: center; page-break-before: never;'>"
|
||||
"<a name='T000001'></a>A Title</h1>\n"
|
||||
)
|
||||
|
||||
# Separator
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_SEP, 1, "* * *", None, theHtml.A_CENTRE),
|
||||
(theHtml.T_EMPTY, 1, "", None, theHtml.A_NONE),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<p class='sep'>* * *</p>\n"
|
||||
|
||||
# Skip
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_SKIP, 1, "", None, theHtml.A_NONE),
|
||||
(theHtml.T_EMPTY, 1, "", None, theHtml.A_NONE),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == "<p class='skip'> </p>\n"
|
||||
|
||||
# Styles
|
||||
# ======
|
||||
|
||||
theHtml.setLinkHeaders(False)
|
||||
|
||||
# Align Left
|
||||
theHtml.setStyles(False)
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_LEFT),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<h1 class='title'>A Title</h1>\n"
|
||||
)
|
||||
|
||||
theHtml.setStyles(True)
|
||||
|
||||
# Align Left
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_LEFT),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<h1 class='title' style='text-align: left;'>A Title</h1>\n"
|
||||
)
|
||||
|
||||
# Align Right
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_RIGHT),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<h1 class='title' style='text-align: right;'>A Title</h1>\n"
|
||||
)
|
||||
|
||||
# Align Centre
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_CENTRE),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<h1 class='title' style='text-align: center;'>A Title</h1>\n"
|
||||
)
|
||||
|
||||
# Align Justify
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_JUSTIFY),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<h1 class='title' style='text-align: justify;'>A Title</h1>\n"
|
||||
)
|
||||
|
||||
# Page Break Always
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_PBB | theHtml.A_PBA),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<h1 class='title' "
|
||||
"style='page-break-before: always; page-break-after: always;'>A Title</h1>\n"
|
||||
)
|
||||
|
||||
# Page Break Avoid
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_PBB_AV | theHtml.A_PBA_AV),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<h1 class='title' "
|
||||
"style='page-break-before: avoid; page-break-after: avoid;'>A Title</h1>\n"
|
||||
)
|
||||
|
||||
# Page Break ANever
|
||||
theHtml.theTokens = [
|
||||
(theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_PBB_NO | theHtml.A_PBA_NO),
|
||||
]
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<h1 class='title' "
|
||||
"style='page-break-before: never; page-break-after: never;'>A Title</h1>\n"
|
||||
)
|
||||
|
||||
# Preview Mode
|
||||
# ============
|
||||
|
||||
theHtml.setPreview(True, True)
|
||||
|
||||
# Text (HTML4)
|
||||
theHtml.theText = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<p>Some <b>nested bold and <i>italic</i> and "
|
||||
"<span style='text-decoration: line-through;'>strikethrough</span> "
|
||||
"text</b> here</p>\n"
|
||||
)
|
||||
|
||||
# END Test testCoreToHtml_Convert
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreToHtml_Methods(dummyGUI):
|
||||
"""Test all the other methods of the ToHtml class.
|
||||
"""
|
||||
theProject = NWProject(dummyGUI)
|
||||
theHtml = ToHtml(theProject, dummyGUI)
|
||||
|
||||
# Auto-Replace
|
||||
docText = "Text with <brackets> & short–dash, long—dash …\n"
|
||||
theHtml.theText = docText
|
||||
theHtml.doAutoReplace()
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theResult == (
|
||||
"<p>Text with <brackets> & short–dash, long—dash …</p>\n"
|
||||
)
|
||||
|
||||
# Revert on MD
|
||||
assert theHtml.theMarkdown == (
|
||||
"Text with <brackets> & short–dash, long—dash …\n\n"
|
||||
)
|
||||
theHtml.doPostProcessing()
|
||||
assert theHtml.theMarkdown == docText + "\n"
|
||||
|
||||
# With Preview, No Revert
|
||||
theHtml.setPreview(True, True)
|
||||
theHtml.theText = docText
|
||||
theHtml.doAutoReplace()
|
||||
theHtml.tokenizeText()
|
||||
theHtml.doConvert()
|
||||
assert theHtml.theMarkdown == (
|
||||
"Text with <brackets> & short–dash, long—dash …\n\n"
|
||||
)
|
||||
theHtml.doPostProcessing()
|
||||
assert theHtml.theMarkdown == (
|
||||
"Text with <brackets> & short–dash, long—dash …\n\n"
|
||||
)
|
||||
|
||||
# CSS
|
||||
# ===
|
||||
|
||||
assert len(theHtml.getStyleSheet()) > 1
|
||||
assert "p {text-align: left;}" in theHtml.getStyleSheet()
|
||||
assert "p {text-align: justify;}" not in theHtml.getStyleSheet()
|
||||
|
||||
theHtml.setJustify(True)
|
||||
assert "p {text-align: left;}" not in theHtml.getStyleSheet()
|
||||
assert "p {text-align: justify;}" in theHtml.getStyleSheet()
|
||||
|
||||
theHtml.setStyles(False)
|
||||
assert theHtml.getStyleSheet() == []
|
||||
|
||||
# END Test testCoreToHtml_Methods
|
||||
@@ -12,7 +12,7 @@ def testCoreToken_Setters(dummyGUI):
|
||||
"""Test all the setters for the Tokenizer class.
|
||||
"""
|
||||
theProject = NWProject(dummyGUI)
|
||||
theToken = Tokenizer(dummyGUI, theProject)
|
||||
theToken = Tokenizer(theProject, dummyGUI)
|
||||
|
||||
# Verify defaults
|
||||
assert theToken.fmtTitle == "%title%"
|
||||
@@ -600,7 +600,6 @@ def testCoreToken_Headers(dummyGUI):
|
||||
|
||||
# H1: Title
|
||||
theToken.theText = "# Novel Title\n"
|
||||
theToken.setTitleFormat(r"T: %title%")
|
||||
theToken.tokenizeText()
|
||||
theToken.isTitle = True
|
||||
theToken.isPart = False
|
||||
|
||||
Reference in New Issue
Block a user