Add annotations to tokenizer, html and markdown classes

This commit is contained in:
Veronica Berglyd Olsen
2023-06-06 00:35:57 +02:00
parent 850ee73ed4
commit 6b6c517b1f
3 changed files with 177 additions and 166 deletions
+60 -63
View File
@@ -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="&nbsp;"):
"""Replace tabs with spaces in the html.
"""
def replaceTabs(self, nSpaces: int = 8, spaceChar: str = "&nbsp;"):
"""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