diff --git a/nw/core/tohtml.py b/nw/core/tohtml.py
index 46c7d8b6..9c17aeca 100644
--- a/nw/core/tohtml.py
+++ b/nw/core/tohtml.py
@@ -173,16 +173,12 @@ class ToHtml(Tokenizer):
aStyle.append("text-align: justify;")
if tStyle & self.A_PBB:
aStyle.append("page-break-before: always;")
- if tStyle & self.A_PBB_AV:
- aStyle.append("page-break-before: avoid;")
- if tStyle & self.A_PBB_NO:
- aStyle.append("page-break-before: never;")
+ if tStyle & self.A_PBB_AUT:
+ aStyle.append("page-break-before: auto;")
if tStyle & self.A_PBA:
aStyle.append("page-break-after: always;")
- if tStyle & self.A_PBA_AV:
- aStyle.append("page-break-after: avoid;")
- if tStyle & self.A_PBA_NO:
- aStyle.append("page-break-after: never;")
+ if tStyle & self.A_PBA_AUT:
+ aStyle.append("page-break-after: auto;")
if len(aStyle) > 0:
hStyle = " style='%s'" % (" ".join(aStyle))
@@ -268,22 +264,23 @@ class ToHtml(Tokenizer):
if not self.cssStyles:
return theStyles
- if self.doJustify:
- theStyles.append(r"p {text-align: justify;}")
- else:
- theStyles.append(r"p {text-align: left;}")
+ textAlign = "justify" if self.doJustify else "left"
- theStyles.append(r"h1, h2 {color: rgb(66, 113, 174);}")
- theStyles.append(r"h3, h4 {color: rgb(50, 50, 50);}")
- theStyles.append(r"h1, h2, h3, h4 {page-break-after: avoid;}")
- theStyles.append(r"a {color: rgb(66, 113, 174);}")
- theStyles.append(r".title {font-size: 2.5em;}")
- theStyles.append(r".tags {color: rgb(245, 135, 31); font-weight: bold;}")
- theStyles.append(r".break {text-align: left;}")
- theStyles.append(r".sep {text-align: center; margin-top: 1em; margin-bottom: 1em;}")
- theStyles.append(r".skip {margin-top: 1em; margin-bottom: 1em;}")
- theStyles.append(r".synopsis {font-style: italic;}")
- theStyles.append(r".comment {font-style: italic; color: rgb(100, 100, 100);}")
+ theStyles.append("body {font-family: '%s'; font-size: %dpt}" % (
+ self.textFont, self.textSize)
+ )
+ theStyles.append("p {text-align: %s;}" % textAlign)
+ theStyles.append("h1, h2 {color: rgb(66, 113, 174);}")
+ theStyles.append("h3, h4 {color: rgb(50, 50, 50);}")
+ theStyles.append("h1, h2, h3, h4 {page-break-after: avoid;}")
+ theStyles.append("a {color: rgb(66, 113, 174);}")
+ theStyles.append(".title {font-size: 2.5em;}")
+ theStyles.append(".tags {color: rgb(245, 135, 31); font-weight: bold;}")
+ theStyles.append(".break {text-align: left;}")
+ theStyles.append(".sep {text-align: center; margin-top: 1em; margin-bottom: 1em;}")
+ theStyles.append(".skip {margin-top: 1em; margin-bottom: 1em;}")
+ theStyles.append(".synopsis {font-style: italic;}")
+ theStyles.append(".comment {font-style: italic; color: rgb(100, 100, 100);}")
return theStyles
diff --git a/nw/core/tokenizer.py b/nw/core/tokenizer.py
index 4e0c6290..04ded5c1 100644
--- a/nw/core/tokenizer.py
+++ b/nw/core/tokenizer.py
@@ -67,11 +67,9 @@ class Tokenizer():
A_CENTRE = 0x0004 # Centred
A_JUSTIFY = 0x0008 # Justified
A_PBB = 0x0010 # Page break before always
- A_PBB_AV = 0x0020 # Page break before avoid
- A_PBB_NO = 0x0040 # Page break before never
- A_PBA = 0x0080 # Page break after always
- A_PBA_AV = 0x0100 # Page break after avoid
- A_PBA_NO = 0x0200 # Page break after avoid
+ A_PBB_AUT = 0x0020 # Page break before auto
+ A_PBA = 0x0040 # Page break after always
+ A_PBA_AUT = 0x0080 # Page break after auto
def __init__(self, theProject, theParent):
@@ -628,7 +626,7 @@ class Tokenizer():
tToken[1],
tToken[2],
tToken[3],
- self.A_PBB_NO | self.A_CENTRE
+ self.A_PBB_AUT | self.A_CENTRE
)
else:
self.theTokens[n] = (
diff --git a/nw/core/toodt.py b/nw/core/toodt.py
index 69b92157..23721e8e 100644
--- a/nw/core/toodt.py
+++ b/nw/core/toodt.py
@@ -30,6 +30,7 @@ import os
from lxml import etree
from hashlib import sha256
+from datetime import datetime
from nw.core.tokenizer import Tokenizer
@@ -39,6 +40,7 @@ XML_NS = {
"office" : "urn:oasis:names:tc:opendocument:xmlns:office:1.0",
"style" : "urn:oasis:names:tc:opendocument:xmlns:style:1.0",
"text" : "urn:oasis:names:tc:opendocument:xmlns:text:1.0",
+ "meta" : "urn:oasis:names:tc:opendocument:xmlns:meta:1.0",
"fo" : "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0",
}
@@ -113,12 +115,19 @@ class ToOdt(Tokenizer):
_mkTag("office", "mimetype") : "application/vnd.oasis.opendocument.text",
}
self._xRoot = etree.Element(_mkTag("office", "document"), attrib=rAttr, nsmap=XML_NS)
+ self._xMeta = etree.SubElement(self._xRoot, _mkTag("office", "meta"))
self._xFont = etree.SubElement(self._xRoot, _mkTag("office", "font-face-decls"))
self._xStyl = etree.SubElement(self._xRoot, _mkTag("office", "styles"))
self._xAuto = etree.SubElement(self._xRoot, _mkTag("office", "automatic-styles"))
self._xBody = etree.SubElement(self._xRoot, _mkTag("office", "body"))
self._xText = etree.SubElement(self._xBody, _mkTag("office", "text"))
+ # Meta Data
+ xMeta = etree.SubElement(self._xMeta, _mkTag("meta", "creation-date"))
+ xMeta.text = datetime.now().isoformat()
+ xMeta = etree.SubElement(self._xMeta, _mkTag("meta", "generator"))
+ xMeta.text = f"novelWriter/{nw.__version__}"
+
# Re-Init Variables
self._fontFamily = self.textFont
if len(self.textFont.split()) > 1:
@@ -166,8 +175,12 @@ class ToOdt(Tokenizer):
oStyle.setTextAlign("justify")
if tStyle & self.A_PBB:
oStyle.setBreakBefore("page")
+ if tStyle & self.A_PBB_AUT:
+ oStyle.setBreakBefore("auto")
if tStyle & self.A_PBA:
oStyle.setBreakAfter("page")
+ if tStyle & self.A_PBA_AUT:
+ oStyle.setBreakAfter("auto")
# Process Text Type
if tType == self.T_EMPTY:
@@ -212,7 +225,7 @@ class ToOdt(Tokenizer):
if parStyle is None:
parStyle = oStyle
# for xPos, xLen, xFmt in reversed(tFormat):
- # tTemp = tTemp[:xPos]+htmlTags[xFmt]+tTemp[xPos+xLen:]
+ # tTemp = tTemp[:xPos] + htmlTags[xFmt] + tTemp[xPos+xLen:]
if tText.endswith(" "):
thisPar.append(tTemp.rstrip()+"\n")
hasHardBreak = True
@@ -511,6 +524,10 @@ class ToOdt(Tokenizer):
# =============================================================================================== #
class ODTParagraphStyle():
+ """Wrapper class for the paragraph style setting used by the
+ exporter. Only the used settings are exposed here to keep the class
+ minimal and fast.
+ """
VALID_ALIGN = ["start", "center", "end", "justify", "inside", "outside", "left", "right"]
VALID_BREAK = ["auto", "column", "page", "even-page", "odd-page", "inherit"]
@@ -539,7 +556,7 @@ class ODTParagraphStyle():
"break-after": ["fo", None],
}
- # text Attributes
+ # Text Attributes
self._tAttr = {
"font-name": ["style", None],
"font-family": ["fo", None],
diff --git a/nw/gui/build.py b/nw/gui/build.py
index 9e80b588..8e2b3dc7 100644
--- a/nw/gui/build.py
+++ b/nw/gui/build.py
@@ -573,7 +573,7 @@ class GuiBuildNovel(QDialog):
self.nwdText = nwdText
tEnd = int(time())
- logger.debug("Built project in %.3f ms" % (1000*(tEnd-tStart)))
+ logger.debug("Built project in %.3f ms" % (1000*(tEnd - tStart)))
self.htmlStyle = makeHtml.getStyleSheet()
self.buildTime = tEnd
diff --git a/tests/reference/guiBuild_Tool_Step1_Lorem_Ipsum.htm b/tests/reference/guiBuild_Tool_Step1_Lorem_Ipsum.htm
index a3e4432f..70b6b8ac 100644
--- a/tests/reference/guiBuild_Tool_Step1_Lorem_Ipsum.htm
+++ b/tests/reference/guiBuild_Tool_Step1_Lorem_Ipsum.htm
@@ -5,6 +5,7 @@
Lorem Ipsum
-Lorem Ipsum
+Lorem Ipsum
By lipsum.com
“Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit…”
“There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain…”
diff --git a/tests/reference/guiBuild_Tool_Step2_Lorem_Ipsum.htm b/tests/reference/guiBuild_Tool_Step2_Lorem_Ipsum.htm
index 4ab595a3..30d610db 100644
--- a/tests/reference/guiBuild_Tool_Step2_Lorem_Ipsum.htm
+++ b/tests/reference/guiBuild_Tool_Step2_Lorem_Ipsum.htm
@@ -5,6 +5,7 @@
Lorem Ipsum
-Lorem Ipsum
+Lorem Ipsum
By lipsum.com
“Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit…”
“There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain…”
diff --git a/tests/reference/guiBuild_Tool_Step3_Lorem_Ipsum.htm b/tests/reference/guiBuild_Tool_Step3_Lorem_Ipsum.htm
index 8e6ad4b5..2c385360 100644
--- a/tests/reference/guiBuild_Tool_Step3_Lorem_Ipsum.htm
+++ b/tests/reference/guiBuild_Tool_Step3_Lorem_Ipsum.htm
@@ -5,6 +5,7 @@
Lorem Ipsum
-Lorem Ipsum
+Lorem Ipsum
By lipsum.com
“Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit…”
“There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain…”
diff --git a/tests/reference/guiBuild_Tool_Step4H_Lorem_Ipsum.json b/tests/reference/guiBuild_Tool_Step4H_Lorem_Ipsum.json
index c67a1321..ede728bb 100644
--- a/tests/reference/guiBuild_Tool_Step4H_Lorem_Ipsum.json
+++ b/tests/reference/guiBuild_Tool_Step4H_Lorem_Ipsum.json
@@ -5,10 +5,11 @@
"authors": [
"lipsum.com"
],
- "buildTime": 1611662802
+ "buildTime": 1611750760
},
"text": {
"css": [
+ "body {font-family: 'Sans'; font-size: 12pt}",
"p {text-align: justify;}",
"h1, h2 {color: rgb(66, 113, 174);}",
"h3, h4 {color: rgb(50, 50, 50);}",
@@ -24,7 +25,7 @@
],
"html": [
[
- "Lorem Ipsum
"
+ "Lorem Ipsum
"
],
[
""
diff --git a/tests/reference/guiBuild_Tool_Step4_Lorem_Ipsum.htm b/tests/reference/guiBuild_Tool_Step4_Lorem_Ipsum.htm
index f5360c30..fe3676c8 100644
--- a/tests/reference/guiBuild_Tool_Step4_Lorem_Ipsum.htm
+++ b/tests/reference/guiBuild_Tool_Step4_Lorem_Ipsum.htm
@@ -5,6 +5,7 @@
Lorem Ipsum
-Lorem Ipsum
+Lorem Ipsum
Prologue
Synopsis: Explanation from the lipsum.com website.
Act One
diff --git a/tests/test_core/test_core_tohtml.py b/tests/test_core/test_core_tohtml.py
index be99c340..0c20dddd 100644
--- a/tests/test_core/test_core_tohtml.py
+++ b/tests/test_core/test_core_tohtml.py
@@ -211,12 +211,12 @@ def testCoreToHtml_Convert(dummyGUI):
# Title
theHtml.theTokens = [
- (theHtml.T_TITLE, 1, "A Title", None, theHtml.A_PBB_NO | theHtml.A_CENTRE),
+ (theHtml.T_TITLE, 1, "A Title", None, theHtml.A_PBB_AUT | theHtml.A_CENTRE),
(theHtml.T_EMPTY, 1, "", None, theHtml.A_NONE),
]
theHtml.doConvert()
assert theHtml.theResult == (
- ""
+ ""
"A Title
\n"
)
@@ -299,24 +299,14 @@ def testCoreToHtml_Convert(dummyGUI):
"style='page-break-before: always; page-break-after: always;'>A Title
\n"
)
- # Page Break Avoid
+ # Page Break Auto
theHtml.theTokens = [
- (theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_PBB_AV | theHtml.A_PBA_AV),
+ (theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_PBB_AUT | theHtml.A_PBA_AUT),
]
theHtml.doConvert()
assert theHtml.theResult == (
"A Title
\n"
- )
-
- # Page Break ANever
- theHtml.theTokens = [
- (theHtml.T_HEAD1, 1, "A Title", None, theHtml.A_PBB_NO | theHtml.A_PBA_NO),
- ]
- theHtml.doConvert()
- assert theHtml.theResult == (
- "A Title
\n"
+ "style='page-break-before: auto; page-break-after: auto;'>A Title\n"
)
# Preview Mode
diff --git a/tests/test_core/test_core_tokenizer.py b/tests/test_core/test_core_tokenizer.py
index 64096f99..ed5fdc07 100644
--- a/tests/test_core/test_core_tokenizer.py
+++ b/tests/test_core/test_core_tokenizer.py
@@ -623,7 +623,7 @@ def testCoreToken_Headers(dummyGUI):
theToken.isPart = False
theToken.doHeaders()
assert theToken.theTokens == [
- (Tokenizer.T_TITLE, 1, "Novel Title", None, Tokenizer.A_PBB_NO | Tokenizer.A_CENTRE),
+ (Tokenizer.T_TITLE, 1, "Novel Title", None, Tokenizer.A_PBB_AUT | Tokenizer.A_CENTRE),
(Tokenizer.T_EMPTY, 1, "", None, Tokenizer.A_PBA | Tokenizer.A_CENTRE),
]
diff --git a/tests/test_core/test_core_toodt.py b/tests/test_core/test_core_toodt.py
index c0e8c797..ae3e0d6b 100644
--- a/tests/test_core/test_core_toodt.py
+++ b/tests/test_core/test_core_toodt.py
@@ -31,6 +31,7 @@ XML_NS = [
' xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"',
' xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style: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"',
]