Improve handling of page breaks (#916)

* Remove page break from title and always allow for partition and chapter
* Move strip of format string into the Tokenizer class
* Fix page breaks in HTML for skip and sep
* Update documentation
* Update tests
* Allow page breaks before scene and section headers
* Never hide the scene header and instead default to skip line
This commit is contained in:
Veronica Berglyd Olsen
2021-10-24 22:09:41 +02:00
committed by GitHub
parent da2685131d
commit 299cde9cdf
12 changed files with 94 additions and 76 deletions
+12 -6
View File
@@ -30,13 +30,13 @@ title. See also the :ref:`a_fmt` section for more details about the markdown syn
The syntax for the four basic header types, and the two special header types, is listed in section
:ref:`a_fmt_head`. The meaning of the four levels for the structure of your novel is as follows:
**Header Level 1**
**Header Level 1: Partition**
This header level signifies that the text refers to a top level partition. This is useful when
you want to split the manuscript up into books, parts, or acts. These headings are not required.
The novel title itself should use the special header level one code explained in
:ref:`a_fmt_head`.
**Header Level 2**
**Header Level 2: Chapter**
This header level signifies a chapter level partition. Each time you want to start a new
chapter, you must add such a heading. If you choose to split your manuscript up into one
document per scene, you need a single chapter document with just the heading. You can of course
@@ -44,17 +44,21 @@ The syntax for the four basic header types, and the two special header types, is
chapter with a quote or other introductory text that isn't part of a scene, this is also where
you'd put that text.
**Header Level 3**
**Header Level 3: Scene**
This header level signifies a scene level partition. You must provide a title text, but the
title text can be replaced with a scene separator or just skipped entirely when you export your
manuscript.
**Header Level 4**
**Header Level 4: Section**
This header level signifies a sub-scene level partition, usually called a "section" in the
documentation and the user interface. These can be useful if you want to change tag references
mid-scene, like if you change the point-of-view character. You are free to use sections as you
wish, and can filter them out of the final manuscript just like with scene titles.
Page breaks are automatically added before level 1 and 2 headers when you export your project to a
format that supports page breaks, or when you print the document directly from the build tool. If
you want page breaks in other places, you have to specify them manually. See :ref:`a_fmt_break`.
.. tip::
There are multiple options of how to process novel titles when exporting the manuscript. For
instance, chapter numbers can be applied automatically, and so can scene numbers if you want
@@ -76,7 +80,7 @@ document, like so:
The title is by default centred on the page when exported. You can add more text to the page as you
wish, like for instance the author's name and details.
If you want an additional page inserted after the title page, starting on a fresh page, you can add
If you want an additional page of text after the title page, starting on a fresh page, you can add
``[NEW PAGE]`` on a line by itself, and continue the text after it. This will insert a page break
when the project is exported.
@@ -93,7 +97,9 @@ build tool to skip these chapters.
``##! Unnumbered Chapter Title``
There is a separate formatting feature for such chapters in the :guilabel:`Build Novel Project`
tool as well. See the :ref:`a_export` page for more details.
tool as well. See the :ref:`a_export` page for more details. When exporting to a format that
supports page breaks, also unnumbered chapters will have a page break added just like for normal
chapters.
.. Note::
Previously, you could also disable the automatic numbering of a chapter by adding an ``*`` as
+8
View File
@@ -218,3 +218,11 @@ headers of level two for novel documents, i.e. chapters, but not for project not
If you need to add a page break somewhere else, put the text ``[NEW PAGE]`` on a line by itself
before the text you wish to start on a new page.
Page breaks are automatically added to partition, chapter and unnumbered chapter headers of novel
documents. If you want such breaks for scenes and sections, you must add them manually.
.. note::
The page break code is applied to the text that follows. It adds a "page break before" mark to
the text when exporting to HTML or Open Document. This means that a ``[NEW PAGE]`` which has no
text following it will not result in a page break.
+1 -4
View File
@@ -34,10 +34,7 @@ the project. It has four columns:
**Column 4**
The fourth column shows the user-defined status or importance labels you've assigned to each
project item. See :ref:`a_ui_tree_status` for more details. By default, both the icon and the
label text is shown, but you can turn off the text label from :guilabel:`Preferences`. If the
text label is off, the text will instead appear in a tooltip when you hover your mouse over the
icon.
project item. See :ref:`a_ui_tree_status` for more details.
Right-clicking an item in the project tree will open a context menu under the cursor, displaying
a selection of actions that can be performed on the selected item.
+2 -3
View File
@@ -63,7 +63,6 @@ class ToHtml(Tokenizer):
self.doKeywords = True
self.doComments = doComments
self.doSynopsis = doSynopsis
return
def setStyles(self, cssStyles):
@@ -230,10 +229,10 @@ class ToHtml(Tokenizer):
tmpResult.append(f"<{h4}{hStyle}>{aNm}{tHead}</{h4}>\n")
elif tType == self.T_SEP:
tmpResult.append(f"<p class='sep'>{tText}</p>\n")
tmpResult.append(f"<p class='sep'{hStyle}>{tText}</p>\n")
elif tType == self.T_SKIP:
tmpResult.append("<p class='skip'>&nbsp;</p>\n")
tmpResult.append(f"<p class='skip'{hStyle}>&nbsp;</p>\n")
elif tType == self.T_TEXT:
tTemp = tText
+27 -26
View File
@@ -134,10 +134,10 @@ class Tokenizer():
self.firstScene = False # Flag to indicate that the first scene of the chapter
# This File
self.isNone = False
self.isNovel = False
self.isNote = False
self.isFirst = True
self.isNone = False # Document has unknown layout
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
# Error Handling
self.errData = []
@@ -156,30 +156,30 @@ class Tokenizer():
##
def setTitleFormat(self, fmtTitle):
self.fmtTitle = fmtTitle
self.fmtTitle = fmtTitle.strip()
return
def setChapterFormat(self, fmtChapter):
self.fmtChapter = fmtChapter
self.fmtChapter = fmtChapter.strip()
return
def setUnNumberedFormat(self, fmtUnNum):
self.fmtUnNum = fmtUnNum
self.fmtUnNum = fmtUnNum.strip()
return
def setSceneFormat(self, fmtScene, hideScene):
self.fmtScene = fmtScene
self.fmtScene = fmtScene.strip()
self.hideScene = hideScene
return
def setSectionFormat(self, fmtSection, hideSection):
self.fmtSection = fmtSection
self.fmtSection = fmtSection.strip()
self.hideSection = hideSection
return
def setFont(self, textFont, textSize, textFixed=False):
self.textFont = textFont
self.textSize = round(int(textSize))
self.textFont = textFont
self.textSize = round(int(textSize))
self.textFixed = textFixed
return
@@ -446,8 +446,6 @@ class Tokenizer():
elif aLine[:2] == "# ":
if self.isNovel:
sAlign |= self.A_CENTRE
if self.isNovel and not self.isFirst:
sAlign |= self.A_PBB
self.theTokens.append((
@@ -457,7 +455,7 @@ class Tokenizer():
tmpMarkdown.append("%s\n" % aLine)
elif aLine[:3] == "## ":
if self.isNovel and not self.isFirst:
if self.isNovel:
sAlign |= self.A_PBB
self.theTokens.append((
@@ -486,9 +484,6 @@ class Tokenizer():
else:
tStyle = self.T_HEAD1
if self.isNovel and not self.isFirst:
sAlign |= self.A_PBB
self.theTokens.append((
tStyle, nLine, aLine[3:].strip(), None, sAlign | self.A_CENTRE
))
@@ -498,12 +493,10 @@ class Tokenizer():
elif aLine[:4] == "##! ":
if self.isNovel:
tStyle = self.T_UNNUM
sAlign |= self.A_PBB
else:
tStyle = self.T_HEAD2
if self.isNovel and not self.isFirst:
sAlign |= self.A_PBB
self.theTokens.append((
tStyle, nLine, aLine[4:].strip(), None, sAlign
))
@@ -571,6 +564,14 @@ class Tokenizer():
if self.isFirst and self.theTokens:
self.isFirst = False
# Make sure the token array doesn't start with a page break
# on the very first page, adding a blank first page.
if self.theTokens[0][4] & self.A_PBB:
tToken = self.theTokens[0]
self.theTokens[0] = (
tToken[0], tToken[1], tToken[2], tToken[3], tToken[4] & ~self.A_PBB
)
# Always add an empty line at the end of the file
self.theTokens.append((
self.T_EMPTY, nLine, "", None, self.A_NONE
@@ -665,7 +666,7 @@ class Tokenizer():
)
else:
self.theTokens[n] = (
self.T_SKIP, tToken[1], "", None, self.A_NONE
self.T_SKIP, tToken[1], "", None, tToken[4]
)
elif tTemp == self.fmtScene:
if self.firstScene:
@@ -674,11 +675,11 @@ class Tokenizer():
)
else:
self.theTokens[n] = (
self.T_SEP, tToken[1], tTemp, None, self.A_CENTRE
self.T_SEP, tToken[1], tTemp, None, tToken[4] | self.A_CENTRE
)
else:
self.theTokens[n] = (
tToken[0], tToken[1], tTemp, None, self.A_NONE
tToken[0], tToken[1], tTemp, None, tToken[4]
)
# Definitely no longer the first scene
@@ -694,15 +695,15 @@ class Tokenizer():
)
elif tTemp == "" and not self.hideSection:
self.theTokens[n] = (
self.T_SKIP, tToken[1], "", None, self.A_NONE
self.T_SKIP, tToken[1], "", None, tToken[4]
)
elif tTemp == self.fmtSection:
self.theTokens[n] = (
self.T_SEP, tToken[1], tTemp, None, self.A_CENTRE
self.T_SEP, tToken[1], tTemp, None, tToken[4] | self.A_CENTRE
)
else:
self.theTokens[n] = (
tToken[0], tToken[1], tTemp, None, self.A_NONE
tToken[0], tToken[1], tTemp, None, tToken[4]
)
return True
+6 -6
View File
@@ -643,11 +643,11 @@ class GuiBuildNovel(QDialog):
tStart = int(time())
# Get Settings
fmtTitle = self.fmtTitle.text().strip()
fmtChapter = self.fmtChapter.text().strip()
fmtUnnumbered = self.fmtUnnumbered.text().strip()
fmtScene = self.fmtScene.text().strip()
fmtSection = self.fmtSection.text().strip()
fmtTitle = self.fmtTitle.text()
fmtChapter = self.fmtChapter.text()
fmtUnnumbered = self.fmtUnnumbered.text()
fmtScene = self.fmtScene.text()
fmtSection = self.fmtSection.text()
textFont = self.textFont.text()
textSize = self.textSize.value()
lineHeight = self.lineHeight.value()
@@ -675,7 +675,7 @@ class GuiBuildNovel(QDialog):
bldObj.setTitleFormat(fmtTitle)
bldObj.setChapterFormat(fmtChapter)
bldObj.setUnNumberedFormat(fmtUnnumbered)
bldObj.setSceneFormat(fmtScene, fmtScene == "")
bldObj.setSceneFormat(fmtScene, False)
bldObj.setSectionFormat(fmtSection, fmtSection == "")
bldObj.setFont(textFont, textSize, textFixed)
@@ -1,8 +1,8 @@
<?xml version='1.0' encoding='utf-8'?>
<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text">
<office:meta>
<meta:creation-date>2021-08-13T18:57:51</meta:creation-date>
<meta:generator>novelWriter/1.5-alpha0</meta:generator>
<meta:creation-date>2021-10-24T21:44:56</meta:creation-date>
<meta:generator>novelWriter/1.6-alpha0</meta:generator>
</office:meta>
<office:font-face-decls>
<style:font-face style:name="Liberation Serif" style:font-pitch="variable"/>
@@ -59,6 +59,9 @@
<style:header-footer-properties fo:min-height="0.600cm" fo:margin-left="0.000cm" fo:margin-right="0.000cm" fo:margin-bottom="0.500cm"/>
</style:header-style>
</style:page-layout>
<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Heading_2">
<style:paragraph-properties fo:break-before="page"/>
</style:style>
</office:automatic-styles>
<office:master-styles>
<style:master-page style:name="Standard" style:page-layout-name="PM1">
@@ -74,7 +77,7 @@
<office:text>
<text:h text:style-name="Heading_2" text:outline-level="2">Chapter One</text:h>
<text:p text:style-name="Text_Body">Text</text:p>
<text:h text:style-name="Heading_2" text:outline-level="2">Chapter Two</text:h>
<text:h text:style-name="P1" text:outline-level="2">Chapter Two</text:h>
<text:p text:style-name="Text_Body">Text</text:p>
</office:text>
</office:body>
@@ -3,12 +3,16 @@
<office:font-face-decls>
<style:font-face style:name="Liberation Serif" style:font-pitch="variable"/>
</office:font-face-decls>
<office:automatic-styles/>
<office:automatic-styles>
<style:style style:name="P1" style:family="paragraph" style:parent-style-name="Heading_2">
<style:paragraph-properties fo:break-before="page"/>
</style:style>
</office:automatic-styles>
<office:body>
<office:text>
<text:h text:style-name="Heading_2" text:outline-level="2">Chapter One</text:h>
<text:p text:style-name="Text_Body">Text</text:p>
<text:h text:style-name="Heading_2" text:outline-level="2">Chapter Two</text:h>
<text:h text:style-name="P1" text:outline-level="2">Chapter Two</text:h>
<text:p text:style-name="Text_Body">Text</text:p>
</office:text>
</office:body>
@@ -34,12 +34,12 @@ article {width: 800px; margin: 40px auto;}
<p style='text-align: center;'>“Fusce maximus felis libero”</p>
<h1 style='page-break-before: always;'>Chapter 1: Chapter One</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque at aliquam quam. Praesent magna nunc, lacinia sit amet quam eget, aliquet ultrices justo. Morbi ornare enim et lorem rutrum finibus ut eu dolor. Aliquam a orci odio. Ut ultrices sem quis massa placerat, eget mollis nisl cursus. Cras vel sagittis justo. Ut non ultricies leo. Maecenas rutrum velit in est varius, et egestas massa pulvinar.</p>
<p class='sep'>* * *</p>
<p class='sep' style='text-align: center;'>* * *</p>
<p>Aenean ut placerat velit. Etiam laoreet ullamcorper risus, eget lobortis enim scelerisque non. Suspendisse id maximus nunc, et mollis sapien. Curabitur vel semper sapien, non pulvinar dolor. Etiam finibus nisi vel mi molestie consectetur. Donec quis ante nunc. Mauris ut leo ipsum. Vestibulum est neque, hendrerit nec neque a, ullamcorper lobortis tellus. Fusce sollicitudin purus quis congue bibendum. Aliquam condimentum ipsum tristique blandit tristique. Donec pulvinar neque ac suscipit malesuada.</p>
<p>Aliquam ut nisl arcu. Ut ultricies, lorem dignissim rutrum convallis, risus orci tempus lectus, congue feugiat sem lectus vitae odio. Duis sit amet justo finibus, hendrerit nulla at, ullamcorper enim. Praesent vel tellus sit amet tellus vulputate bibendum. Morbi eleifend sagittis sem, ac volutpat ante congue non. In hac habitasse platea dictumst. Morbi lobortis fermentum elit, dignissim sagittis ligula volutpat lacinia. Vestibulum eu interdum odio. Integer ac purus commodo metus congue tempor non at urna. Sed eget tortor vel quam viverra egestas. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec non convallis mauris, ac feugiat ex.</p>
<p>Integer vel libero ipsum. Donec varius aliquam libero, sit amet commodo urna hendrerit non. Nullam quis erat mollis nunc viverra volutpat tincidunt in odio. Nam vitae quam sem. Aliquam suscipit nulla non lorem pharetra semper. Ut suscipit erat eu ligula accumsan ultrices. Phasellus nisl tellus, placerat sed laoreet id, consectetur nec dolor. Sed fringilla ipsum id dapibus posuere. Aenean finibus pharetra tincidunt. Ut molestie malesuada nulla, id posuere lorem tincidunt eu. Aliquam tempor eros a est vulputate, scelerisque pulvinar ipsum fermentum. In hac habitasse platea dictumst.</p>
<p>Curabitur congue, justo quis interdum fermentum, tellus nulla imperdiet sapien, eu interdum enim tellus condimentum metus. Vivamus nunc velit, dignissim ut ultrices sit amet, ultricies quis enim. Donec ut vestibulum neque. Vivamus semper neque id ex ullamcorper varius. Fusce mattis nibh viverra lorem sagittis, et tempor arcu congue. Suspendisse sit amet felis sed urna facilisis mattis eget vitae arcu. Proin eu magna hendrerit, tristique sem maximus, placerat diam. Nulla tristique sed velit sit amet varius. Etiam vel ornare magna, in vulputate arcu. Cras velit orci, tincidunt sed volutpat cursus, bibendum vel sem. Nunc vulputate pharetra tortor, ac consectetur neque tincidunt sit amet. Nulla ornare mi sed mi dignissim ultricies. Ut tincidunt bibendum mauris, sed elementum ex vulputate vel. Mauris fermentum, felis nec vehicula congue, felis lorem facilisis erat, a dictum dolor augue vitae quam. Maecenas rutrum tortor nec consequat eleifend.</p>
<p class='sep'>* * *</p>
<p class='sep' style='text-align: center;'>* * *</p>
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Integer sapien nulla, dictum at lacus a, dignissim consectetur dolor. Nunc vel eleifend lacus, eu dapibus orci. Vestibulum facilisis bibendum aliquam. Aliquam posuere, turpis ac bibendum varius, sem tellus venenatis risus, in elementum massa enim ac lorem. Integer in sem ac diam blandit ultricies ut in nulla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam sit amet erat est. Curabitur vitae cursus justo, sit amet placerat dolor. Vivamus eu felis hendrerit, tincidunt massa rutrum, maximus arcu. Pellentesque commodo justo odio, vel rutrum nulla tincidunt eu. Integer non neque condimentum, convallis diam non, varius ligula. Aliquam eget sapien mauris. Aenean pharetra nunc nisi, vel maximus ante tristique sit amet. Aliquam risus metus, interdum non odio eu, consectetur lacinia sapien.</p>
<p>Proin vitae gravida nisl. Integer viverra orci turpis, sit amet pretium ligula facilisis consequat. Nulla interdum commodo metus, mollis consequat dui tincidunt et. Proin consequat bibendum justo id commodo. Fusce fermentum nunc turpis, eu vestibulum risus feugiat ut. Sed scelerisque vel ligula ut interdum. Suspendisse ac blandit ligula, sagittis fringilla dolor. In tincidunt convallis diam et ornare. Aenean id dignissim est, ut rhoncus quam. Donec vitae nisl velit. In convallis nibh ut augue dignissim, eu elementum quam cursus. Phasellus in lectus lorem. Curabitur in pellentesque nisi, at gravida sapien. Sed cursus justo volutpat lacus placerat, sit amet dignissim turpis commodo. Aliquam vitae orci eget nulla posuere condimentum in ut felis.</p>
<p>Nulla accumsan ante in pulvinar efficitur. Nulla non velit quis urna hendrerit bibendum. Suspendisse ultrices ante eu justo malesuada, sed fermentum enim rutrum. Nunc fermentum pharetra felis, vitae sollicitudin quam rutrum porta. Aliquam fringilla velit a mi laoreet, et luctus est rutrum. In gravida non ipsum sit amet tempus. Curabitur et eleifend purus. Nulla facilisi.</p>
@@ -48,19 +48,19 @@ article {width: 800px; margin: 40px auto;}
<p>Ut et consequat enim, quis ornare nibh. In lectus neque, mollis et suscipit et, vestibulum vitae augue. Praesent id ante sit amet odio venenatis placerat a at erat. Sed sed metus sed nisi dictum varius. Integer tincidunt fermentum purus ac porta. Fusce porttitor non risus eget tristique. Donec augue nunc, maximus at fermentum vel, varius et neque. Ut sed consectetur mauris. Quisque ipsum enim, porttitor vitae imperdiet sit amet, tempor et mauris. Aliquam malesuada tincidunt lectus quis blandit. Sed commodo orci felis, quis ultrices tellus facilisis sed. Nunc vel varius est. Duis ullamcorper eu metus in pulvinar. Morbi at sapien dictum, rutrum mauris eget, interdum tellus.</p>
<h1 style='page-break-before: always;'>Chapter 2: Chapter Two</h1>
<p>Curabitur a elit posuere, varius ex et, convallis neque. Phasellus sagittis pharetra sem vitae dapibus. Curabitur varius lorem non pulvinar congue. Vestibulum pharetra fermentum leo, sed faucibus eros placerat quis. In hac habitasse platea dictumst. Donec metus massa, rutrum quis consequat et, tincidunt ac felis. Duis mollis metus ac nunc tincidunt blandit. Ut aliquet velit eu odio pharetra condimentum. Integer rutrum lacus orci, id venenatis libero accumsan at.</p>
<p class='sep'>* * *</p>
<p class='sep' style='text-align: center;'>* * *</p>
<p>Aenean ut libero ut lectus porttitor rhoncus vel et massa. Nam pretium, nibh et varius vehicula, urna metus blandit eros, euismod pharetra diam diam et libero. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean tincidunt lacus vitae nibh elementum eleifend. Sed rutrum condimentum sem quis blandit. Duis imperdiet libero metus, quis convallis quam faucibus a. Nulla ligula est, semper quis sollicitudin et, pretium id justo. Curabitur pharetra risus eget consectetur commodo. Duis mattis arcu non est condimentum, id venenatis risus volutpat. Pellentesque aliquet mauris non mauris porttitor ultrices. Phasellus ut vestibulum mi. Suspendisse malesuada metus lorem, a malesuada orci rhoncus a. Praesent euismod convallis ante, lacinia tincidunt ex egestas id. Praesent sit amet efficitur sapien. Morbi tincidunt volutpat nunc sed dictum. Aliquam ultrices metus id fermentum lobortis.</p>
<p>Pellentesque id sagittis dui. Praesent ut nisi sit amet libero euismod ornare. Vestibulum vehicula, lorem eget aliquet imperdiet, eros nulla iaculis mi, vel bibendum est dui sed orci. Nullam vitae lorem rutrum, euismod lacus id, ullamcorper lectus. Duis nec commodo mi, a fringilla diam. Vestibulum molestie nibh tristique, viverra augue non, aliquet metus. Phasellus a tellus ac nisl tempor aliquet. Nulla vitae sapien rutrum augue ornare ultrices a quis nisi. Sed pulvinar tincidunt ex. Fusce vel sem vitae ante pellentesque lobortis.</p>
<p>Maecenas ullamcorper lacus nec turpis finibus aliquet eget rutrum augue. Integer lorem erat, faucibus non lacus lacinia, pulvinar egestas felis. Proin rutrum nunc eget nulla varius, id blandit mauris tincidunt. Donec sit amet ullamcorper nisi, ut efficitur mi. Aliquam aliquet, nulla eget rhoncus tristique, justo lorem consectetur dui, id ornare leo odio sed tellus. Curabitur interdum velit a turpis condimentum venenatis. Nunc rhoncus sem ac augue auctor, nec malesuada ex fringilla. Vestibulum egestas diam sed leo consectetur vulputate quis eget enim. Nam tincidunt metus sit amet maximus ullamcorper. Sed placerat velit vitae massa efficitur viverra. Etiam eleifend dignissim ante, sed luctus nisl tristique a. In vestibulum pharetra dolor in molestie. Vivamus auctor massa ac magna imperdiet, sit amet iaculis turpis finibus.</p>
<p>Aenean dapibus vulputate purus, sit amet tempor nunc suscipit consequat. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris auctor congue eros, non pellentesque neque dapibus ac. Vestibulum non leo nec urna lacinia eleifend quis et diam. Praesent eu nisi magna. Nulla at magna massa. Suspendisse porta varius scelerisque. Duis at auctor dolor, non dapibus urna. Nunc venenatis feugiat magna non molestie. Aliquam non ornare ex. Quisque eu ultrices velit, quis pellentesque eros. Phasellus eleifend, elit id imperdiet aliquam, nulla quam molestie turpis, at egestas odio ante et tortor. Suspendisse fringilla condimentum justo, at aliquet odio aliquam ac.</p>
<p class='sep'>* * *</p>
<p class='sep' style='text-align: center;'>* * *</p>
<p>Nam tempor blandit magna laoreet aliquet. Vestibulum auctor posuere leo, ac gravida nisi rhoncus varius. Aenean posuere dolor vitae condimentum volutpat. Donec egestas volutpat risus, quis luctus justo. Nullam viverra dui et auctor pretium. Ut ullamcorper velit urna, sed imperdiet massa convallis a. Suspendisse efficitur, ipsum nec cursus pulvinar, eros urna posuere diam, nec elementum mi felis vitae sapien.</p>
<p>Duis efficitur metus pulvinar, molestie magna eget, feugiat dui. Fusce convallis vehicula ipsum convallis blandit. Duis eros risus, malesuada eu imperdiet in, hendrerit ac metus. Vestibulum id justo gravida, dignissim nibh non, iaculis diam. Fusce accumsan est ut massa porta ultricies. Nulla vitae justo in tortor laoreet mollis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eu libero justo. Vivamus aliquet placerat est, et auctor eros posuere venenatis. Nunc quam diam, tincidunt ac aliquet in, fermentum sit amet lectus. Proin commodo tincidunt blandit. Quisque erat arcu, semper nec dui non, consectetur gravida ipsum. Nullam pretium consectetur elit at condimentum.</p>
<p>Etiam sagittis, erat vitae accumsan tempor, neque augue scelerisque nulla, ut ultrices justo urna sit amet augue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Aenean at pulvinar tortor. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Cras vel porta quam. Nullam eu mauris mollis, vehicula justo vel, placerat sapien. Phasellus viverra elit et vestibulum pharetra. Vestibulum commodo fermentum leo, eu porta nisi aliquam eget. Nulla tempus porttitor nisi nec mollis. Nam non mollis turpis. Nam finibus leo a bibendum tincidunt. Donec commodo velit magna, ac semper sapien mattis id. Proin sem velit, lobortis quis ultricies id, pharetra et lectus. Vestibulum condimentum neque vitae mi dapibus mollis. Mauris luctus vel sapien vitae hendrerit.</p>
<p>Aenean vestibulum magna placerat fermentum tempus. Nam auctor condimentum nunc, in elementum quam ornare a. Etiam in ipsum elit. Proin pharetra, dolor sollicitudin pellentesque congue, lorem dolor ultricies magna, non iaculis risus nisl dictum diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Vivamus vel euismod nibh, et lobortis dolor. Maecenas dui odio, gravida nec molestie ut, feugiat ut arcu. Pellentesque risus sapien, gravida a convallis quis, ullamcorper porttitor sapien.</p>
<p>Donec ipsum eros, vestibulum sit amet cursus eget, iaculis quis dolor. Pellentesque magna augue, tristique dapibus mi vitae, molestie venenatis enim. Nam malesuada, turpis volutpat rhoncus ullamcorper, justo est eleifend orci, ut luctus risus ex rutrum arcu. Sed mi elit, feugiat rhoncus ornare sed, porta id leo. Pellentesque feugiat nulla tincidunt erat suscipit, eu congue lacus hendrerit. Morbi pulvinar enim sed consequat auctor. Ut eleifend enim sem, vitae euismod ex ultricies sit amet. Curabitur eu efficitur nisi, suscipit finibus sapien. In sodales blandit erat, vestibulum pulvinar ante volutpat nec. Vivamus dictum non libero at molestie. Donec sit amet neque in ante convallis pretium. Nunc vel iaculis dui.</p>
<p>Phasellus eu nunc ut nunc faucibus laoreet. Aliquam at magna risus. Praesent lobortis, risus finibus semper varius, magna purus vestibulum eros, at pulvinar sapien enim a ex. In scelerisque malesuada ex, sit amet egestas neque condimentum sed. Praesent vulputate efficitur massa. Cras at accumsan ligula. In elementum lectus eget blandit dictum. Nam vitae libero ut justo eleifend rutrum ac nec arcu. Aliquam sodales in quam congue vestibulum. Aliquam in accumsan sapien. Quisque lobortis nisl nisi, vitae bibendum turpis efficitur sed. Vestibulum tempor nulla eget nisi convallis, blandit sagittis ipsum convallis. Donec odio nibh, ultrices quis odio in, mollis euismod libero.</p>
<p class='sep'>* * *</p>
<p class='sep' style='text-align: center;'>* * *</p>
<p>Praesent eget est porta, dictum ante in, egestas risus. Mauris risus mauris, consequat aliquam mauris et, feugiat iaculis ipsum. Aliquam arcu ipsum, fermentum ut arcu sed, lobortis euismod sem. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In sed felis auctor, rhoncus dui ac, consequat dolor. Integer volutpat libero sed nisl aliquet varius. Suspendisse et lorem sapien. Proin id ultrices nibh, ac suscipit diam. Suspendisse placerat varius porttitor. Curabitur elementum sed enim ultrices imperdiet.</p>
<p>In ut lobortis lacus, nec luctus arcu. Vivamus condimentum sapien a ipsum malesuada sodales. Donec et vestibulum risus. Integer dictum euismod eros id tincidunt. Aliquam sagittis leo vitae consequat fermentum. Donec maximus ex eu ex iaculis porta. Praesent pharetra lacinia risus, et eleifend diam commodo non. Sed feugiat ipsum ut orci sagittis, quis faucibus lectus blandit. Sed tellus quam, gravida vitae laoreet quis, tempus lobortis dui. Vivamus semper accumsan ullamcorper. Praesent tempus pretium eros, non elementum risus. Pellentesque odio quam, auctor quis ex non, vulputate egestas dolor. Nunc luctus enim ut justo sodales consectetur. Sed aliquet a mauris vel posuere.</p>
<p>Donec luctus lectus efficitur, blandit nisi vitae, dignissim tellus. Pellentesque euismod pharetra augue gravida hendrerit. Quisque nisi mi, mattis ac nisi non, maximus malesuada ante. Nulla lobortis, diam eu ornare ornare, tellus enim feugiat arcu, non vestibulum tortor nunc eu justo. Integer blandit felis justo, eu semper est scelerisque vel. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nam ultricies, nisi vel elementum commodo, nisl dolor tincidunt magna, sed varius est nunc at lectus. Aliquam dolor tortor, sodales placerat ultricies quis, sodales quis sapien. Duis ullamcorper sollicitudin risus at mattis. Integer consequat et nunc at condimentum. Pellentesque cursus congue augue, non suscipit lectus sodales ut. Nam a mi bibendum, blandit nisl eu, accumsan nunc. Aliquam a ex mauris. Sed nec sem quis arcu dignissim tempus eget et turpis. Ut sed ex nec ipsum ultrices lobortis.</p>
+2 -2
View File
@@ -75,7 +75,7 @@ def testCoreToHtml_ConvertFormat(mockGUI):
theHtml.tokenizeText()
theHtml.doConvert()
assert theHtml.theResult == (
"<h1 class='title' style='text-align: center; page-break-before: always;'>Title</h1>\n"
"<h1 class='title' style='text-align: center;'>Title</h1>\n"
)
# Unnumbered
@@ -276,7 +276,7 @@ def testCoreToHtml_ConvertDirect(mockGUI):
(theHtml.T_EMPTY, 1, "", None, theHtml.A_NONE),
]
theHtml.doConvert()
assert theHtml.theResult == "<p class='sep'>* * *</p>\n"
assert theHtml.theResult == "<p class='sep' style='text-align: center;'>* * *</p>\n"
# Skip
theHtml.theTokens = [
+1 -1
View File
@@ -374,7 +374,7 @@ def testCoreToken_HeaderFormat(mockGUI):
theToken.tokenizeText()
assert theToken.theTokens == [
(Tokenizer.T_TITLE, 1, "Title", None, Tokenizer.A_CENTRE | Tokenizer.A_PBB),
(Tokenizer.T_TITLE, 1, "Title", None, Tokenizer.A_CENTRE),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_NONE),
]
assert theToken.theMarkdown[-1] == "#! Title\n\n"
+18 -18
View File
@@ -308,7 +308,7 @@ def testCoreToOdt_Convert(mockGUI):
assert theDoc.getErrors() == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:h text:style-name="P3">Title</text:h>'
'<text:h text:style-name="Title">Title</text:h>'
'</office:text>'
)
@@ -445,9 +445,9 @@ def testCoreToOdt_Convert(mockGUI):
assert theDoc.getErrors() == []
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:p text:style-name="P4">* * *</text:p>'
'<text:p text:style-name="P3">* * *</text:p>'
'<text:p text:style-name="Text_Body">Text</text:p>'
'<text:p text:style-name="P4">* * *</text:p>'
'<text:p text:style-name="P3">* * *</text:p>'
'<text:p text:style-name="Text_Body">Text</text:p>'
'</office:text>'
)
@@ -491,26 +491,26 @@ def testCoreToOdt_Convert(mockGUI):
assert xmlToText(theDoc._xText) == (
'<office:text>'
'<text:h text:style-name="Heading_3" text:outline-level="3">Scene</text:h>'
'<text:p text:style-name="P5"><text:span text:style-name="T4">'
'<text:p text:style-name="P4"><text:span text:style-name="T4">'
'Point of View:</text:span> Jane</text:p>'
'<text:p text:style-name="P6"><text:span text:style-name="T4">'
'<text:p text:style-name="P5"><text:span text:style-name="T4">'
'Characters:</text:span> John</text:p>'
'<text:p text:style-name="Text_Meta"><text:span text:style-name="T4">'
'Plot:</text:span> Main</text:p>'
'<text:p text:style-name="P7">Right align</text:p>'
'<text:p text:style-name="P6">Right align</text:p>'
'<text:p text:style-name="Text_Body">Left Align</text:p>'
'<text:p text:style-name="P4">Centered</text:p>'
'<text:p text:style-name="P8">Left indent</text:p>'
'<text:p text:style-name="P9">Right indent</text:p>'
'<text:p text:style-name="P3">Centered</text:p>'
'<text:p text:style-name="P7">Left indent</text:p>'
'<text:p text:style-name="P8">Right indent</text:p>'
'</office:text>'
)
assert getStyle("P4")._pAttr["margin-bottom"] == ["fo", "0.000cm"]
assert getStyle("P5")._pAttr["margin-bottom"] == ["fo", "0.000cm"]
assert getStyle("P6")._pAttr["margin-bottom"] == ["fo", "0.000cm"]
assert getStyle("P6")._pAttr["margin-top"] == ["fo", "0.000cm"]
assert getStyle("P7")._pAttr["text-align"] == ["fo", "right"]
assert getStyle("P4")._pAttr["text-align"] == ["fo", "center"]
assert getStyle("P8")._pAttr["margin-left"] == ["fo", "1.693cm"]
assert getStyle("P9")._pAttr["margin-right"] == ["fo", "1.693cm"]
assert getStyle("P5")._pAttr["margin-top"] == ["fo", "0.000cm"]
assert getStyle("P6")._pAttr["text-align"] == ["fo", "right"]
assert getStyle("P3")._pAttr["text-align"] == ["fo", "center"]
assert getStyle("P7")._pAttr["margin-left"] == ["fo", "1.693cm"]
assert getStyle("P8")._pAttr["margin-right"] == ["fo", "1.693cm"]
# Justified
theDoc.theText = (
@@ -529,11 +529,11 @@ def testCoreToOdt_Convert(mockGUI):
'<office:text>'
'<text:h text:style-name="Heading_3" text:outline-level="3">Scene</text:h>'
'<text:p text:style-name="Text_Body">Regular paragraph</text:p>'
'<text:p text:style-name="P10">with<text:line-break/>break</text:p>'
'<text:p text:style-name="P10">Left Align</text:p>'
'<text:p text:style-name="P9">with<text:line-break/>break</text:p>'
'<text:p text:style-name="P9">Left Align</text:p>'
'</office:text>'
)
assert getStyle("P10")._pAttr["text-align"] == ["fo", "left"]
assert getStyle("P9")._pAttr["text-align"] == ["fo", "left"]
# Page Breaks
theDoc.theText = (