Add annotations to tokenizer, html and markdown classes
This commit is contained in:
+60
-63
@@ -22,11 +22,15 @@ General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from novelwriter import CONFIG
|
||||
from novelwriter.constants import nwKeyWords, nwLabels, nwHtmlUnicode
|
||||
from novelwriter.core.project import NWProject
|
||||
from novelwriter.core.tokenizer import Tokenizer, stripEscape
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -38,8 +42,8 @@ class ToHtml(Tokenizer):
|
||||
M_EXPORT = 1 # Tweak output for saving to HTML or printing
|
||||
M_EBOOK = 2 # Tweak output for converting to epub
|
||||
|
||||
def __init__(self, theProject):
|
||||
super().__init__(theProject)
|
||||
def __init__(self, project: NWProject):
|
||||
super().__init__(project)
|
||||
|
||||
self._genMode = self.M_EXPORT
|
||||
self._cssStyles = True
|
||||
@@ -63,7 +67,7 @@ class ToHtml(Tokenizer):
|
||||
# Setters
|
||||
##
|
||||
|
||||
def setPreview(self, doComments, doSynopsis):
|
||||
def setPreview(self, doComments: bool, doSynopsis: bool):
|
||||
"""If we're using this class to generate markdown preview, we
|
||||
need to make a few changes to formatting, which is managed by
|
||||
these flags.
|
||||
@@ -74,14 +78,14 @@ class ToHtml(Tokenizer):
|
||||
self._doSynopsis = doSynopsis
|
||||
return
|
||||
|
||||
def setStyles(self, cssStyles):
|
||||
"""Enable/disable CSS styling. Some elements may still have
|
||||
def setStyles(self, cssStyles: bool):
|
||||
"""Enable or disable CSS styling. Some elements may still have
|
||||
class tags.
|
||||
"""
|
||||
self._cssStyles = cssStyles
|
||||
return
|
||||
|
||||
def setReplaceUnicode(self, doReplace):
|
||||
def setReplaceUnicode(self, doReplace: bool):
|
||||
"""Set the translation map to either minimal or full unicode for
|
||||
html entities replacement.
|
||||
"""
|
||||
@@ -92,16 +96,14 @@ class ToHtml(Tokenizer):
|
||||
if doReplace:
|
||||
# Extend to all relevant Unicode characters
|
||||
self._trMap.update(str.maketrans(nwHtmlUnicode.U_TO_H))
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
# Class Methods
|
||||
##
|
||||
|
||||
def getFullResultSize(self):
|
||||
"""Return the size of the full HTML result.
|
||||
"""
|
||||
def getFullResultSize(self) -> int:
|
||||
"""Return the size of the full HTML result."""
|
||||
return sum([len(x) for x in self._fullHTML])
|
||||
|
||||
def doPreProcessing(self):
|
||||
@@ -114,7 +116,7 @@ class ToHtml(Tokenizer):
|
||||
|
||||
def doConvert(self):
|
||||
"""Convert the list of text tokens into a HTML document saved
|
||||
to theResult.
|
||||
to _result.
|
||||
"""
|
||||
if self._genMode == self.M_PREVIEW:
|
||||
htmlTags = { # HTML4 + CSS2 (for Qt)
|
||||
@@ -290,7 +292,7 @@ class ToHtml(Tokenizer):
|
||||
|
||||
return
|
||||
|
||||
def saveHTML5(self, savePath):
|
||||
def saveHTML5(self, savePath: str | Path):
|
||||
"""Save the data to an .html file.
|
||||
"""
|
||||
with open(savePath, mode="w", encoding="utf-8") as outFile:
|
||||
@@ -324,9 +326,8 @@ class ToHtml(Tokenizer):
|
||||
|
||||
return
|
||||
|
||||
def replaceTabs(self, nSpaces=8, spaceChar=" "):
|
||||
"""Replace tabs with spaces in the html.
|
||||
"""
|
||||
def replaceTabs(self, nSpaces: int = 8, spaceChar: str = " "):
|
||||
"""Replace tabs with spaces in the html."""
|
||||
htmlText = []
|
||||
tabSpace = spaceChar*nSpaces
|
||||
for aLine in self._fullHTML:
|
||||
@@ -335,20 +336,19 @@ class ToHtml(Tokenizer):
|
||||
self._fullHTML = htmlText
|
||||
return
|
||||
|
||||
def getStyleSheet(self):
|
||||
"""Generate a stylesheet appropriate for the current settings.
|
||||
"""
|
||||
theStyles = []
|
||||
def getStyleSheet(self) -> list:
|
||||
"""Generate a stylesheet for the current settings."""
|
||||
styles = []
|
||||
if not self._cssStyles:
|
||||
return theStyles
|
||||
return styles
|
||||
|
||||
mScale = self._lineHeight/1.15
|
||||
textAlign = "justify" if self._doJustify else "left"
|
||||
|
||||
theStyles.append("body {{font-family: '{0:s}'; font-size: {1:d}pt;}}".format(
|
||||
styles.append("body {{font-family: '{0:s}'; font-size: {1:d}pt;}}".format(
|
||||
self._textFont, self._textSize
|
||||
))
|
||||
theStyles.append((
|
||||
styles.append((
|
||||
"p {{"
|
||||
"text-align: {0}; line-height: {1:d}%; "
|
||||
"margin-top: {2:.2f}em; margin-bottom: {3:.2f}em;"
|
||||
@@ -359,7 +359,7 @@ class ToHtml(Tokenizer):
|
||||
mScale * self._marginText[0],
|
||||
mScale * self._marginText[1],
|
||||
))
|
||||
theStyles.append((
|
||||
styles.append((
|
||||
"h1 {{"
|
||||
"color: rgb(66, 113, 174); "
|
||||
"page-break-after: avoid; "
|
||||
@@ -369,7 +369,7 @@ class ToHtml(Tokenizer):
|
||||
).format(
|
||||
mScale * self._marginHead1[0], mScale * self._marginHead1[1]
|
||||
))
|
||||
theStyles.append((
|
||||
styles.append((
|
||||
"h2 {{"
|
||||
"color: rgb(66, 113, 174); "
|
||||
"page-break-after: avoid; "
|
||||
@@ -379,7 +379,7 @@ class ToHtml(Tokenizer):
|
||||
).format(
|
||||
mScale * self._marginHead2[0], mScale * self._marginHead2[1]
|
||||
))
|
||||
theStyles.append((
|
||||
styles.append((
|
||||
"h3 {{"
|
||||
"color: rgb(50, 50, 50); "
|
||||
"page-break-after: avoid; "
|
||||
@@ -389,7 +389,7 @@ class ToHtml(Tokenizer):
|
||||
).format(
|
||||
mScale * self._marginHead3[0], mScale * self._marginHead3[1]
|
||||
))
|
||||
theStyles.append((
|
||||
styles.append((
|
||||
"h4 {{"
|
||||
"color: rgb(50, 50, 50); "
|
||||
"page-break-after: avoid; "
|
||||
@@ -399,7 +399,7 @@ class ToHtml(Tokenizer):
|
||||
).format(
|
||||
mScale * self._marginHead4[0], mScale * self._marginHead4[1]
|
||||
))
|
||||
theStyles.append((
|
||||
styles.append((
|
||||
".title {{"
|
||||
"font-size: 2.5em; "
|
||||
"margin-top: {0:.2f}em; "
|
||||
@@ -408,7 +408,7 @@ class ToHtml(Tokenizer):
|
||||
).format(
|
||||
mScale * self._marginTitle[0], mScale * self._marginTitle[1]
|
||||
))
|
||||
theStyles.append((
|
||||
styles.append((
|
||||
".sep, .skip {{"
|
||||
"text-align: center; "
|
||||
"margin-top: {0:.2f}em; "
|
||||
@@ -418,61 +418,58 @@ class ToHtml(Tokenizer):
|
||||
mScale, mScale
|
||||
))
|
||||
|
||||
theStyles.append("a {color: rgb(66, 113, 174);}")
|
||||
theStyles.append(".tags {color: rgb(245, 135, 31); font-weight: bold;}")
|
||||
theStyles.append(".break {text-align: left;}")
|
||||
theStyles.append(".synopsis {font-style: italic;}")
|
||||
theStyles.append(".comment {font-style: italic; color: rgb(100, 100, 100);}")
|
||||
styles.append("a {color: rgb(66, 113, 174);}")
|
||||
styles.append(".tags {color: rgb(245, 135, 31); font-weight: bold;}")
|
||||
styles.append(".break {text-align: left;}")
|
||||
styles.append(".synopsis {font-style: italic;}")
|
||||
styles.append(".comment {font-style: italic; color: rgb(100, 100, 100);}")
|
||||
|
||||
return theStyles
|
||||
return styles
|
||||
|
||||
##
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _formatSynopsis(self, tText):
|
||||
"""Apply HTML formatting to synopsis.
|
||||
"""
|
||||
def _formatSynopsis(self, text: str) -> str:
|
||||
"""Apply HTML formatting to synopsis."""
|
||||
if self._genMode == self.M_PREVIEW:
|
||||
sSynop = self._trSynopsis
|
||||
return f"<p class='comment'><span class='synopsis'>{sSynop}:</span> {tText}</p>\n"
|
||||
return f"<p class='comment'><span class='synopsis'>{sSynop}:</span> {text}</p>\n"
|
||||
else:
|
||||
sSynop = self._localLookup("Synopsis")
|
||||
return f"<p class='synopsis'><strong>{sSynop}:</strong> {tText}</p>\n"
|
||||
return f"<p class='synopsis'><strong>{sSynop}:</strong> {text}</p>\n"
|
||||
|
||||
def _formatComments(self, tText):
|
||||
"""Apply HTML formatting to comments.
|
||||
"""
|
||||
def _formatComments(self, text: str) -> str:
|
||||
"""Apply HTML formatting to comments."""
|
||||
if self._genMode == self.M_PREVIEW:
|
||||
return f"<p class='comment'>{tText}</p>\n"
|
||||
return f"<p class='comment'>{text}</p>\n"
|
||||
else:
|
||||
sComm = self._localLookup("Comment")
|
||||
return f"<p class='comment'><strong>{sComm}:</strong> {tText}</p>\n"
|
||||
return f"<p class='comment'><strong>{sComm}:</strong> {text}</p>\n"
|
||||
|
||||
def _formatKeywords(self, tText):
|
||||
"""Apply HTML formatting to keywords.
|
||||
"""
|
||||
isValid, theBits, _ = self._project.index.scanThis("@"+tText)
|
||||
if not isValid or not theBits:
|
||||
def _formatKeywords(self, text: str) -> str:
|
||||
"""Apply HTML formatting to keywords."""
|
||||
valid, bits, _ = self._project.index.scanThis("@"+text)
|
||||
if not valid or not bits:
|
||||
return ""
|
||||
|
||||
retText = ""
|
||||
refTags = []
|
||||
if theBits[0] in nwLabels.KEY_NAME:
|
||||
retText += f"<span class='tags'>{nwLabels.KEY_NAME[theBits[0]]}:</span> "
|
||||
if len(theBits) > 1:
|
||||
if theBits[0] == nwKeyWords.TAG_KEY:
|
||||
retText += f"<a name='tag_{theBits[1]}'>{theBits[1]}</a>"
|
||||
result = ""
|
||||
tags = []
|
||||
if bits[0] in nwLabels.KEY_NAME:
|
||||
result += f"<span class='tags'>{nwLabels.KEY_NAME[bits[0]]}:</span> "
|
||||
if len(bits) > 1:
|
||||
if bits[0] == nwKeyWords.TAG_KEY:
|
||||
result += f"<a name='tag_{bits[1]}'>{bits[1]}</a>"
|
||||
else:
|
||||
if self._genMode == self.M_PREVIEW:
|
||||
for tTag in theBits[1:]:
|
||||
refTags.append(f"<a href='#{theBits[0][1:]}={tTag}'>{tTag}</a>")
|
||||
retText += ", ".join(refTags)
|
||||
for tTag in bits[1:]:
|
||||
tags.append(f"<a href='#{bits[0][1:]}={tTag}'>{tTag}</a>")
|
||||
result += ", ".join(tags)
|
||||
else:
|
||||
for tTag in theBits[1:]:
|
||||
refTags.append(f"<a href='#tag_{tTag}'>{tTag}</a>")
|
||||
retText += ", ".join(refTags)
|
||||
for tTag in bits[1:]:
|
||||
tags.append(f"<a href='#tag_{tTag}'>{tTag}</a>")
|
||||
result += ", ".join(tags)
|
||||
|
||||
return retText
|
||||
return result
|
||||
|
||||
# END Class ToHtml
|
||||
|
||||
Reference in New Issue
Block a user