Files
novelWriter/tests/test_formats/test_fmt_tohtml.py
T
Veronica Berglyd Olsen 5bdbd7c195 Update linting for tests
2025-08-27 21:04:32 +02:00

852 lines
25 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
novelWriter ToHtml Class Tester
=================================
This file is a part of novelWriter
Copyright (C) 2020 Veronica Berglyd Olsen and novelWriter contributors
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/>.
""" # noqa
from __future__ import annotations
import json
import pytest
from novelwriter import CONFIG
from novelwriter.constants import nwHeadFmt
from novelwriter.core.project import NWProject
from novelwriter.enum import nwComment
from novelwriter.formats.shared import BlockFmt, BlockTyp
from novelwriter.formats.tohtml import ToHtml
@pytest.mark.core
def testFmtToHtml_ConvertHeaders(mockGUI):
"""Test header formats in the ToHtml class."""
project = NWProject()
html = ToHtml(project)
html.initDocument()
# Novel Files Headers
# ===================
html._isNovel = True
html._isFirst = True
# Header 1
html._text = "# Title\n"
html.setPartitionFormat(f"Part{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<h1 class='title' style='text-align: center;'>Part<br>Title</h1>\n"
)
# Header 2
html._text = "## Title\n"
html.setChapterFormat(f"Chapter {nwHeadFmt.CH_NUM}{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<h1 style='page-break-before: always;'>Chapter 1<br>Title</h1>\n"
)
# Header 3
html._text = "### Title\n"
html.setSceneFormat(f"Scene {nwHeadFmt.SC_ABS}{nwHeadFmt.BR}{nwHeadFmt.TITLE}")
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == "<h2>Scene 1<br>Title</h2>\n"
# Header 4
html._text = "#### Title\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == "<h3>Title</h3>\n"
# Title
html._text = "#! Title\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<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._pages[-1] == "<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._pages[-1] == "<h1><a name='0000000000000:T0001'></a>Heading One</h1>\n"
# Header 2
html._text = "## Heading Two\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == "<h2><a name='0000000000000:T0001'></a>Heading Two</h2>\n"
# Header 3
html._text = "### Heading Three\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == "<h3><a name='0000000000000:T0001'></a>Heading Three</h3>\n"
# Header 4
html._text = "#### Heading Four\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == "<h4><a name='0000000000000:T0001'></a>Heading Four</h4>\n"
# Title
html._text = "#! Heading One\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<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._pages[-1] == "<h2><a name='0000000000000:T0001'></a>Heading Two</h2>\n"
@pytest.mark.core
def testFmtToHtml_ConvertParagraphs(mockGUI):
"""Test paragraph formats in the ToHtml class."""
project = NWProject()
html = ToHtml(project)
html.initDocument()
html._isNovel = True
html._isFirst = True
# Text
html._text = "Some **nested bold and _italic_ and ~~strikethrough~~ text** here\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<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._pages[-1] == (
"<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._pages[-1] == (
"<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._pages[-1] == ""
html.setCommentType(nwComment.SYNOPSIS, True)
html._text = "%synopsis: The synopsis ...\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<p class='comment'>"
"<strong><span style='color: #813709'>Synopsis:</span></strong> "
"<span style='color: #813709'>The synopsis ...</span>"
"</p>\n"
)
html.setCommentType(nwComment.SHORT, True)
html._text = "%short: A short description ...\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<p class='comment'>"
"<strong><span style='color: #813709'>Short Description:</span></strong> "
"<span style='color: #813709'>A short description ...</span>"
"</p>\n"
)
# Comment
html._text = "% A comment ...\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == ""
html.setCommentType(nwComment.PLAIN, True)
html._text = "% A comment ...\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<p class='comment'>"
"<strong><span style='color: #646464'>Comment:</span></strong> "
"<span style='color: #646464'>A comment ...</span>"
"</p>\n"
)
@pytest.mark.core
def testFmtToHtml_ConvertMeta(mockGUI):
"""Test meta data formats in the ToHtml class."""
project = NWProject()
html = ToHtml(project)
html.initDocument()
html._isNovel = True
html._isFirst = True
# Keywords Disabled
html.setKeywords(False)
html._text = "@char: Bod, Jane\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == ""
# Keywords Enabled
html.setKeywords(True)
html._text = "@char: Bod, Jane\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<p class='meta meta-char'><strong><span style='color: #f5871f'>"
"Characters:</span></strong> "
"<span style='color: #4271ae'><a href='#tag_bod'>Bod</a></span>, "
"<span style='color: #4271ae'><a href='#tag_jane'>Jane</a></span></p>\n"
)
# Tags w/Colour
html.setStyles(True)
html._text = "@tag: Bod\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<p class='meta meta-tag'><strong><span style='color: #f5871f'>Tag:</span></strong> "
"<span style='color: #4271ae'><a name='tag_bod'>Bod</a></span></p>\n"
)
html._text = "@tag: Bod | Nobody Owens\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<p class='meta meta-tag'><strong><span style='color: #f5871f'>Tag:</span></strong> "
"<span style='color: #4271ae'><a name='tag_bod'>Bod</a></span> | "
"<span style='color: #4271ae'>Nobody Owens</span></p>\n"
)
# Tags wo/Colour
html.setStyles(False)
html._text = "@tag: Bod\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<p class='meta meta-tag'><strong>Tag:</strong> <a name='tag_bod'>Bod</a></p>\n"
)
html._text = "@tag: Bod | Nobody Owens\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<p class='meta meta-tag'><strong>Tag:</strong> "
"<a name='tag_bod'>Bod</a> | Nobody Owens</p>\n"
)
# Multiple Keywords w/Colour
html.setStyles(True)
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._pages[-1] == (
"<h1 style='page-break-before: always;'>Chapter</h1>\n"
"<p class='meta meta-pov' style='margin-bottom: 0;'>"
"<strong><span style='color: #f5871f'>Point of View:</span></strong> "
"<span style='color: #4271ae'><a href='#tag_bod'>Bod</a></span></p>\n"
"<p class='meta meta-plot' style='margin-bottom: 0; margin-top: 0;'>"
"<strong><span style='color: #f5871f'>Plot:</span></strong> "
"<span style='color: #4271ae'><a href='#tag_main'>Main</a></span></p>\n"
"<p class='meta meta-location' style='margin-top: 0;'>"
"<strong><span style='color: #f5871f'>Locations:</span></strong> "
"<span style='color: #4271ae'><a href='#tag_europe'>Europe</a></span></p>\n"
)
# Multiple Keywords wo/Colour
html.setStyles(False)
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._pages[-1] == (
"<h1 style='page-break-before: always;'>Chapter</h1>\n"
"<p class='meta meta-pov' style='margin-bottom: 0;'>"
"<strong>Point of View:</strong> <a href='#tag_bod'>Bod</a></p>\n"
"<p class='meta meta-plot' style='margin-bottom: 0; margin-top: 0;'>"
"<strong>Plot:</strong> <a href='#tag_main'>Main</a></p>\n"
"<p class='meta meta-location' style='margin-top: 0;'>"
"<strong>Locations:</strong> <a href='#tag_europe'>Europe</a></p>\n"
)
@pytest.mark.core
def testFmtToHtml_Alignment(mockGUI):
"""Test paragraph alignment in the ToHtml class."""
project = NWProject()
html = ToHtml(project)
html.initDocument()
# Left
html._text = "This is text <<\nspanning multiple\nlines"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<p style='text-align: left;'>This is text<br>spanning multiple<br>lines</p>\n"
)
# Right
html._text = ">> This is text\nspanning multiple\nlines"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<p style='text-align: right;'>This is text<br>spanning multiple<br>lines</p>\n"
)
# Centre
html._text = ">> This is text <<\nspanning multiple\nlines"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<p style='text-align: center;'>This is text<br>spanning multiple<br>lines</p>\n"
)
# Left before Right
html._text = ">> This is text\nspanning multiple <<\nlines"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<p style='text-align: left;'>This is text<br>spanning multiple<br>lines</p>\n"
)
# Right before Centre
html._text = ">> This is text <<\n>> spanning multiple\nlines"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<p style='text-align: right;'>This is text<br>spanning multiple<br>lines</p>\n"
)
@pytest.mark.core
def testFmtToHtml_Dialog(mockGUI):
"""Test paragraph formats in the ToHtml class."""
CONFIG.altDialogOpen = "::"
CONFIG.altDialogClose = "::"
project = NWProject()
html = ToHtml(project)
html.initDocument()
html.setDialogHighlight(True)
html._isNovel = True
html._isFirst = True
# Dialog
html.setDialogHighlight(True)
html._text = "## Chapter\n\nThis text \u201chas dialogue\u201d in it.\n\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<h1>Chapter</h1>\n"
"<p>This text <span style='color: #4271ae'>“has dialogue”</span> in it.</p>\n"
)
# Alt Dialog
html._text = "## Chapter\n\nThis text ::has alt dialogue:: in it.\n\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<h1 style='page-break-before: always;'>Chapter</h1>\n"
"<p>This text <span style='color: #813709'>::has alt dialogue::</span> in it.</p>\n"
)
@pytest.mark.core
def testFmtToHtml_Footnotes(mockGUI):
"""Test paragraph formats in the ToHtml class."""
project = NWProject()
html = ToHtml(project)
html.initDocument()
html._isNovel = True
html._isFirst = True
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._pages[-1] == (
"<p>Text with one<sup><a href='#footnote_1'>1</a></sup> "
"or two<sup>ERR</sup> footnotes.</p>\n"
)
html.closeDocument()
assert html._pages[-2] == (
"<p>Text with one<sup><a href='#footnote_1'>1</a></sup> "
"or two<sup>ERR</sup> footnotes.</p>\n"
)
assert html._pages[-1] == (
"<h3>Footnotes</h3>\n"
"<ol>\n"
"<li id='footnote_1'><p>Footnote text A.</p></li>\n"
"</ol>\n"
)
@pytest.mark.core
def testFmtToHtml_CloseTags(mockGUI):
"""Test automatic closing of HTML tags for shortcodes."""
project = NWProject()
html = ToHtml(project)
html.initDocument()
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._pages[-1] == (
"<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._pages[-1] == (
"<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._pages[-1] == (
"<p>Text text text text.</p>\n"
)
@pytest.mark.core
def testFmtToHtml_ConvertDirect(mockGUI):
"""Test the converter directly using the ToHtml class."""
project = NWProject()
html = ToHtml(project)
html.initDocument()
html._isNovel = True
html._handle = "0000000000000"
html.setLinkHeadings(True)
tMeta = "0000000000000:T0001"
# Special Titles
# ==============
# Title
html._blocks = [
(BlockTyp.TITLE, tMeta, "A Title", [], BlockFmt.PBB | BlockFmt.CENTRE),
]
html.doConvert()
assert html._pages[-1] == (
"<h1 class='title' style='text-align: center; page-break-before: always;'>"
"<a name='0000000000000:T0001'></a>A Title</h1>\n"
)
# Unnumbered
html._blocks = [
(BlockTyp.HEAD1, tMeta, "Prologue", [], BlockFmt.PBB),
]
html.doConvert()
assert html._pages[-1] == (
"<h1 style='page-break-before: always;'>"
"<a name='0000000000000:T0001'></a>Prologue</h1>\n"
)
# Separators
# ==========
# Separator
html._blocks = [
(BlockTyp.SEP, tMeta, "* * *", [], BlockFmt.CENTRE),
]
html.doConvert()
assert html._pages[-1] == "<p class='sep' style='text-align: center;'>* * *</p>\n"
# Skip
html._blocks = [
(BlockTyp.SKIP, tMeta, "", [], BlockFmt.NONE),
]
html.doConvert()
assert html._pages[-1] == "<p>&nbsp;</p>\n"
# Alignment
# =========
html.setLinkHeadings(False)
html.setStyles(True)
# Align Left
html._blocks = [
(BlockTyp.PART, tMeta, "A Title", [], BlockFmt.LEFT),
]
html.doConvert()
assert html._pages[-1] == (
"<h1 class='title' style='text-align: left;'>A Title</h1>\n"
)
# Align Right
html._blocks = [
(BlockTyp.PART, tMeta, "A Title", [], BlockFmt.RIGHT),
]
html.doConvert()
assert html._pages[-1] == (
"<h1 class='title' style='text-align: right;'>A Title</h1>\n"
)
# Align Centre
html._blocks = [
(BlockTyp.PART, tMeta, "A Title", [], BlockFmt.CENTRE),
]
html.doConvert()
assert html._pages[-1] == (
"<h1 class='title' style='text-align: center;'>A Title</h1>\n"
)
# Align Justify
html._blocks = [
(BlockTyp.PART, tMeta, "A Title", [], BlockFmt.JUSTIFY),
]
html.doConvert()
assert html._pages[-1] == (
"<h1 class='title' style='text-align: justify;'>A Title</h1>\n"
)
# Page Break
# ==========
# Page Break Always
html._blocks = [
(BlockTyp.PART, tMeta, "A Title", [], BlockFmt.PBB | BlockFmt.PBA),
]
html.doConvert()
assert html._pages[-1] == (
"<h1 class='title' "
"style='page-break-before: always; page-break-after: always;'>A Title</h1>\n"
)
# Indent
# ======
# Indent Left
html._blocks = [
(BlockTyp.TEXT, tMeta, "Some text ...", [], BlockFmt.IND_L),
]
html.doConvert()
assert html._pages[-1] == (
"<p style='margin-left: 4.00em;'>Some text ...</p>\n"
)
# Indent Right
html._blocks = [
(BlockTyp.TEXT, tMeta, "Some text ...", [], BlockFmt.IND_R),
]
html.doConvert()
assert html._pages[-1] == (
"<p style='margin-right: 4.00em;'>Some text ...</p>\n"
)
# Text Indent
html._blocks = [
(BlockTyp.TEXT, tMeta, "Some text ...", [], BlockFmt.IND_T),
]
html.doConvert()
assert html._pages[-1] == (
"<p style='text-indent: 1.40em;'>Some text ...</p>\n"
)
@pytest.mark.core
def testFmtToHtml_SpecialCases(mockGUI):
"""Test some special cases that have caused errors in the past."""
project = NWProject()
html = ToHtml(project)
html.initDocument()
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._pages[-1] == (
"<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._pages[-1] == (
"<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._pages[-1] == (
"<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._pages[-1] == (
"<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.setCommentType(nwComment.PLAIN, True)
html._text = "% Test > text _<**bold**>_ and more.\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<p class='comment'>"
"<strong><span style='color: #646464'>Comment:</span></strong> "
"<span style='color: #646464'>Test &gt; text <em>&lt;<strong>bold</strong>&gt;</em> "
"and more.</span>"
"</p>\n"
)
html._isFirst = False
html._text = "## Heading <1>\n"
html.tokenizeText()
html.doConvert()
assert html._pages[-1] == (
"<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._pages[-1] == (
"<p>Test text **<em>bold</em>** and more.</p>\n"
)
@pytest.mark.core
def testFmtToHtml_Save(mockGUI, fncPath):
"""Test the save method of the ToHtml class."""
project = NWProject()
html = ToHtml(project)
html.initDocument()
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._pages == 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
# ===========
hStyle = html.getStyleSheet()
# HTML w/Styles
html.setStyles(True)
htmlDocCSS = (
"<!DOCTYPE html>\n"
"<html>\n"
"<head>\n"
"<title></title>\n"
"<meta charset='utf-8'>\n"
"<meta name='viewport' content='width=device-width, initial-scale=1'>\n"
"<style>\n"
"{style}\n"
"</style>\n"
"</head>\n"
"<body>\n"
"{body}\n"
"</body>\n"
"</html>\n"
).format(
style="\n".join(hStyle),
body="".join(resText).rstrip()
)
saveFile = fncPath / "outFile.htm"
html.saveDocument(saveFile)
assert saveFile.read_text(encoding="utf-8") == htmlDocCSS
# HTML wo/Styles
html.setStyles(False)
htmlDocCSS = (
"<!DOCTYPE html>\n"
"<html>\n"
"<head>\n"
"<title></title>\n"
"<meta charset='utf-8'>\n"
"</head>\n"
"<body>\n"
"{body}\n"
"</body>\n"
"</html>\n"
).format(
body="".join(resText).rstrip()
)
saveFile = fncPath / "outFile.htm"
html.saveDocument(saveFile)
assert saveFile.read_text(encoding="utf-8") == htmlDocCSS
# JSON + HTML w/Styles
html.setStyles(True)
saveFile = fncPath / "outFile.json"
html.saveDocument(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 testFmtToHtml_Methods(mockGUI):
"""Test all the other methods of the ToHtml class."""
project = NWProject()
html = ToHtml(project)
html.initDocument()
# 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._pages[-1] == (
"<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._pages[-1] == (
"<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.setStyles(False)
assert html.getStyleSheet() == []