Add more formatting options for manuscript builds (#1723)
This commit is contained in:
@@ -59,10 +59,17 @@ SETTINGS_TEMPLATE = {
|
||||
"headings.fmtSection": (str, ""),
|
||||
"headings.hideScene": (bool, False),
|
||||
"headings.hideSection": (bool, True),
|
||||
"headings.centerTitle": (bool, True),
|
||||
"headings.centerChapter": (bool, False),
|
||||
"headings.centerScene": (bool, False),
|
||||
"headings.breakTitle": (bool, True),
|
||||
"headings.breakChapter": (bool, True),
|
||||
"headings.breakScene": (bool, False),
|
||||
"text.includeSynopsis": (bool, False),
|
||||
"text.includeComments": (bool, False),
|
||||
"text.includeKeywords": (bool, False),
|
||||
"text.includeBodyText": (bool, True),
|
||||
"text.ignoredKeywords": (str, ""),
|
||||
"text.addNoteHeadings": (bool, True),
|
||||
"format.textFont": (str, CONFIG.textFont),
|
||||
"format.textSize": (int, 12),
|
||||
@@ -81,7 +88,9 @@ SETTINGS_TEMPLATE = {
|
||||
"odt.addColours": (bool, True),
|
||||
"odt.pageHeader": (str, nwHeadFmt.ODT_AUTO),
|
||||
"odt.pageCountOffset": (int, 0),
|
||||
"md.preserveBreaks": (bool, True),
|
||||
"html.addStyles": (bool, True),
|
||||
"html.preserveTabs": (bool, False),
|
||||
}
|
||||
|
||||
SETTINGS_LABELS = {
|
||||
@@ -104,6 +113,7 @@ SETTINGS_LABELS = {
|
||||
"text.includeComments": QT_TRANSLATE_NOOP("Builds", "Include Comments"),
|
||||
"text.includeKeywords": QT_TRANSLATE_NOOP("Builds", "Include Keywords"),
|
||||
"text.includeBodyText": QT_TRANSLATE_NOOP("Builds", "Include Body Text"),
|
||||
"text.ignoredKeywords": QT_TRANSLATE_NOOP("Builds", "Ignore These Keywords"),
|
||||
"text.grpInsert": QT_TRANSLATE_NOOP("Builds", "Insert Content"),
|
||||
"text.addNoteHeadings": QT_TRANSLATE_NOOP("Builds", "Add Titles for Notes"),
|
||||
|
||||
@@ -130,8 +140,12 @@ SETTINGS_LABELS = {
|
||||
"odt.pageHeader": QT_TRANSLATE_NOOP("Builds", "Page Header"),
|
||||
"odt.pageCountOffset": QT_TRANSLATE_NOOP("Builds", "Page Counter Offset"),
|
||||
|
||||
"md": QT_TRANSLATE_NOOP("Builds", "Markdown (.md)"),
|
||||
"md.preserveBreaks": QT_TRANSLATE_NOOP("Builds", "Preserve Hard Line Breaks"),
|
||||
|
||||
"html": QT_TRANSLATE_NOOP("Builds", "HTML (.html)"),
|
||||
"html.addStyles": QT_TRANSLATE_NOOP("Builds", "Add CSS Styles"),
|
||||
"html.preserveTabs": QT_TRANSLATE_NOOP("Builds", "Preserve Tab Characters"),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -52,15 +52,16 @@ class NWBuildDocument:
|
||||
manuscript, based on a build definition object (BuildSettings).
|
||||
"""
|
||||
|
||||
__slots__ = ("_project", "_build", "_queue", "_error", "_cache", "_count")
|
||||
__slots__ = ("_project", "_build", "_queue", "_error", "_cache", "_count", "_preview")
|
||||
|
||||
def __init__(self, project: NWProject, build: BuildSettings, doCount: bool = False) -> None:
|
||||
def __init__(self, project: NWProject, build: BuildSettings) -> None:
|
||||
self._project = project
|
||||
self._build = build
|
||||
self._queue = []
|
||||
self._error = None
|
||||
self._cache = None
|
||||
self._count = doCount
|
||||
self._count = False
|
||||
self._preview = False
|
||||
return
|
||||
|
||||
##
|
||||
@@ -80,6 +81,21 @@ class NWBuildDocument:
|
||||
"""
|
||||
return self._cache
|
||||
|
||||
##
|
||||
# Setters
|
||||
##
|
||||
|
||||
def setCountEnabled(self, state: bool) -> None:
|
||||
"""Turn on/off stats counting for builds."""
|
||||
self._count = state
|
||||
return
|
||||
|
||||
def setPreviewMode(self, state: bool) -> None:
|
||||
"""Set the preview mode of the build. Implies count mode."""
|
||||
self._preview = state
|
||||
self._count = state
|
||||
return
|
||||
|
||||
##
|
||||
# Special Methods
|
||||
##
|
||||
@@ -161,7 +177,7 @@ class NWBuildDocument:
|
||||
else:
|
||||
yield i, False
|
||||
|
||||
if self._build.getBool("format.replaceTabs"):
|
||||
if not (self._build.getBool("html.preserveTabs") or self._preview):
|
||||
makeObj.replaceTabs()
|
||||
|
||||
self._error = None
|
||||
@@ -192,6 +208,8 @@ class NWBuildDocument:
|
||||
if self._build.getBool("format.replaceTabs"):
|
||||
makeObj.replaceTabs(nSpaces=4, spaceChar=" ")
|
||||
|
||||
makeObj.setPreserveBreaks(self._build.getBool("md.preserveBreaks"))
|
||||
|
||||
for i, tHandle in enumerate(self._queue):
|
||||
self._error = None
|
||||
if filtered.get(tHandle, (False, 0))[0]:
|
||||
@@ -268,15 +286,28 @@ class NWBuildDocument:
|
||||
self._build.getStr("headings.fmtSection"),
|
||||
self._build.getBool("headings.hideSection")
|
||||
)
|
||||
bldObj.setTitleStyle(
|
||||
self._build.getBool("headings.centerTitle"),
|
||||
self._build.getBool("headings.breakTitle")
|
||||
)
|
||||
bldObj.setChapterStyle(
|
||||
self._build.getBool("headings.centerChapter"),
|
||||
self._build.getBool("headings.breakChapter")
|
||||
)
|
||||
bldObj.setSceneStyle(
|
||||
self._build.getBool("headings.centerScene"),
|
||||
self._build.getBool("headings.breakScene")
|
||||
)
|
||||
|
||||
bldObj.setFont(fontFamily, textSize, textFixed)
|
||||
bldObj.setJustify(self._build.getBool("format.justifyText"))
|
||||
bldObj.setLineHeight(self._build.getFloat("format.lineHeight"))
|
||||
|
||||
bldObj.setBodyText(self._build.getBool("text.includeBodyText"))
|
||||
bldObj.setSynopsis(self._build.getBool("text.includeSynopsis"))
|
||||
bldObj.setComments(self._build.getBool("text.includeComments"))
|
||||
bldObj.setKeywords(self._build.getBool("text.includeKeywords"))
|
||||
bldObj.setBodyText(self._build.getBool("text.includeBodyText"))
|
||||
bldObj.setIgnoredKeywords(self._build.getStr("text.ignoredKeywords"))
|
||||
|
||||
if isinstance(bldObj, ToHtml):
|
||||
bldObj.setStyles(self._build.getBool("html.addStyles"))
|
||||
|
||||
@@ -130,16 +130,17 @@ class Tokenizer(ABC):
|
||||
self._tokens: list[tuple[int, int, str, list[tuple[int, int]], int]] = []
|
||||
|
||||
# User Settings
|
||||
self._textFont = "Serif" # Output text font
|
||||
self._textSize = 11 # Output text size
|
||||
self._textFixed = False # Fixed width text
|
||||
self._lineHeight = 1.15 # Line height in units of em
|
||||
self._blockIndent = 4.00 # Block indent in units of em
|
||||
self._doJustify = False # Justify text
|
||||
self._doBodyText = True # Include body text
|
||||
self._doSynopsis = False # Also process synopsis comments
|
||||
self._doComments = False # Also process comments
|
||||
self._doKeywords = False # Also process keywords like tags and references
|
||||
self._textFont = "Serif" # Output text font
|
||||
self._textSize = 11 # Output text size
|
||||
self._textFixed = False # Fixed width text
|
||||
self._lineHeight = 1.15 # Line height in units of em
|
||||
self._blockIndent = 4.00 # Block indent in units of em
|
||||
self._doJustify = False # Justify text
|
||||
self._doBodyText = True # Include body text
|
||||
self._doSynopsis = False # Also process synopsis comments
|
||||
self._doComments = False # Also process comments
|
||||
self._doKeywords = False # Also process keywords like tags and references
|
||||
self._skipKeywords = set() # Keywords to ignore
|
||||
|
||||
# Margins
|
||||
self._marginTitle = (1.000, 0.500)
|
||||
@@ -162,6 +163,10 @@ class Tokenizer(ABC):
|
||||
|
||||
self._linkHeaders = False # Add an anchor before headers
|
||||
|
||||
self._titleStyle = self.A_CENTRE | self.A_PBB
|
||||
self._chapterStyle = self.A_PBB
|
||||
self._sceneStyle = self.A_NONE
|
||||
|
||||
# Instance Variables
|
||||
self._hFormatter = HeadingFormatter(self._project)
|
||||
self._skipSeparator = False # Flag to indicate that we skip the scene separator
|
||||
@@ -171,6 +176,7 @@ class Tokenizer(ABC):
|
||||
self._isNovel = False # Document is a novel document
|
||||
self._isNote = False # Document is a project note
|
||||
self._isFirst = True # Document is the first in a set
|
||||
self._noBreak = False # Don't allow an initial break when formatting headers
|
||||
|
||||
# Error Handling
|
||||
self._errData = []
|
||||
@@ -255,6 +261,27 @@ class Tokenizer(ABC):
|
||||
self._hideSection = hide
|
||||
return
|
||||
|
||||
def setTitleStyle(self, center: bool, pageBreak: bool) -> None:
|
||||
"""Set the title heading style."""
|
||||
self._titleStyle = (
|
||||
(self.A_CENTRE if center else self.A_NONE) | (self.A_PBB if pageBreak else self.A_NONE)
|
||||
)
|
||||
return
|
||||
|
||||
def setChapterStyle(self, center: bool, pageBreak: bool) -> None:
|
||||
"""Set the chapter heading style."""
|
||||
self._chapterStyle = (
|
||||
(self.A_CENTRE if center else self.A_NONE) | (self.A_PBB if pageBreak else self.A_NONE)
|
||||
)
|
||||
return
|
||||
|
||||
def setSceneStyle(self, center: bool, pageBreak: bool) -> None:
|
||||
"""Set the scene heading style."""
|
||||
self._sceneStyle = (
|
||||
(self.A_CENTRE if center else self.A_NONE) | (self.A_PBB if pageBreak else self.A_NONE)
|
||||
)
|
||||
return
|
||||
|
||||
def setFont(self, family: str, size: int, isFixed: bool = False) -> None:
|
||||
"""Set the build font."""
|
||||
self._textFont = family
|
||||
@@ -337,6 +364,11 @@ class Tokenizer(ABC):
|
||||
self._doKeywords = state
|
||||
return
|
||||
|
||||
def setIgnoredKeywords(self, keywords: str) -> None:
|
||||
"""Comma separated string of keywords to ignore."""
|
||||
self._skipKeywords = set(x.lower().strip() for x in keywords.split(","))
|
||||
return
|
||||
|
||||
def setKeepMarkdown(self, state: bool) -> None:
|
||||
"""Keep original markdown during build."""
|
||||
self._keepMarkdown = state
|
||||
@@ -504,31 +536,26 @@ class Tokenizer(ABC):
|
||||
tmpMarkdown.append("%s\n" % aLine)
|
||||
|
||||
elif aLine[0] == "@":
|
||||
self._tokens.append((
|
||||
self.T_KEYWORD, nHead, aLine[1:].strip(), [], sAlign
|
||||
))
|
||||
if self._doKeywords and self._keepMarkdown:
|
||||
tmpMarkdown.append("%s\n" % aLine)
|
||||
valid, bits, _ = self._project.index.scanThis(aLine)
|
||||
if valid and bits and bits[0] not in self._skipKeywords:
|
||||
self._tokens.append((
|
||||
self.T_KEYWORD, nHead, aLine[1:].strip(), [], sAlign
|
||||
))
|
||||
if self._doKeywords and self._keepMarkdown:
|
||||
tmpMarkdown.append("%s\n" % aLine)
|
||||
|
||||
elif aLine[:2] == "# ":
|
||||
if self._isNovel:
|
||||
sAlign |= self.A_CENTRE
|
||||
sAlign |= self.A_PBB
|
||||
|
||||
nHead += 1
|
||||
self._tokens.append((
|
||||
self.T_HEAD1, nHead, aLine[2:].strip(), [], sAlign
|
||||
self.T_HEAD1, nHead, aLine[2:].strip(), [], self.A_NONE
|
||||
))
|
||||
if self._keepMarkdown:
|
||||
tmpMarkdown.append("%s\n" % aLine)
|
||||
|
||||
elif aLine[:3] == "## ":
|
||||
if self._isNovel:
|
||||
sAlign |= self.A_PBB
|
||||
|
||||
nHead += 1
|
||||
self._tokens.append((
|
||||
self.T_HEAD2, nHead, aLine[3:].strip(), [], sAlign
|
||||
self.T_HEAD2, nHead, aLine[3:].strip(), [], self.A_NONE
|
||||
))
|
||||
if self._keepMarkdown:
|
||||
tmpMarkdown.append("%s\n" % aLine)
|
||||
@@ -536,7 +563,7 @@ class Tokenizer(ABC):
|
||||
elif aLine[:4] == "### ":
|
||||
nHead += 1
|
||||
self._tokens.append((
|
||||
self.T_HEAD3, nHead, aLine[4:].strip(), [], sAlign
|
||||
self.T_HEAD3, nHead, aLine[4:].strip(), [], self.A_NONE
|
||||
))
|
||||
if self._keepMarkdown:
|
||||
tmpMarkdown.append("%s\n" % aLine)
|
||||
@@ -544,34 +571,25 @@ class Tokenizer(ABC):
|
||||
elif aLine[:5] == "#### ":
|
||||
nHead += 1
|
||||
self._tokens.append((
|
||||
self.T_HEAD4, nHead, aLine[5:].strip(), [], sAlign
|
||||
self.T_HEAD4, nHead, aLine[5:].strip(), [], self.A_NONE
|
||||
))
|
||||
if self._keepMarkdown:
|
||||
tmpMarkdown.append("%s\n" % aLine)
|
||||
|
||||
elif aLine[:3] == "#! ":
|
||||
nHead += 1
|
||||
if self._isNovel:
|
||||
tStyle = self.T_TITLE
|
||||
else:
|
||||
tStyle = self.T_HEAD1
|
||||
|
||||
self._tokens.append((
|
||||
tStyle, nHead, aLine[3:].strip(), [], sAlign | self.A_CENTRE
|
||||
self.T_TITLE, nHead, aLine[3:].strip(), [], self.A_PBB | self.A_CENTRE
|
||||
))
|
||||
if self._keepMarkdown:
|
||||
tmpMarkdown.append("%s\n" % aLine)
|
||||
|
||||
elif aLine[:4] == "##! ":
|
||||
nHead += 1
|
||||
if self._isNovel:
|
||||
tStyle = self.T_UNNUM
|
||||
sAlign |= self.A_PBB
|
||||
else:
|
||||
tStyle = self.T_HEAD2
|
||||
|
||||
# If we're not in a novel section, we just treat this as a regular H2
|
||||
tStyle = self.T_UNNUM if self._isNovel else self.T_HEAD2
|
||||
self._tokens.append((
|
||||
tStyle, nHead, aLine[4:].strip(), [], sAlign
|
||||
tStyle, nHead, aLine[4:].strip(), [], self.A_NONE
|
||||
))
|
||||
if self._keepMarkdown:
|
||||
tmpMarkdown.append("%s\n" % aLine)
|
||||
@@ -622,7 +640,8 @@ class Tokenizer(ABC):
|
||||
|
||||
# If we have content, turn off the first page flag
|
||||
if self._isFirst and self._tokens:
|
||||
self._isFirst = False
|
||||
self._isFirst = False # First document has been processed
|
||||
self._noBreak = True # Check again after headers are processed
|
||||
|
||||
# Make sure the token array doesn't start with a page break
|
||||
# on the very first page, adding a blank first page.
|
||||
@@ -686,7 +705,7 @@ class Tokenizer(ABC):
|
||||
|
||||
tTemp = self._hFormatter.apply(self._fmtTitle, token[2], token[1])
|
||||
self._tokens[n] = (
|
||||
token[0], token[1], tTemp, [], token[4]
|
||||
token[0], token[1], tTemp, [], self._titleStyle
|
||||
)
|
||||
|
||||
# Set scene variables
|
||||
@@ -704,7 +723,7 @@ class Tokenizer(ABC):
|
||||
|
||||
# Format the chapter header
|
||||
self._tokens[n] = (
|
||||
token[0], token[1], tTemp, [], token[4]
|
||||
token[0], token[1], tTemp, [], self._chapterStyle
|
||||
)
|
||||
|
||||
# Set scene variables
|
||||
@@ -729,11 +748,11 @@ class Tokenizer(ABC):
|
||||
self._tokens[n] = (
|
||||
self.T_EMPTY if self._skipSeparator else self.T_SEP, token[1],
|
||||
"" if self._skipSeparator else tTemp, [],
|
||||
self.A_NONE if self._skipSeparator else (token[4] | self.A_CENTRE)
|
||||
self.A_NONE if self._skipSeparator else self.A_CENTRE
|
||||
)
|
||||
else:
|
||||
self._tokens[n] = (
|
||||
token[0], token[1], tTemp, [], token[4]
|
||||
token[0], token[1], tTemp, [], self._sceneStyle
|
||||
)
|
||||
|
||||
self._skipSeparator = False
|
||||
@@ -758,6 +777,15 @@ class Tokenizer(ABC):
|
||||
token[0], token[1], tTemp, [], token[4]
|
||||
)
|
||||
|
||||
if n == 0 and self._noBreak:
|
||||
# Make sure again that the token array doesn't start with a page break
|
||||
self._noBreak = False
|
||||
if self._tokens[0][4] & self.A_PBB:
|
||||
token = self._tokens[0]
|
||||
self._tokens[0] = (
|
||||
token[0], token[1], token[2], token[3], token[4] & ~self.A_PBB
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
def countStats(self) -> dict[str, int]:
|
||||
|
||||
@@ -49,6 +49,7 @@ class ToMarkdown(Tokenizer):
|
||||
super().__init__(project)
|
||||
self._genMode = self.M_STD
|
||||
self._fullMD: list[str] = []
|
||||
self._preserveBreaks = True
|
||||
return
|
||||
|
||||
##
|
||||
@@ -74,6 +75,11 @@ class ToMarkdown(Tokenizer):
|
||||
self._genMode = self.M_EXT
|
||||
return
|
||||
|
||||
def setPreserveBreaks(self, state: bool) -> None:
|
||||
"""Preserve line breaks in paragraphs."""
|
||||
self._preserveBreaks = state
|
||||
return
|
||||
|
||||
##
|
||||
# Class Methods
|
||||
##
|
||||
@@ -125,12 +131,13 @@ class ToMarkdown(Tokenizer):
|
||||
|
||||
para = []
|
||||
lines = []
|
||||
lineSep = " \n" if self._preserveBreaks else " "
|
||||
|
||||
for tType, _, tText, tFormat, tStyle in self._tokens:
|
||||
|
||||
if tType == self.T_EMPTY:
|
||||
if len(para) > 0:
|
||||
tTemp = (" \n".join(para)).rstrip(" ")
|
||||
tTemp = (lineSep.join(para)).rstrip(" ")
|
||||
lines.append(f"{tTemp}\n\n")
|
||||
para = []
|
||||
|
||||
|
||||
@@ -337,7 +337,8 @@ class GuiManuscript(QDialog):
|
||||
if build is None:
|
||||
return
|
||||
|
||||
docBuild = NWBuildDocument(SHARED.project, build, doCount=True)
|
||||
docBuild = NWBuildDocument(SHARED.project, build)
|
||||
docBuild.setPreviewMode(True)
|
||||
docBuild.queueAll()
|
||||
|
||||
self.docPreview.beginNewBuild(len(docBuild))
|
||||
|
||||
@@ -37,7 +37,7 @@ from PyQt5.QtWidgets import (
|
||||
)
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.constants import nwHeadFmt, nwLabels, trConst
|
||||
from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, trConst
|
||||
from novelwriter.core.buildsettings import BuildSettings, FilterMode
|
||||
from novelwriter.extensions.switch import NSwitch
|
||||
from novelwriter.extensions.modified import NComboBox, NDoubleSpinBox, NSpinBox
|
||||
@@ -593,6 +593,7 @@ class _HeadingsTab(NScrollablePage):
|
||||
self._editing = 0
|
||||
|
||||
iPx = SHARED.theme.baseIconSize
|
||||
sSp = CONFIG.pxInt(16)
|
||||
vSp = CONFIG.pxInt(12)
|
||||
bSp = CONFIG.pxInt(6)
|
||||
|
||||
@@ -614,8 +615,8 @@ class _HeadingsTab(NScrollablePage):
|
||||
wrapTitle.addWidget(self.btnTitle)
|
||||
wrapTitle.setSpacing(bSp)
|
||||
|
||||
self.formatBox.addWidget(self.lblTitle, 0, 0, Qt.AlignLeft)
|
||||
self.formatBox.addLayout(wrapTitle, 0, 1, Qt.AlignLeft)
|
||||
self.formatBox.addWidget(self.lblTitle, 0, 0)
|
||||
self.formatBox.addLayout(wrapTitle, 0, 1)
|
||||
|
||||
# Chapter Heading
|
||||
self.lblChapter = QLabel(self._build.getLabel("headings.fmtChapter"))
|
||||
@@ -630,8 +631,8 @@ class _HeadingsTab(NScrollablePage):
|
||||
wrapChapter.addWidget(self.btnChapter)
|
||||
wrapChapter.setSpacing(bSp)
|
||||
|
||||
self.formatBox.addWidget(self.lblChapter, 1, 0, Qt.AlignLeft)
|
||||
self.formatBox.addLayout(wrapChapter, 1, 1, Qt.AlignLeft)
|
||||
self.formatBox.addWidget(self.lblChapter, 1, 0)
|
||||
self.formatBox.addLayout(wrapChapter, 1, 1)
|
||||
|
||||
# Unnumbered Chapter Heading
|
||||
self.lblUnnumbered = QLabel(self._build.getLabel("headings.fmtUnnumbered"))
|
||||
@@ -646,8 +647,8 @@ class _HeadingsTab(NScrollablePage):
|
||||
wrapUnnumbered.addWidget(self.btnUnnumbered)
|
||||
wrapUnnumbered.setSpacing(bSp)
|
||||
|
||||
self.formatBox.addWidget(self.lblUnnumbered, 2, 0, Qt.AlignLeft)
|
||||
self.formatBox.addLayout(wrapUnnumbered, 2, 1, Qt.AlignLeft)
|
||||
self.formatBox.addWidget(self.lblUnnumbered, 2, 0)
|
||||
self.formatBox.addLayout(wrapUnnumbered, 2, 1)
|
||||
|
||||
# Scene Heading
|
||||
sceneHideTip = self._build.getLabel("headings.hideScene")
|
||||
@@ -672,9 +673,9 @@ class _HeadingsTab(NScrollablePage):
|
||||
wrapSceneHide.addWidget(self.swtScene)
|
||||
wrapSceneHide.setSpacing(bSp)
|
||||
|
||||
self.formatBox.addWidget(self.lblScene, 3, 0, Qt.AlignLeft)
|
||||
self.formatBox.addLayout(wrapScene, 3, 1, Qt.AlignLeft)
|
||||
self.formatBox.addLayout(wrapSceneHide, 3, 2, Qt.AlignLeft)
|
||||
self.formatBox.addWidget(self.lblScene, 3, 0)
|
||||
self.formatBox.addLayout(wrapScene, 3, 1)
|
||||
self.formatBox.addLayout(wrapSceneHide, 3, 2)
|
||||
|
||||
# Section Heading
|
||||
sectionHideTip = self._build.getLabel("headings.hideSection")
|
||||
@@ -699,16 +700,16 @@ class _HeadingsTab(NScrollablePage):
|
||||
wrapSectionHide.addWidget(self.swtSection)
|
||||
wrapSectionHide.setSpacing(bSp)
|
||||
|
||||
self.formatBox.addWidget(self.lblSection, 4, 0, Qt.AlignLeft)
|
||||
self.formatBox.addLayout(wrapSection, 4, 1, Qt.AlignLeft)
|
||||
self.formatBox.addLayout(wrapSectionHide, 4, 2, Qt.AlignLeft)
|
||||
self.formatBox.addWidget(self.lblSection, 4, 0)
|
||||
self.formatBox.addLayout(wrapSection, 4, 1)
|
||||
self.formatBox.addLayout(wrapSectionHide, 4, 2)
|
||||
|
||||
# Edit Form
|
||||
# =========
|
||||
|
||||
self.lblEditForm = QLabel(self.tr("Editing: {0}").format(self.tr("None")))
|
||||
|
||||
self.editTextBox = QPlainTextEdit()
|
||||
self.editTextBox = QPlainTextEdit(self)
|
||||
self.editTextBox.setFixedHeight(5*iPx)
|
||||
self.editTextBox.setEnabled(False)
|
||||
|
||||
@@ -735,10 +736,10 @@ class _HeadingsTab(NScrollablePage):
|
||||
self.aInsCharPOV.triggered.connect(lambda: self._insertIntoForm(nwHeadFmt.CHAR_POV))
|
||||
self.aInsCharFocus.triggered.connect(lambda: self._insertIntoForm(nwHeadFmt.CHAR_FOCUS))
|
||||
|
||||
self.btnInsert = QPushButton(self.tr("Insert"))
|
||||
self.btnInsert = QPushButton(self.tr("Insert"), self)
|
||||
self.btnInsert.setMenu(self.menuInsert)
|
||||
|
||||
self.btnApply = QPushButton(self.tr("Apply"))
|
||||
self.btnApply = QPushButton(self.tr("Apply"), self)
|
||||
self.btnApply.clicked.connect(self._saveFormat)
|
||||
|
||||
self.formButtonBox = QHBoxLayout()
|
||||
@@ -751,13 +752,72 @@ class _HeadingsTab(NScrollablePage):
|
||||
self.editFormBox.addWidget(self.editTextBox)
|
||||
self.editFormBox.addLayout(self.formButtonBox)
|
||||
|
||||
# Layout Matrix
|
||||
# =============
|
||||
self.layoutMatrix = QGridLayout()
|
||||
self.layoutMatrix.setVerticalSpacing(vSp)
|
||||
self.layoutMatrix.setHorizontalSpacing(vSp)
|
||||
|
||||
# Heading
|
||||
self.layoutHeading = QLabel("<b>{0}</b>".format(self.tr("Additional Styling")), self)
|
||||
self.layoutMatrix.addWidget(self.layoutHeading, 0, 0, 1, 5)
|
||||
|
||||
# Title Layout
|
||||
self.mtxTitle = QLabel(self._build.getLabel("headings.fmtTitle"))
|
||||
self.centerTitle = NSwitch(self, height=iPx)
|
||||
self.breakTitle = NSwitch(self, height=iPx)
|
||||
lblCenterT = QLabel(self.tr("Centre"))
|
||||
lblCenterT.setIndent(sSp)
|
||||
lblBreakT = QLabel(self.tr("Page Break"))
|
||||
lblBreakT.setIndent(sSp)
|
||||
|
||||
self.layoutMatrix.addWidget(self.mtxTitle, 1, 0)
|
||||
self.layoutMatrix.addWidget(lblCenterT, 1, 1)
|
||||
self.layoutMatrix.addWidget(self.centerTitle, 1, 2)
|
||||
self.layoutMatrix.addWidget(lblBreakT, 1, 3)
|
||||
self.layoutMatrix.addWidget(self.breakTitle, 1, 4)
|
||||
|
||||
# Chapter Layout
|
||||
self.mtxChapter = QLabel(self._build.getLabel("headings.fmtChapter"))
|
||||
self.centerChapter = NSwitch(self, height=iPx)
|
||||
self.breakChapter = NSwitch(self, height=iPx)
|
||||
lblCenterC = QLabel(self.tr("Centre"))
|
||||
lblCenterC.setIndent(sSp)
|
||||
lblBreakC = QLabel(self.tr("Page Break"))
|
||||
lblBreakC.setIndent(sSp)
|
||||
|
||||
self.layoutMatrix.addWidget(self.mtxChapter, 2, 0)
|
||||
self.layoutMatrix.addWidget(lblCenterC, 2, 1)
|
||||
self.layoutMatrix.addWidget(self.centerChapter, 2, 2)
|
||||
self.layoutMatrix.addWidget(lblBreakC, 2, 3)
|
||||
self.layoutMatrix.addWidget(self.breakChapter, 2, 4)
|
||||
|
||||
# Scene Layout
|
||||
self.mtxScene = QLabel(self._build.getLabel("headings.fmtScene"))
|
||||
self.centerScene = NSwitch(self, height=iPx)
|
||||
self.breakScene = NSwitch(self, height=iPx)
|
||||
lblCenterS = QLabel(self.tr("Centre"))
|
||||
lblCenterS.setIndent(sSp)
|
||||
lblBreakS = QLabel(self.tr("Page Break"))
|
||||
lblBreakS.setIndent(sSp)
|
||||
|
||||
self.layoutMatrix.addWidget(self.mtxScene, 3, 0)
|
||||
self.layoutMatrix.addWidget(lblCenterS, 3, 1)
|
||||
self.layoutMatrix.addWidget(self.centerScene, 3, 2)
|
||||
self.layoutMatrix.addWidget(lblBreakS, 3, 3)
|
||||
self.layoutMatrix.addWidget(self.breakScene, 3, 4)
|
||||
|
||||
self.layoutMatrix.setColumnStretch(5, 1)
|
||||
|
||||
# Assemble
|
||||
# ========
|
||||
|
||||
self.outerBox = QVBoxLayout()
|
||||
self.outerBox.addLayout(self.formatBox)
|
||||
self.outerBox.addSpacing(CONFIG.pxInt(16))
|
||||
self.outerBox.addSpacing(sSp)
|
||||
self.outerBox.addLayout(self.editFormBox)
|
||||
self.outerBox.addSpacing(sSp)
|
||||
self.outerBox.addLayout(self.layoutMatrix)
|
||||
self.outerBox.addStretch(1)
|
||||
|
||||
self.setCentralLayout(self.outerBox)
|
||||
@@ -773,12 +833,24 @@ class _HeadingsTab(NScrollablePage):
|
||||
self.fmtSection.setText(self._build.getStr("headings.fmtSection"))
|
||||
self.swtScene.setChecked(self._build.getBool("headings.hideScene"))
|
||||
self.swtSection.setChecked(self._build.getBool("headings.hideSection"))
|
||||
self.centerTitle.setChecked(self._build.getBool("headings.centerTitle"))
|
||||
self.centerChapter.setChecked(self._build.getBool("headings.centerChapter"))
|
||||
self.centerScene.setChecked(self._build.getBool("headings.centerScene"))
|
||||
self.breakTitle.setChecked(self._build.getBool("headings.breakTitle"))
|
||||
self.breakChapter.setChecked(self._build.getBool("headings.breakChapter"))
|
||||
self.breakScene.setChecked(self._build.getBool("headings.breakScene"))
|
||||
return
|
||||
|
||||
def saveContent(self) -> None:
|
||||
"""Save choices back into build object."""
|
||||
self._build.setValue("headings.hideScene", self.swtScene.isChecked())
|
||||
self._build.setValue("headings.hideSection", self.swtSection.isChecked())
|
||||
self._build.setValue("headings.centerTitle", self.centerTitle.isChecked())
|
||||
self._build.setValue("headings.centerChapter", self.centerChapter.isChecked())
|
||||
self._build.setValue("headings.centerScene", self.centerScene.isChecked())
|
||||
self._build.setValue("headings.breakTitle", self.breakTitle.isChecked())
|
||||
self._build.setValue("headings.breakChapter", self.breakChapter.isChecked())
|
||||
self._build.setValue("headings.breakScene", self.breakScene.isChecked())
|
||||
return
|
||||
|
||||
##
|
||||
@@ -894,16 +966,32 @@ class _ContentTab(NScrollableForm):
|
||||
iPx = SHARED.theme.baseIconSize
|
||||
|
||||
# Text Content
|
||||
self.incBodyText = NSwitch(self, height=iPx)
|
||||
self.incSynopsis = NSwitch(self, height=iPx)
|
||||
self.incComments = NSwitch(self, height=iPx)
|
||||
self.incKeywords = NSwitch(self, height=iPx)
|
||||
self.incBodyText = NSwitch(self, height=iPx)
|
||||
|
||||
self.ignoredKeywords = QLineEdit(self)
|
||||
|
||||
self.mnKeywords = QMenu(self)
|
||||
for keyword in nwKeyWords.VALID_KEYS:
|
||||
self.mnKeywords.addAction(
|
||||
trConst(nwLabels.KEY_NAME[keyword]),
|
||||
lambda keyword=keyword: self._updateIgnoredKeywords(keyword)
|
||||
)
|
||||
|
||||
self.ignoredKeywordsButton = QToolButton(self)
|
||||
self.ignoredKeywordsButton.setIcon(SHARED.theme.getIcon("add"))
|
||||
self.ignoredKeywordsButton.setMenu(self.mnKeywords)
|
||||
self.ignoredKeywordsButton.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
|
||||
|
||||
self.addGroupLabel(self._build.getLabel("text.grpContent"))
|
||||
self.addRow(self._build.getLabel("text.includeBodyText"), self.incBodyText)
|
||||
self.addRow(self._build.getLabel("text.includeSynopsis"), self.incSynopsis)
|
||||
self.addRow(self._build.getLabel("text.includeComments"), self.incComments)
|
||||
self.addRow(self._build.getLabel("text.includeKeywords"), self.incKeywords)
|
||||
self.addRow(self._build.getLabel("text.includeBodyText"), self.incBodyText)
|
||||
self.addRow(self._build.getLabel("text.ignoredKeywords"), self.ignoredKeywords,
|
||||
button=self.ignoredKeywordsButton, stretch=(1, 1))
|
||||
|
||||
# Insert Content
|
||||
self.addNoteHead = NSwitch(self, height=iPx)
|
||||
@@ -918,22 +1006,39 @@ class _ContentTab(NScrollableForm):
|
||||
|
||||
def loadContent(self) -> None:
|
||||
"""Populate the widgets."""
|
||||
self.incBodyText.setChecked(self._build.getBool("text.includeBodyText"))
|
||||
self.incSynopsis.setChecked(self._build.getBool("text.includeSynopsis"))
|
||||
self.incComments.setChecked(self._build.getBool("text.includeComments"))
|
||||
self.incKeywords.setChecked(self._build.getBool("text.includeKeywords"))
|
||||
self.incBodyText.setChecked(self._build.getBool("text.includeBodyText"))
|
||||
self.ignoredKeywords.setText(self._build.getStr("text.ignoredKeywords"))
|
||||
self.addNoteHead.setChecked(self._build.getBool("text.addNoteHeadings"))
|
||||
self._updateIgnoredKeywords()
|
||||
return
|
||||
|
||||
def saveContent(self) -> None:
|
||||
"""Save choices back into build object."""
|
||||
self._updateIgnoredKeywords()
|
||||
self._build.setValue("text.includeBodyText", self.incBodyText.isChecked())
|
||||
self._build.setValue("text.includeSynopsis", self.incSynopsis.isChecked())
|
||||
self._build.setValue("text.includeComments", self.incComments.isChecked())
|
||||
self._build.setValue("text.includeKeywords", self.incKeywords.isChecked())
|
||||
self._build.setValue("text.includeBodyText", self.incBodyText.isChecked())
|
||||
self._build.setValue("text.ignoredKeywords", self.ignoredKeywords.text())
|
||||
self._build.setValue("text.addNoteHeadings", self.addNoteHead.isChecked())
|
||||
return
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _updateIgnoredKeywords(self, keyword: str | None = None) -> None:
|
||||
"""Update the ignored keywords list."""
|
||||
current = [x.lower().strip() for x in self.ignoredKeywords.text().split(",")]
|
||||
if keyword:
|
||||
current.append(keyword)
|
||||
verified = set(x for x in current if x in nwKeyWords.VALID_KEYS)
|
||||
self.ignoredKeywords.setText(", ".join(verified))
|
||||
return
|
||||
|
||||
# END Class _ContentTab
|
||||
|
||||
|
||||
@@ -1245,6 +1350,15 @@ class _OutputTab(NScrollableForm):
|
||||
self.htmlAddStyles = NSwitch(self, height=iPx)
|
||||
self.addRow(self._build.getLabel("html.addStyles"), self.htmlAddStyles)
|
||||
|
||||
self.htmlPreserveTabs = NSwitch(self, height=iPx)
|
||||
self.addRow(self._build.getLabel("html.preserveTabs"), self.htmlPreserveTabs)
|
||||
|
||||
# Markdown Document
|
||||
self.addGroupLabel(self._build.getLabel("md"))
|
||||
|
||||
self.mdPreserveBreaks = NSwitch(self, height=iPx)
|
||||
self.addRow(self._build.getLabel("md.preserveBreaks"), self.mdPreserveBreaks)
|
||||
|
||||
# Finalise
|
||||
self.finalise()
|
||||
|
||||
@@ -1256,6 +1370,8 @@ class _OutputTab(NScrollableForm):
|
||||
self.odtPageHeader.setText(self._build.getStr("odt.pageHeader"))
|
||||
self.odtPageCountOffset.setValue(self._build.getInt("odt.pageCountOffset"))
|
||||
self.htmlAddStyles.setChecked(self._build.getBool("html.addStyles"))
|
||||
self.htmlPreserveTabs.setChecked(self._build.getBool("html.preserveTabs"))
|
||||
self.mdPreserveBreaks.setChecked(self._build.getBool("md.preserveBreaks"))
|
||||
return
|
||||
|
||||
def saveContent(self) -> None:
|
||||
@@ -1264,6 +1380,8 @@ class _OutputTab(NScrollableForm):
|
||||
self._build.setValue("odt.pageHeader", self.odtPageHeader.text())
|
||||
self._build.setValue("odt.pageCountOffset", self.odtPageCountOffset.value())
|
||||
self._build.setValue("html.addStyles", self.htmlAddStyles.isChecked())
|
||||
self._build.setValue("html.preserveTabs", self.htmlPreserveTabs.isChecked())
|
||||
self._build.setValue("md.preserveBreaks", self.mdPreserveBreaks.isChecked())
|
||||
return
|
||||
|
||||
##
|
||||
|
||||
@@ -83,7 +83,8 @@ def testCoreDocBuild_OpenDocument(monkeypatch, mockGUI, prjLipsum, fncPath, tstP
|
||||
build = BuildSettings()
|
||||
build.unpack(BUILD_CONF)
|
||||
|
||||
docBuild = NWBuildDocument(project, build, doCount=True)
|
||||
docBuild = NWBuildDocument(project, build)
|
||||
docBuild.setCountEnabled(True)
|
||||
docBuild.queueAll()
|
||||
|
||||
assert len(docBuild) == 21
|
||||
|
||||
@@ -44,6 +44,7 @@ def testCoreToHtml_ConvertHeaders(mockGUI):
|
||||
# Header 1
|
||||
html._text = "# Partition\n"
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == (
|
||||
"<h1 class='title' style='text-align: center;'>Partition</h1>\n"
|
||||
@@ -52,6 +53,7 @@ def testCoreToHtml_ConvertHeaders(mockGUI):
|
||||
# Header 2
|
||||
html._text = "## Chapter Title\n"
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == (
|
||||
"<h1 style='page-break-before: always;'>Chapter Title</h1>\n"
|
||||
@@ -60,26 +62,30 @@ def testCoreToHtml_ConvertHeaders(mockGUI):
|
||||
# Header 3
|
||||
html._text = "### Scene Title\n"
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == "<h2>Scene Title</h2>\n"
|
||||
|
||||
# Header 4
|
||||
html._text = "#### Section Title\n"
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == "<h3>Section Title</h3>\n"
|
||||
|
||||
# Title
|
||||
html._text = "#! Title\n"
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == (
|
||||
"<h1 class='title' style='text-align: center;'>Title</h1>\n"
|
||||
"<h1 class='title' style='text-align: center; page-break-before: always;'>Title</h1>\n"
|
||||
)
|
||||
|
||||
# Unnumbered
|
||||
html._text = "##! Prologue\n"
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == "<h1 style='page-break-before: always;'>Prologue</h1>\n"
|
||||
|
||||
@@ -94,38 +100,45 @@ def testCoreToHtml_ConvertHeaders(mockGUI):
|
||||
# Header 1
|
||||
html._text = "# Heading One\n"
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == "<h1><a name='T0001'></a>Heading One</h1>\n"
|
||||
|
||||
# Header 2
|
||||
html._text = "## Heading Two\n"
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == "<h2><a name='T0001'></a>Heading Two</h2>\n"
|
||||
|
||||
# Header 3
|
||||
html._text = "### Heading Three\n"
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == "<h3><a name='T0001'></a>Heading Three</h3>\n"
|
||||
|
||||
# Header 4
|
||||
html._text = "#### Heading Four\n"
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == "<h4><a name='T0001'></a>Heading Four</h4>\n"
|
||||
|
||||
# Title
|
||||
html._text = "#! Heading One\n"
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == (
|
||||
"<h1 style='text-align: center;'><a name='T0001'></a>Heading One</h1>\n"
|
||||
"<h1 class='title' style='text-align: center; page-break-before: always;'>"
|
||||
"<a name='T0001'></a>Heading One</h1>\n"
|
||||
)
|
||||
|
||||
# Unnumbered
|
||||
html._text = "##! Heading Two\n"
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == "<h2><a name='T0001'></a>Heading Two</h2>\n"
|
||||
|
||||
@@ -227,9 +240,12 @@ def testCoreToHtml_ConvertParagraphs(mockGUI):
|
||||
)
|
||||
|
||||
# Multiple Keywords
|
||||
html._isFirst = False
|
||||
html._noBreak = False
|
||||
html.setKeywords(True)
|
||||
html._text = "## Chapter\n\n@pov: Bod\n@plot: Main\n@location: Europe\n\n"
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == (
|
||||
"<h1 style='page-break-before: always;'>Chapter</h1>\n"
|
||||
@@ -457,8 +473,11 @@ def testCoreToHtml_SpecialCases(mockGUI):
|
||||
"</p>\n"
|
||||
)
|
||||
|
||||
html._isFirst = False
|
||||
html._noBreak = False
|
||||
html._text = "## Heading <1>\n"
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == (
|
||||
"<h1 style='page-break-before: always;'>Heading <1></h1>\n"
|
||||
@@ -532,6 +551,7 @@ def testCoreToHtml_Complex(mockGUI, fncPath):
|
||||
html._text = docText[i]
|
||||
html.doPreProcessing()
|
||||
html.tokenizeText()
|
||||
html.doHeaders()
|
||||
html.doConvert()
|
||||
assert html.result == resText[i]
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ def testCoreToken_HeaderFormat(mockGUI):
|
||||
|
||||
tokens.tokenizeText()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Note Title", [], Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_TITLE, 1, "Note Title", [], Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
]
|
||||
assert tokens.allMarkdown[-1] == "#! Note Title\n\n"
|
||||
@@ -276,6 +276,7 @@ def testCoreToken_HeaderFormat(mockGUI):
|
||||
tokens._text = "# Novel Title\n"
|
||||
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Novel Title", [], Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -289,6 +290,7 @@ def testCoreToken_HeaderFormat(mockGUI):
|
||||
tokens._text = "# Note Title\n"
|
||||
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Note Title", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -301,9 +303,11 @@ def testCoreToken_HeaderFormat(mockGUI):
|
||||
# Story File
|
||||
tokens._isNovel = True
|
||||
tokens._isNote = False
|
||||
tokens._noBreak = False
|
||||
tokens._text = "## Chapter One\n"
|
||||
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD2, 1, "Chapter One", [], Tokenizer.A_PBB),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -316,6 +320,7 @@ def testCoreToken_HeaderFormat(mockGUI):
|
||||
tokens._text = "## Heading 2\n"
|
||||
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD2, 1, "Heading 2", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -331,6 +336,7 @@ def testCoreToken_HeaderFormat(mockGUI):
|
||||
tokens._text = "### Scene One\n"
|
||||
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD3, 1, "Scene One", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -343,6 +349,7 @@ def testCoreToken_HeaderFormat(mockGUI):
|
||||
tokens._text = "### Heading 3\n"
|
||||
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD3, 1, "Heading 3", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -358,6 +365,7 @@ def testCoreToken_HeaderFormat(mockGUI):
|
||||
tokens._text = "#### A Section\n"
|
||||
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD4, 1, "A Section", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -370,6 +378,7 @@ def testCoreToken_HeaderFormat(mockGUI):
|
||||
tokens._text = "#### Heading 4\n"
|
||||
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD4, 1, "Heading 4", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -382,11 +391,13 @@ def testCoreToken_HeaderFormat(mockGUI):
|
||||
# Story File
|
||||
tokens._isNovel = True
|
||||
tokens._isNote = False
|
||||
tokens._isFirst = False
|
||||
tokens._text = "#! Title\n"
|
||||
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_TITLE, 1, "Title", [], Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_TITLE, 1, "Title", [], Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
]
|
||||
assert tokens.allMarkdown[-1] == "#! Title\n\n"
|
||||
@@ -394,11 +405,13 @@ def testCoreToken_HeaderFormat(mockGUI):
|
||||
# Note File
|
||||
tokens._isNovel = False
|
||||
tokens._isNote = True
|
||||
tokens._isFirst = False
|
||||
tokens._text = "#! Title\n"
|
||||
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title", [], Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_TITLE, 1, "Title", [], Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
]
|
||||
assert tokens.allMarkdown[-1] == "#! Title\n\n"
|
||||
@@ -412,6 +425,7 @@ def testCoreToken_HeaderFormat(mockGUI):
|
||||
tokens._text = "##! Prologue\n"
|
||||
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_UNNUM, 1, "Prologue", [], Tokenizer.A_PBB),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -424,6 +438,7 @@ def testCoreToken_HeaderFormat(mockGUI):
|
||||
tokens._text = "##! Prologue\n"
|
||||
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD2, 1, "Prologue", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -433,6 +448,280 @@ def testCoreToken_HeaderFormat(mockGUI):
|
||||
# END Test testCoreToken_HeaderFormat
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreToken_HeaderStyle(mockGUI):
|
||||
"""Test the styling of headers in the Tokenizer class."""
|
||||
project = NWProject()
|
||||
tokens = BareTokenizer(project)
|
||||
|
||||
def processStyle(text: str, first: bool) -> int:
|
||||
tokens._text = text
|
||||
tokens._isFirst = first
|
||||
tokens._noBreak = first
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
return tokens._tokens[0][4]
|
||||
|
||||
# No Styles
|
||||
# =========
|
||||
|
||||
tokens.setTitleStyle(False, False)
|
||||
tokens.setChapterStyle(False, False)
|
||||
tokens.setSceneStyle(False, False)
|
||||
|
||||
assert tokens._titleStyle == Tokenizer.A_NONE
|
||||
assert tokens._chapterStyle == Tokenizer.A_NONE
|
||||
assert tokens._sceneStyle == Tokenizer.A_NONE
|
||||
|
||||
# Novel Docs
|
||||
tokens._isNovel = True
|
||||
tokens._isNote = False
|
||||
|
||||
# First Document is False
|
||||
assert processStyle("# Title\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("## Chapter\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("### Scene\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#### Section\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("##! Prologue\n", False) == Tokenizer.A_NONE
|
||||
|
||||
# First Document is True
|
||||
assert processStyle("# Title\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("## Chapter\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("### Scene\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("#### Section\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", True) == Tokenizer.A_CENTRE
|
||||
assert processStyle("##! Prologue\n", True) == Tokenizer.A_NONE
|
||||
|
||||
# Note Docs
|
||||
tokens._isNovel = False
|
||||
tokens._isNote = True
|
||||
|
||||
# First Document is False
|
||||
assert processStyle("# Title\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("## Chapter\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("### Scene\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#### Section\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("##! Prologue\n", False) == Tokenizer.A_NONE
|
||||
|
||||
# First Document is True
|
||||
assert processStyle("# Title\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("## Chapter\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("### Scene\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("#### Section\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", True) == Tokenizer.A_CENTRE
|
||||
assert processStyle("##! Prologue\n", True) == Tokenizer.A_NONE
|
||||
|
||||
# Center Headers
|
||||
# ==============
|
||||
|
||||
tokens.setTitleStyle(True, False)
|
||||
tokens.setChapterStyle(True, False)
|
||||
tokens.setSceneStyle(True, False)
|
||||
|
||||
assert tokens._titleStyle == Tokenizer.A_CENTRE
|
||||
assert tokens._chapterStyle == Tokenizer.A_CENTRE
|
||||
assert tokens._sceneStyle == Tokenizer.A_CENTRE
|
||||
|
||||
# Novel Docs
|
||||
tokens._isNovel = True
|
||||
tokens._isNote = False
|
||||
|
||||
# First Document is False
|
||||
assert processStyle("# Title\n", False) == Tokenizer.A_CENTRE
|
||||
assert processStyle("## Chapter\n", False) == Tokenizer.A_CENTRE
|
||||
assert processStyle("### Scene\n", False) == Tokenizer.A_CENTRE
|
||||
assert processStyle("#### Section\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("##! Prologue\n", False) == Tokenizer.A_CENTRE
|
||||
|
||||
# First Document is True
|
||||
assert processStyle("# Title\n", True) == Tokenizer.A_CENTRE
|
||||
assert processStyle("## Chapter\n", True) == Tokenizer.A_CENTRE
|
||||
assert processStyle("### Scene\n", True) == Tokenizer.A_CENTRE
|
||||
assert processStyle("#### Section\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", True) == Tokenizer.A_CENTRE
|
||||
assert processStyle("##! Prologue\n", True) == Tokenizer.A_CENTRE
|
||||
|
||||
# Note Docs
|
||||
tokens._isNovel = False
|
||||
tokens._isNote = True
|
||||
|
||||
# First Document is False
|
||||
assert processStyle("# Title\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("## Chapter\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("### Scene\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#### Section\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("##! Prologue\n", False) == Tokenizer.A_NONE
|
||||
|
||||
# First Document is True
|
||||
assert processStyle("# Title\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("## Chapter\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("### Scene\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("#### Section\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", True) == Tokenizer.A_CENTRE
|
||||
assert processStyle("##! Prologue\n", True) == Tokenizer.A_NONE
|
||||
|
||||
# Page Break Headers
|
||||
# ==================
|
||||
|
||||
tokens.setTitleStyle(False, True)
|
||||
tokens.setChapterStyle(False, True)
|
||||
tokens.setSceneStyle(False, True)
|
||||
|
||||
assert tokens._titleStyle == Tokenizer.A_PBB
|
||||
assert tokens._chapterStyle == Tokenizer.A_PBB
|
||||
assert tokens._sceneStyle == Tokenizer.A_PBB
|
||||
|
||||
# Novel Docs
|
||||
tokens._isNovel = True
|
||||
tokens._isNote = False
|
||||
|
||||
# First Document is False
|
||||
assert processStyle("# Title\n", False) == Tokenizer.A_PBB
|
||||
assert processStyle("## Chapter\n", False) == Tokenizer.A_PBB
|
||||
assert processStyle("### Scene\n", False) == Tokenizer.A_PBB
|
||||
assert processStyle("#### Section\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("##! Prologue\n", False) == Tokenizer.A_PBB
|
||||
|
||||
# First Document is True
|
||||
assert processStyle("# Title\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("## Chapter\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("### Scene\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("#### Section\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", True) == Tokenizer.A_CENTRE
|
||||
assert processStyle("##! Prologue\n", True) == Tokenizer.A_NONE
|
||||
|
||||
# Note Docs
|
||||
tokens._isNovel = False
|
||||
tokens._isNote = True
|
||||
|
||||
# First Document is False
|
||||
assert processStyle("# Title\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("## Chapter\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("### Scene\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#### Section\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("##! Prologue\n", False) == Tokenizer.A_NONE
|
||||
|
||||
# First Document is True
|
||||
assert processStyle("# Title\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("## Chapter\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("### Scene\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("#### Section\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", True) == Tokenizer.A_CENTRE
|
||||
assert processStyle("##! Prologue\n", True) == Tokenizer.A_NONE
|
||||
|
||||
# Page Break and Centre Headers
|
||||
# =============================
|
||||
|
||||
tokens.setTitleStyle(True, True)
|
||||
tokens.setChapterStyle(True, True)
|
||||
tokens.setSceneStyle(True, True)
|
||||
|
||||
assert tokens._titleStyle == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert tokens._chapterStyle == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert tokens._sceneStyle == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
|
||||
# Novel Docs
|
||||
tokens._isNovel = True
|
||||
tokens._isNote = False
|
||||
|
||||
# First Document is False
|
||||
assert processStyle("# Title\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("## Chapter\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("### Scene\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("#### Section\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("##! Prologue\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
|
||||
# First Document is True
|
||||
assert processStyle("# Title\n", True) == Tokenizer.A_CENTRE
|
||||
assert processStyle("## Chapter\n", True) == Tokenizer.A_CENTRE
|
||||
assert processStyle("### Scene\n", True) == Tokenizer.A_CENTRE
|
||||
assert processStyle("#### Section\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", True) == Tokenizer.A_CENTRE
|
||||
assert processStyle("##! Prologue\n", True) == Tokenizer.A_CENTRE
|
||||
|
||||
# Note Docs
|
||||
tokens._isNovel = False
|
||||
tokens._isNote = True
|
||||
|
||||
# First Document is False
|
||||
assert processStyle("# Title\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("## Chapter\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("### Scene\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#### Section\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("##! Prologue\n", False) == Tokenizer.A_NONE
|
||||
|
||||
# First Document is True
|
||||
assert processStyle("# Title\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("## Chapter\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("### Scene\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("#### Section\n", True) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", True) == Tokenizer.A_CENTRE
|
||||
assert processStyle("##! Prologue\n", True) == Tokenizer.A_NONE
|
||||
|
||||
# Check Separation
|
||||
# ================
|
||||
tokens._isNovel = True
|
||||
tokens._isNote = False
|
||||
|
||||
# Title Styles
|
||||
tokens.setTitleStyle(True, True)
|
||||
tokens.setChapterStyle(False, False)
|
||||
tokens.setSceneStyle(False, False)
|
||||
|
||||
assert tokens._titleStyle == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert tokens._chapterStyle == Tokenizer.A_NONE
|
||||
assert tokens._sceneStyle == Tokenizer.A_NONE
|
||||
|
||||
assert processStyle("# Title\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("## Chapter\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("### Scene\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#### Section\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("##! Prologue\n", False) == Tokenizer.A_NONE
|
||||
|
||||
# Chapter Styles
|
||||
tokens.setTitleStyle(False, False)
|
||||
tokens.setChapterStyle(True, True)
|
||||
tokens.setSceneStyle(False, False)
|
||||
|
||||
assert tokens._titleStyle == Tokenizer.A_NONE
|
||||
assert tokens._chapterStyle == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert tokens._sceneStyle == Tokenizer.A_NONE
|
||||
|
||||
assert processStyle("# Title\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("## Chapter\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("### Scene\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#### Section\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("##! Prologue\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
|
||||
# Scene Styles
|
||||
tokens.setTitleStyle(False, False)
|
||||
tokens.setChapterStyle(False, False)
|
||||
tokens.setSceneStyle(True, True)
|
||||
|
||||
assert tokens._titleStyle == Tokenizer.A_NONE
|
||||
assert tokens._chapterStyle == Tokenizer.A_NONE
|
||||
assert tokens._sceneStyle == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
|
||||
assert processStyle("# Title\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("## Chapter\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("### Scene\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("#### Section\n", False) == Tokenizer.A_NONE
|
||||
assert processStyle("#! My Novel\n", False) == Tokenizer.A_CENTRE | Tokenizer.A_PBB
|
||||
assert processStyle("##! Prologue\n", False) == Tokenizer.A_NONE
|
||||
|
||||
# END Test testCoreToken_HeaderStyle
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreToken_MetaFormat(mockGUI):
|
||||
"""Test the tokenization of meta formats in the Tokenizer class."""
|
||||
@@ -520,6 +809,15 @@ def testCoreToken_MetaFormat(mockGUI):
|
||||
]
|
||||
assert tokens.allMarkdown[-1] == "@pov: Bod\n@plot: Main\n@location: Europe\n\n"
|
||||
|
||||
# Ignored keywords
|
||||
tokens._text = "@pov: Bod\n@plot: Main\n@location: Europe\n"
|
||||
tokens.setIgnoredKeywords("@plot, @location")
|
||||
tokens.tokenizeText()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_KEYWORD, 0, "pov: Bod", [], Tokenizer.A_NONE),
|
||||
(Tokenizer.T_EMPTY, 0, "", [], Tokenizer.A_NONE),
|
||||
]
|
||||
|
||||
# END Test testCoreToken_MetaFormat
|
||||
|
||||
|
||||
@@ -822,6 +1120,7 @@ def testCoreToken_SpecialFormat(mockGUI):
|
||||
"# Title Two\n\n"
|
||||
)
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == correctResp
|
||||
|
||||
# Command w/Space
|
||||
@@ -832,6 +1131,7 @@ def testCoreToken_SpecialFormat(mockGUI):
|
||||
"# Title Two\n\n"
|
||||
)
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == correctResp
|
||||
|
||||
# Trailing Spaces
|
||||
@@ -842,6 +1142,7 @@ def testCoreToken_SpecialFormat(mockGUI):
|
||||
"# Title Two\n\n"
|
||||
)
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == correctResp
|
||||
|
||||
# Single Empty Paragraph
|
||||
@@ -853,6 +1154,7 @@ def testCoreToken_SpecialFormat(mockGUI):
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", [], Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -873,6 +1175,7 @@ def testCoreToken_SpecialFormat(mockGUI):
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", [], Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -890,6 +1193,7 @@ def testCoreToken_SpecialFormat(mockGUI):
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", [], Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -909,6 +1213,7 @@ def testCoreToken_SpecialFormat(mockGUI):
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", [], Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -925,6 +1230,7 @@ def testCoreToken_SpecialFormat(mockGUI):
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", [], Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -941,6 +1247,7 @@ def testCoreToken_SpecialFormat(mockGUI):
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", [], Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -961,6 +1268,7 @@ def testCoreToken_SpecialFormat(mockGUI):
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", [], Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
@@ -980,6 +1288,7 @@ def testCoreToken_SpecialFormat(mockGUI):
|
||||
"Some text to go here ...\n\n"
|
||||
)
|
||||
tokens.tokenizeText()
|
||||
tokens.doHeaders()
|
||||
assert tokens._tokens == [
|
||||
(Tokenizer.T_HEAD1, 1, "Title One", [], Tokenizer.A_PBB | Tokenizer.A_CENTRE),
|
||||
(Tokenizer.T_EMPTY, 1, "", [], Tokenizer.A_NONE),
|
||||
|
||||
@@ -246,6 +246,7 @@ def testCoreToOdt_ConvertHeaders(mockGUI):
|
||||
# Header 1
|
||||
odt._text = "# Title\n"
|
||||
odt.tokenizeText()
|
||||
odt.doHeaders()
|
||||
odt.initDocument()
|
||||
odt.doConvert()
|
||||
odt.closeDocument()
|
||||
@@ -259,6 +260,7 @@ def testCoreToOdt_ConvertHeaders(mockGUI):
|
||||
# Header 2
|
||||
odt._text = "## Chapter\n"
|
||||
odt.tokenizeText()
|
||||
odt.doHeaders()
|
||||
odt.initDocument()
|
||||
odt.doConvert()
|
||||
odt.closeDocument()
|
||||
@@ -272,6 +274,7 @@ def testCoreToOdt_ConvertHeaders(mockGUI):
|
||||
# Header 3
|
||||
odt._text = "### Scene\n"
|
||||
odt.tokenizeText()
|
||||
odt.doHeaders()
|
||||
odt.initDocument()
|
||||
odt.doConvert()
|
||||
odt.closeDocument()
|
||||
@@ -285,6 +288,7 @@ def testCoreToOdt_ConvertHeaders(mockGUI):
|
||||
# Header 4
|
||||
odt._text = "#### Section\n"
|
||||
odt.tokenizeText()
|
||||
odt.doHeaders()
|
||||
odt.initDocument()
|
||||
odt.doConvert()
|
||||
odt.closeDocument()
|
||||
@@ -296,8 +300,10 @@ def testCoreToOdt_ConvertHeaders(mockGUI):
|
||||
)
|
||||
|
||||
# Title
|
||||
odt._isFirst = True
|
||||
odt._text = "#! Title\n"
|
||||
odt.tokenizeText()
|
||||
odt.doHeaders()
|
||||
odt.initDocument()
|
||||
odt.doConvert()
|
||||
odt.closeDocument()
|
||||
@@ -311,6 +317,7 @@ def testCoreToOdt_ConvertHeaders(mockGUI):
|
||||
# Unnumbered chapter
|
||||
odt._text = "##! Prologue\n"
|
||||
odt.tokenizeText()
|
||||
odt.doHeaders()
|
||||
odt.initDocument()
|
||||
odt.doConvert()
|
||||
odt.closeDocument()
|
||||
@@ -605,6 +612,7 @@ def testCoreToOdt_ConvertParagraphs(mockGUI):
|
||||
"Text\n\n"
|
||||
)
|
||||
odt.tokenizeText()
|
||||
odt.doHeaders()
|
||||
odt.initDocument()
|
||||
odt.doConvert()
|
||||
odt.closeDocument()
|
||||
@@ -729,6 +737,7 @@ def testCoreToOdt_SaveFlat(mockGUI, fncPath, tstPaths):
|
||||
"Text\n\n"
|
||||
)
|
||||
odt.tokenizeText()
|
||||
odt.doHeaders()
|
||||
odt.initDocument()
|
||||
odt.doConvert()
|
||||
odt.closeDocument()
|
||||
@@ -768,6 +777,7 @@ def testCoreToOdt_SaveFull(mockGUI, fncPath, tstPaths):
|
||||
"Text\n\n"
|
||||
)
|
||||
odt.tokenizeText()
|
||||
odt.doHeaders()
|
||||
odt.initDocument()
|
||||
odt.doConvert()
|
||||
odt.closeDocument()
|
||||
|
||||
@@ -479,10 +479,11 @@ def testBuildSettings_Content(qtbot: QtBot, nwGUI: GuiMain):
|
||||
"""Test the Content Tab of the GuiBuildSettings dialog."""
|
||||
build = BuildSettings()
|
||||
|
||||
build.setValue("text.includeBodyText", False)
|
||||
build.setValue("text.includeSynopsis", False)
|
||||
build.setValue("text.includeComments", False)
|
||||
build.setValue("text.includeKeywords", False)
|
||||
build.setValue("text.includeBodyText", False)
|
||||
build.setValue("text.ignoredKeywords", "")
|
||||
|
||||
build.setValue("text.addNoteHeadings", False)
|
||||
|
||||
@@ -496,28 +497,35 @@ def testBuildSettings_Content(qtbot: QtBot, nwGUI: GuiMain):
|
||||
assert bSettings.toolStack.currentWidget() is contTab
|
||||
|
||||
# Check initial values
|
||||
assert contTab.incBodyText.isChecked() is False
|
||||
assert contTab.incSynopsis.isChecked() is False
|
||||
assert contTab.incComments.isChecked() is False
|
||||
assert contTab.incKeywords.isChecked() is False
|
||||
assert contTab.incBodyText.isChecked() is False
|
||||
assert contTab.ignoredKeywords.text() == ""
|
||||
|
||||
assert contTab.addNoteHead.isChecked() is False
|
||||
|
||||
# Toggle all
|
||||
# Toggle switches
|
||||
contTab.incBodyText.setChecked(True)
|
||||
contTab.incSynopsis.setChecked(True)
|
||||
contTab.incComments.setChecked(True)
|
||||
contTab.incKeywords.setChecked(True)
|
||||
contTab.incBodyText.setChecked(True)
|
||||
|
||||
contTab.addNoteHead.setChecked(True)
|
||||
|
||||
# Test cleanup of ignored keywords
|
||||
contTab.ignoredKeywords.setText("@stuff, @pizza, @object") # First two are invalid
|
||||
contTab._updateIgnoredKeywords("@custom") # Adding a new should trigger cleanup
|
||||
assert contTab.ignoredKeywords.text() in ("@custom, @object", "@object, @custom")
|
||||
|
||||
# Save values
|
||||
contTab.saveContent()
|
||||
|
||||
assert build.getBool("text.includeBodyText") is True
|
||||
assert build.getBool("text.includeSynopsis") is True
|
||||
assert build.getBool("text.includeComments") is True
|
||||
assert build.getBool("text.includeKeywords") is True
|
||||
assert build.getBool("text.includeBodyText") is True
|
||||
assert build.getStr("text.ignoredKeywords") in ("@custom, @object", "@object, @custom")
|
||||
|
||||
assert build.getBool("text.addNoteHeadings") is True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user