Extended the style formatting of tokenizer and tohtml to allow multiple styles for a block
This commit is contained in:
+26
-10
@@ -102,19 +102,35 @@ class ToHtml(Tokenizer):
|
|||||||
|
|
||||||
self.theResult = ""
|
self.theResult = ""
|
||||||
thisPar = []
|
thisPar = []
|
||||||
for tType, tText, tFormat, tAlign in self.theTokens:
|
for tType, tText, tFormat, tStyle in self.theTokens:
|
||||||
|
|
||||||
# Styles
|
# Styles
|
||||||
aStyle = []
|
aStyle = []
|
||||||
if tAlign == self.A_CENTRE:
|
if tStyle is not None:
|
||||||
aStyle.append("text-align: center;")
|
if tStyle & self.A_LEFT:
|
||||||
elif tAlign == self.A_RIGHT:
|
aStyle.append("text-align: left;")
|
||||||
aStyle.append("text-align: right;")
|
if tStyle & self.A_RIGHT:
|
||||||
elif tAlign == self.A_JUSTIFY:
|
aStyle.append("text-align: right;")
|
||||||
aStyle.append("text-align: justify;")
|
if tStyle & self.A_CENTRE:
|
||||||
|
aStyle.append("text-align: center;")
|
||||||
if tType == self.T_HEAD2:
|
if tStyle & self.A_JUSTIFY:
|
||||||
aStyle.append("page-break-before: always;")
|
aStyle.append("text-align: justify;")
|
||||||
|
if tStyle & self.A_PBB:
|
||||||
|
aStyle.append("page-break-before: always;")
|
||||||
|
if tStyle & self.A_PBB_L:
|
||||||
|
aStyle.append("page-break-before: left;")
|
||||||
|
if tStyle & self.A_PBB_R:
|
||||||
|
aStyle.append("page-break-before: right;")
|
||||||
|
if tStyle & self.A_PBB_AV:
|
||||||
|
aStyle.append("page-break-before: avoid;")
|
||||||
|
if tStyle & self.A_PBA:
|
||||||
|
aStyle.append("page-break-after: always;")
|
||||||
|
if tStyle & self.A_PBA_L:
|
||||||
|
aStyle.append("page-break-after: left;")
|
||||||
|
if tStyle & self.A_PBA_R:
|
||||||
|
aStyle.append("page-break-after: right;")
|
||||||
|
if tStyle & self.A_PBA_AV:
|
||||||
|
aStyle.append("page-break-after: avoid;")
|
||||||
|
|
||||||
if len(aStyle) > 0:
|
if len(aStyle) > 0:
|
||||||
hStyle = " style='%s'" % (" ".join(aStyle))
|
hStyle = " style='%s'" % (" ".join(aStyle))
|
||||||
|
|||||||
+171
-33
@@ -60,10 +60,18 @@ class Tokenizer():
|
|||||||
T_SKIP = 11 # Paragraph break
|
T_SKIP = 11 # Paragraph break
|
||||||
T_PBREAK = 12 # Page break
|
T_PBREAK = 12 # Page break
|
||||||
|
|
||||||
A_LEFT = 1 # Left aligned
|
A_LEFT = 1 # Left aligned
|
||||||
A_RIGHT = 2 # Right aligned
|
A_RIGHT = 2 # Right aligned
|
||||||
A_CENTRE = 3 # Centred
|
A_CENTRE = 4 # Centred
|
||||||
A_JUSTIFY = 4 # Justified
|
A_JUSTIFY = 8 # Justified
|
||||||
|
A_PBB = 16 # Page break before
|
||||||
|
A_PBB_L = 32 # Page break before, left
|
||||||
|
A_PBB_R = 64 # Page break before, right
|
||||||
|
A_PBB_AV = 128 # Page break, avoid
|
||||||
|
A_PBA = 256 # Page break after
|
||||||
|
A_PBA_L = 512 # Page break after, left
|
||||||
|
A_PBA_R = 1024 # Page break after, right
|
||||||
|
A_PBA_AV = 2048 # Page break, avoid
|
||||||
|
|
||||||
def __init__(self, theProject, theParent):
|
def __init__(self, theProject, theParent):
|
||||||
|
|
||||||
@@ -208,6 +216,13 @@ class Tokenizer():
|
|||||||
just contains plain text. in the case of plain text, apply the
|
just contains plain text. in the case of plain text, apply the
|
||||||
same RegExes that the syntax highlighter uses and save the
|
same RegExes that the syntax highlighter uses and save the
|
||||||
locations of these formatting tags into the token array.
|
locations of these formatting tags into the token array.
|
||||||
|
|
||||||
|
The format of the token list is an entry with a four-tuple for
|
||||||
|
each line in the file. The tuple is as follows:
|
||||||
|
1: The type of the block, self.T_*
|
||||||
|
2: The text content of the block, without leading tags
|
||||||
|
3: The internal formatting map of the text, self.FMT_*
|
||||||
|
4: The style of the block, self.A_*
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# RegExes for adding formatting tags within text lines
|
# RegExes for adding formatting tags within text lines
|
||||||
@@ -233,23 +248,63 @@ class Tokenizer():
|
|||||||
|
|
||||||
# Tag lines starting with specific characters
|
# Tag lines starting with specific characters
|
||||||
if len(aLine.strip()) == 0:
|
if len(aLine.strip()) == 0:
|
||||||
self.theTokens.append((self.T_EMPTY, "", None, self.A_LEFT))
|
self.theTokens.append((
|
||||||
|
self.T_EMPTY,
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
))
|
||||||
elif aLine[0] == "%":
|
elif aLine[0] == "%":
|
||||||
cLine = aLine[1:].strip()
|
cLine = aLine[1:].strip()
|
||||||
if cLine.lower().startswith("synopsis:"):
|
if cLine.lower().startswith("synopsis:"):
|
||||||
self.theTokens.append((self.T_SYNOPSIS, cLine[9:].strip(), None, defAlign))
|
self.theTokens.append((
|
||||||
|
self.T_SYNOPSIS,
|
||||||
|
cLine[9:].strip(),
|
||||||
|
None,
|
||||||
|
defAlign
|
||||||
|
))
|
||||||
else:
|
else:
|
||||||
self.theTokens.append((self.T_COMMENT, aLine[1:].strip(), None, defAlign))
|
self.theTokens.append((
|
||||||
|
self.T_COMMENT,
|
||||||
|
aLine[1:].strip(),
|
||||||
|
None,
|
||||||
|
defAlign
|
||||||
|
))
|
||||||
elif aLine[0] == "@":
|
elif aLine[0] == "@":
|
||||||
self.theTokens.append((self.T_KEYWORD, aLine[1:].strip(), None, self.A_LEFT))
|
self.theTokens.append((
|
||||||
|
self.T_KEYWORD,
|
||||||
|
aLine[1:].strip(),
|
||||||
|
None,
|
||||||
|
self.A_LEFT
|
||||||
|
))
|
||||||
elif aLine[:2] == "# ":
|
elif aLine[:2] == "# ":
|
||||||
self.theTokens.append((self.T_HEAD1, aLine[2:].strip(), None, self.A_LEFT))
|
self.theTokens.append((
|
||||||
|
self.T_HEAD1,
|
||||||
|
aLine[2:].strip(),
|
||||||
|
None,
|
||||||
|
self.A_LEFT | self.A_PBB
|
||||||
|
))
|
||||||
elif aLine[:3] == "## ":
|
elif aLine[:3] == "## ":
|
||||||
self.theTokens.append((self.T_HEAD2, aLine[3:].strip(), None, self.A_LEFT))
|
self.theTokens.append((
|
||||||
|
self.T_HEAD2,
|
||||||
|
aLine[3:].strip(),
|
||||||
|
None,
|
||||||
|
self.A_LEFT | self.A_PBA_AV
|
||||||
|
))
|
||||||
elif aLine[:4] == "### ":
|
elif aLine[:4] == "### ":
|
||||||
self.theTokens.append((self.T_HEAD3, aLine[4:].strip(), None, self.A_LEFT))
|
self.theTokens.append((
|
||||||
|
self.T_HEAD3,
|
||||||
|
aLine[4:].strip(),
|
||||||
|
None,
|
||||||
|
self.A_LEFT | self.A_PBA_AV
|
||||||
|
))
|
||||||
elif aLine[:5] == "#### ":
|
elif aLine[:5] == "#### ":
|
||||||
self.theTokens.append((self.T_HEAD4, aLine[5:].strip(), None, self.A_LEFT))
|
self.theTokens.append((
|
||||||
|
self.T_HEAD4,
|
||||||
|
aLine[5:].strip(),
|
||||||
|
None,
|
||||||
|
self.A_LEFT | self.A_PBA_AV
|
||||||
|
))
|
||||||
else:
|
else:
|
||||||
if not self.doBodyText:
|
if not self.doBodyText:
|
||||||
# Skip all body text
|
# Skip all body text
|
||||||
@@ -270,10 +325,20 @@ class Tokenizer():
|
|||||||
# Save the line as is, but append the array of formatting locations
|
# Save the line as is, but append the array of formatting locations
|
||||||
# sorted by position
|
# sorted by position
|
||||||
fmtPos = sorted(fmtPos, key=itemgetter(0))
|
fmtPos = sorted(fmtPos, key=itemgetter(0))
|
||||||
self.theTokens.append((self.T_TEXT, aLine, fmtPos, defAlign))
|
self.theTokens.append((
|
||||||
|
self.T_TEXT,
|
||||||
|
aLine,
|
||||||
|
fmtPos,
|
||||||
|
defAlign
|
||||||
|
))
|
||||||
|
|
||||||
# Always add an empty line at the end
|
# Always add an empty line at the end
|
||||||
self.theTokens.append((self.T_EMPTY, "", None, self.A_LEFT))
|
self.theTokens.append((
|
||||||
|
self.T_EMPTY,
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -308,53 +373,126 @@ class Tokenizer():
|
|||||||
if tType == self.T_TEXT:
|
if tType == self.T_TEXT:
|
||||||
self.firstScene = False
|
self.firstScene = False
|
||||||
|
|
||||||
elif tType == self.T_HEAD2:
|
elif tType == self.T_HEAD2: # Novel Chapter
|
||||||
if not isUnNum:
|
if not isUnNum:
|
||||||
self.numChapter += 1
|
self.numChapter += 1
|
||||||
tText = self._formatChapter(tText,isUnNum)
|
tText = self._formatChapter(tText,isUnNum)
|
||||||
self.theTokens[n] = (tType, tText, None, self.A_LEFT)
|
self.theTokens[n] = (
|
||||||
|
tType,
|
||||||
|
tText,
|
||||||
|
None,
|
||||||
|
self.A_LEFT | self.A_PBB_R
|
||||||
|
)
|
||||||
self.firstScene = True
|
self.firstScene = True
|
||||||
|
|
||||||
elif tType == self.T_HEAD3:
|
elif tType == self.T_HEAD3: # Novel Scene
|
||||||
tTemp = self._formatScene(tText)
|
tTemp = self._formatScene(tText)
|
||||||
if tTemp == "" and self.hideScene:
|
if tTemp == "" and self.hideScene:
|
||||||
self.theTokens[n] = (self.T_EMPTY, "", None, self.A_LEFT)
|
self.theTokens[n] = (
|
||||||
|
self.T_EMPTY,
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
)
|
||||||
elif tTemp == "" and not self.hideScene:
|
elif tTemp == "" and not self.hideScene:
|
||||||
if self.firstScene:
|
if self.firstScene:
|
||||||
self.theTokens[n] = (self.T_EMPTY, "", None, self.A_LEFT)
|
self.theTokens[n] = (
|
||||||
|
self.T_EMPTY,
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (self.T_SKIP, "", None, self.A_LEFT)
|
self.theTokens[n] = (
|
||||||
|
self.T_SKIP,
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
)
|
||||||
elif tTemp == self.fmtScene:
|
elif tTemp == self.fmtScene:
|
||||||
if self.firstScene:
|
if self.firstScene:
|
||||||
self.theTokens[n] = (self.T_EMPTY, "", None, self.A_LEFT)
|
self.theTokens[n] = (
|
||||||
|
self.T_EMPTY,
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (self.T_SEP, tTemp, None, self.A_CENTRE)
|
self.theTokens[n] = (
|
||||||
|
self.T_SEP,
|
||||||
|
tTemp,
|
||||||
|
None,
|
||||||
|
self.A_CENTRE
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (tType, tTemp, None, self.A_LEFT)
|
self.theTokens[n] = (
|
||||||
|
tType,
|
||||||
|
tTemp,
|
||||||
|
None,
|
||||||
|
self.A_LEFT | self.A_PBA_AV
|
||||||
|
)
|
||||||
self.firstScene = False
|
self.firstScene = False
|
||||||
|
|
||||||
elif tType == self.T_HEAD4:
|
elif tType == self.T_HEAD4: # Novel Section
|
||||||
tTemp = self._formatSection(tText)
|
tTemp = self._formatSection(tText)
|
||||||
if tTemp == "" and self.hideSection:
|
if tTemp == "" and self.hideSection:
|
||||||
self.theTokens[n] = (self.T_EMPTY, "", None, self.A_LEFT)
|
self.theTokens[n] = (
|
||||||
|
self.T_EMPTY,
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
)
|
||||||
elif tTemp == "" and not self.hideSection:
|
elif tTemp == "" and not self.hideSection:
|
||||||
self.theTokens[n] = (self.T_SKIP, "", None, self.A_LEFT)
|
self.theTokens[n] = (
|
||||||
|
self.T_SKIP,
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
)
|
||||||
elif tTemp == self.fmtSection:
|
elif tTemp == self.fmtSection:
|
||||||
self.theTokens[n] = (self.T_SEP, tTemp, None, self.A_CENTRE)
|
self.theTokens[n] = (
|
||||||
|
self.T_SEP,
|
||||||
|
tTemp,
|
||||||
|
None,
|
||||||
|
self.A_CENTRE
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.theTokens[n] = (tType, tTemp, None, self.A_LEFT)
|
self.theTokens[n] = (
|
||||||
|
tType,
|
||||||
|
tTemp,
|
||||||
|
None,
|
||||||
|
self.A_LEFT | self.A_PBA_AV
|
||||||
|
)
|
||||||
|
|
||||||
# For title page and partitions, we need to centre all text
|
# For title page and partitions, we need to centre all text.
|
||||||
# and for some formats, we need a page break
|
# For partition, we also add a page break before, and for
|
||||||
|
# both types we always add a page break after the content.
|
||||||
if isTitle or isPart:
|
if isTitle or isPart:
|
||||||
for n in range(len(self.theTokens)):
|
for n in range(len(self.theTokens)):
|
||||||
tToken = self.theTokens[n]
|
tToken = self.theTokens[n]
|
||||||
tType = tToken[0]
|
tType = tToken[0]
|
||||||
tText = tToken[1]
|
tText = tToken[1]
|
||||||
tFormat = tToken[2]
|
tFormat = tToken[2]
|
||||||
self.theTokens[n] = (tType, tText, tFormat, self.A_CENTRE)
|
if isTitle:
|
||||||
|
self.theTokens[n] = (
|
||||||
self.theTokens.append((self.T_PBREAK, "", None, self.A_LEFT))
|
tType,
|
||||||
|
tText,
|
||||||
|
tFormat,
|
||||||
|
self.A_CENTRE
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.theTokens[n] = (
|
||||||
|
tType,
|
||||||
|
tText,
|
||||||
|
tFormat,
|
||||||
|
self.A_CENTRE | self.A_PBB_R
|
||||||
|
)
|
||||||
|
self.theTokens.append((
|
||||||
|
self.T_PBREAK,
|
||||||
|
"",
|
||||||
|
None,
|
||||||
|
None
|
||||||
|
))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
+22
-21
@@ -129,21 +129,6 @@ class GuiBuildNovel(QDialog):
|
|||||||
self.titleForm.setColumnStretch(0, 1)
|
self.titleForm.setColumnStretch(0, 1)
|
||||||
self.titleForm.setColumnStretch(1, 0)
|
self.titleForm.setColumnStretch(1, 0)
|
||||||
|
|
||||||
# Text Options
|
|
||||||
# =============
|
|
||||||
self.textGroup = QGroupBox("Text Options", self)
|
|
||||||
self.textForm = QGridLayout(self)
|
|
||||||
self.textGroup.setLayout(self.textForm)
|
|
||||||
|
|
||||||
self.justifyText = QSwitch()
|
|
||||||
self.justifyText.setChecked(self.optState.getBool("GuiBuildNovel", "justifyText", False))
|
|
||||||
|
|
||||||
self.textForm.addWidget(QLabel("Justify text"), 0, 0)
|
|
||||||
self.textForm.addWidget(self.justifyText, 0, 1)
|
|
||||||
|
|
||||||
self.textForm.setColumnStretch(0, 1)
|
|
||||||
self.textForm.setColumnStretch(1, 0)
|
|
||||||
|
|
||||||
# Build Settings
|
# Build Settings
|
||||||
# ==============
|
# ==============
|
||||||
self.buildGroup = QGroupBox("Build Overrides", self)
|
self.buildGroup = QGroupBox("Build Overrides", self)
|
||||||
@@ -159,6 +144,21 @@ class GuiBuildNovel(QDialog):
|
|||||||
self.buildForm.setColumnStretch(0, 1)
|
self.buildForm.setColumnStretch(0, 1)
|
||||||
self.buildForm.setColumnStretch(1, 0)
|
self.buildForm.setColumnStretch(1, 0)
|
||||||
|
|
||||||
|
# Text Options
|
||||||
|
# =============
|
||||||
|
self.textGroup = QGroupBox("Text Options", self)
|
||||||
|
self.textForm = QGridLayout(self)
|
||||||
|
self.textGroup.setLayout(self.textForm)
|
||||||
|
|
||||||
|
self.justifyText = QSwitch()
|
||||||
|
self.justifyText.setChecked(self.optState.getBool("GuiBuildNovel", "justifyText", False))
|
||||||
|
|
||||||
|
self.textForm.addWidget(QLabel("Justify text"), 0, 0)
|
||||||
|
self.textForm.addWidget(self.justifyText, 0, 1)
|
||||||
|
|
||||||
|
self.textForm.setColumnStretch(0, 1)
|
||||||
|
self.textForm.setColumnStretch(1, 0)
|
||||||
|
|
||||||
# Include Switches
|
# Include Switches
|
||||||
# ================
|
# ================
|
||||||
self.includeGroup = QGroupBox("Include Non-Text Elements", self)
|
self.includeGroup = QGroupBox("Include Non-Text Elements", self)
|
||||||
@@ -230,7 +230,7 @@ class GuiBuildNovel(QDialog):
|
|||||||
self.saveODT.triggered.connect(lambda: self._saveDocument(self.FMT_ODT))
|
self.saveODT.triggered.connect(lambda: self._saveDocument(self.FMT_ODT))
|
||||||
self.saveMenu.addAction(self.saveODT)
|
self.saveMenu.addAction(self.saveODT)
|
||||||
|
|
||||||
# self.savePDF = QAction("Portable Document (.pdf)")
|
# self.savePDF = QAction("Portable Document Format (.pdf)")
|
||||||
# self.savePDF.triggered.connect(lambda: self._saveDocument(self.FMT_PDF))
|
# self.savePDF.triggered.connect(lambda: self._saveDocument(self.FMT_PDF))
|
||||||
# self.saveMenu.addAction(self.savePDF)
|
# self.saveMenu.addAction(self.savePDF)
|
||||||
|
|
||||||
@@ -238,13 +238,14 @@ class GuiBuildNovel(QDialog):
|
|||||||
self.saveHTM1.triggered.connect(lambda: self._saveDocument(self.FMT_HTM1))
|
self.saveHTM1.triggered.connect(lambda: self._saveDocument(self.FMT_HTM1))
|
||||||
self.saveMenu.addAction(self.saveHTM1)
|
self.saveMenu.addAction(self.saveHTM1)
|
||||||
|
|
||||||
self.saveHTM2 = QAction("Plain HTML (.htm)")
|
self.saveHTM2 = QAction("%s HTML (.htm)" % nw.__package__)
|
||||||
self.saveHTM2.triggered.connect(lambda: self._saveDocument(self.FMT_HTM2))
|
self.saveHTM2.triggered.connect(lambda: self._saveDocument(self.FMT_HTM2))
|
||||||
self.saveMenu.addAction(self.saveHTM2)
|
self.saveMenu.addAction(self.saveHTM2)
|
||||||
|
|
||||||
# self.saveMD = QAction("Markdown (.md)")
|
if self.mainConf.verQtValue >= 51400:
|
||||||
# self.saveMD.triggered.connect(lambda: self._saveDocument(self.FMT_MD))
|
self.saveMD = QAction("Markdown (.md)")
|
||||||
# self.saveMenu.addAction(self.saveMD)
|
self.saveMD.triggered.connect(lambda: self._saveDocument(self.FMT_MD))
|
||||||
|
self.saveMenu.addAction(self.saveMD)
|
||||||
|
|
||||||
self.saveTXT = QAction("Plain Text (.txt)")
|
self.saveTXT = QAction("Plain Text (.txt)")
|
||||||
self.saveTXT.triggered.connect(lambda: self._saveDocument(self.FMT_TXT))
|
self.saveTXT.triggered.connect(lambda: self._saveDocument(self.FMT_TXT))
|
||||||
@@ -261,8 +262,8 @@ class GuiBuildNovel(QDialog):
|
|||||||
# Assemble GUI
|
# Assemble GUI
|
||||||
# ============
|
# ============
|
||||||
self.toolsBox.addWidget(self.titleGroup)
|
self.toolsBox.addWidget(self.titleGroup)
|
||||||
self.toolsBox.addWidget(self.textGroup)
|
|
||||||
self.toolsBox.addWidget(self.buildGroup)
|
self.toolsBox.addWidget(self.buildGroup)
|
||||||
|
self.toolsBox.addWidget(self.textGroup)
|
||||||
self.toolsBox.addWidget(self.includeGroup)
|
self.toolsBox.addWidget(self.includeGroup)
|
||||||
self.toolsBox.addWidget(self.addsGroup)
|
self.toolsBox.addWidget(self.addsGroup)
|
||||||
self.toolsBox.addStretch(1)
|
self.toolsBox.addStretch(1)
|
||||||
|
|||||||
Reference in New Issue
Block a user