diff --git a/novelwriter/core/docbuild.py b/novelwriter/core/docbuild.py
index 0c2ab461..3c791334 100644
--- a/novelwriter/core/docbuild.py
+++ b/novelwriter/core/docbuild.py
@@ -191,6 +191,8 @@ class NWBuildDocument:
else:
yield i, False
+ makeObj.appendFootnotes()
+
if not (self._build.getBool("html.preserveTabs") or self._preview):
makeObj.replaceTabs()
@@ -231,6 +233,8 @@ class NWBuildDocument:
else:
yield i, False
+ makeObj.appendFootnotes()
+
self._error = None
self._cache = makeObj
diff --git a/novelwriter/core/tohtml.py b/novelwriter/core/tohtml.py
index 176a6aed..d513d4ea 100644
--- a/novelwriter/core/tohtml.py
+++ b/novelwriter/core/tohtml.py
@@ -33,10 +33,44 @@ from novelwriter import CONFIG
from novelwriter.common import formatTimeStamp
from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels, nwHtmlUnicode
from novelwriter.core.project import NWProject
-from novelwriter.core.tokenizer import Tokenizer, stripEscape
+from novelwriter.core.tokenizer import T_Formats, Tokenizer, stripEscape
logger = logging.getLogger(__name__)
+HTML4_TAGS = {
+ Tokenizer.FMT_B_B: "",
+ Tokenizer.FMT_B_E: "",
+ Tokenizer.FMT_I_B: "",
+ Tokenizer.FMT_I_E: "",
+ Tokenizer.FMT_D_B: "",
+ Tokenizer.FMT_D_E: "",
+ Tokenizer.FMT_U_B: "",
+ Tokenizer.FMT_U_E: "",
+ Tokenizer.FMT_M_B: "",
+ Tokenizer.FMT_M_E: "",
+ Tokenizer.FMT_SUP_B: "",
+ Tokenizer.FMT_SUP_E: "",
+ Tokenizer.FMT_SUB_B: "",
+ Tokenizer.FMT_SUB_E: "",
+}
+
+HTML5_TAGS = {
+ Tokenizer.FMT_B_B: "",
+ Tokenizer.FMT_B_E: "",
+ Tokenizer.FMT_I_B: "",
+ Tokenizer.FMT_I_E: "",
+ Tokenizer.FMT_D_B: "",
+ Tokenizer.FMT_D_E: "",
+ Tokenizer.FMT_U_B: "",
+ Tokenizer.FMT_U_E: "",
+ Tokenizer.FMT_M_B: "",
+ Tokenizer.FMT_M_E: "",
+ Tokenizer.FMT_SUP_B: "",
+ Tokenizer.FMT_SUP_E: "",
+ Tokenizer.FMT_SUB_B: "",
+ Tokenizer.FMT_SUB_E: "",
+}
+
class ToHtml(Tokenizer):
"""Core: HTML Document Writer
@@ -117,38 +151,9 @@ class ToHtml(Tokenizer):
def doConvert(self) -> None:
"""Convert the list of text tokens into an HTML document."""
- if self._genMode == self.M_PREVIEW:
- htmlTags = { # HTML4 + CSS2 (for Qt)
- self.FMT_B_B: "",
- self.FMT_B_E: "",
- self.FMT_I_B: "",
- self.FMT_I_E: "",
- self.FMT_D_B: "",
- self.FMT_D_E: "",
- self.FMT_U_B: "",
- self.FMT_U_E: "",
- self.FMT_M_B: "",
- self.FMT_M_E: "",
- }
- else:
- htmlTags = { # HTML5 (for export)
- self.FMT_B_B: "",
- self.FMT_B_E: "",
- self.FMT_I_B: "",
- self.FMT_I_E: "",
- self.FMT_D_B: "",
- self.FMT_D_E: "",
- self.FMT_U_B: "",
- self.FMT_U_E: "",
- self.FMT_M_B: "",
- self.FMT_M_E: "",
- }
-
- htmlTags[self.FMT_SUP_B] = ""
- htmlTags[self.FMT_SUP_E] = ""
- htmlTags[self.FMT_SUB_B] = ""
- htmlTags[self.FMT_SUB_E] = ""
+ self._result = ""
+ hTags = HTML4_TAGS if self._genMode == self.M_PREVIEW else HTML5_TAGS
if self._isNovel and self._genMode != self.M_PREVIEW:
# For story files, we bump the titles one level up
h1Cl = " class='title'"
@@ -163,12 +168,9 @@ class ToHtml(Tokenizer):
h3 = "h3"
h4 = "h4"
- self._result = ""
-
para = []
- pStyle = None
lines = []
-
+ pStyle = None
tHandle = self._handle
for tType, nHead, tText, tFormat, tStyle in self._tokens:
@@ -181,11 +183,11 @@ class ToHtml(Tokenizer):
for c in tText:
if c == "<":
cText.append("<")
- tFormat = [[p + 3 if p > i else p, f, k] for p, f, k in tFormat]
+ tFormat = [(p + 3 if p > i else p, f, k) for p, f, k in tFormat]
i += 4
elif c == ">":
cText.append(">")
- tFormat = [[p + 3 if p > i else p, f, k] for p, f, k in tFormat]
+ tFormat = [(p + 3 if p > i else p, f, k) for p, f, k in tFormat]
i += 4
else:
cText.append(c)
@@ -275,28 +277,18 @@ class ToHtml(Tokenizer):
lines.append(f"
\n") elif tType == self.T_TEXT: - tTemp = tText if pStyle is None: pStyle = hStyle - for pos, fmt, key in reversed(tFormat): - if fmt > self.MRK_BOUNDARY: - if key in self._markers: - index = self._markers[key][0] - if fmt == self.MRK_FOOTNOTE: - ref = f"[{index+1}]" - tTemp = f"{tTemp[:pos]}{ref}{tTemp[pos:]}" - else: - tTemp = f"{tTemp[:pos]}{htmlTags[fmt]}{tTemp[pos:]}" - para.append(stripEscape(tTemp.rstrip())) + para.append(self._formatText(tText, tFormat, hTags).rstrip()) elif tType == self.T_SYNOPSIS and self._doSynopsis: - lines.append(self._formatSynopsis(tText, True)) + lines.append(self._formatSynopsis(self._formatText(tText, tFormat, hTags), True)) elif tType == self.T_SHORT and self._doSynopsis: - lines.append(self._formatSynopsis(tText, False)) + lines.append(self._formatSynopsis(self._formatText(tText, tFormat, hTags), False)) elif tType == self.T_COMMENT and self._doComments: - lines.append(self._formatComments(tText)) + lines.append(self._formatComments(self._formatText(tText, tFormat, hTags))) elif tType == self.T_KEYWORD and self._doKeywords: tag, text = self._formatKeywords(tText) @@ -309,6 +301,25 @@ class ToHtml(Tokenizer): return + def appendFootnotes(self) -> None: + """Append the footnotes in the buffer.""" + tags = HTML4_TAGS if self._genMode == self.M_PREVIEW else HTML5_TAGS + footnotes = self._localLookup("Footnotes") + + lines = [] + lines.append(f"
".join(self._formatText(t, f, tags) for t, f in content) + lines.append(f"
{text}