Simplify footnote handling in writer classes
This commit is contained in:
@@ -1494,4 +1494,4 @@ def processComment(text: str) -> tuple[nwComment, str, str, int, int]:
|
|||||||
if content and (clean := classifier.strip().lower()) in CLASSIFIERS:
|
if content and (clean := classifier.strip().lower()) in CLASSIFIERS:
|
||||||
term = "ERR" if term and clean not in TERMS else term.strip()
|
term = "ERR" if term and clean not in TERMS else term.strip()
|
||||||
return CLASSIFIERS[clean], term, content.strip(), text.find(".") + 1, text.find(":") + 1
|
return CLASSIFIERS[clean], term, content.strip(), text.find(".") + 1, text.find(":") + 1
|
||||||
return nwComment.PLAIN, "", check, 0, 0
|
return nwComment.IGNORE if text.startswith("%~") else nwComment.PLAIN, "", check, 0, 0
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ class ToHtml(Tokenizer):
|
|||||||
|
|
||||||
# Internals
|
# Internals
|
||||||
self._trMap = {}
|
self._trMap = {}
|
||||||
self._usedNotes = set()
|
self._usedNotes: dict[str, int] = {}
|
||||||
self.setReplaceUnicode(False)
|
self.setReplaceUnicode(False)
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -313,9 +313,9 @@ class ToHtml(Tokenizer):
|
|||||||
lines = []
|
lines = []
|
||||||
lines.append(f"<h3>{footnotes}</h3>\n")
|
lines.append(f"<h3>{footnotes}</h3>\n")
|
||||||
lines.append("<ol>\n")
|
lines.append("<ol>\n")
|
||||||
for key, (index, content) in self._footnotes.items():
|
for key, index in self._usedNotes.items():
|
||||||
if key in self._usedNotes:
|
if content := self._footnotes.get(key):
|
||||||
text = "</p><p>".join(self._formatText(t, f, tags) for t, f in content)
|
text = self._formatText(*content, tags)
|
||||||
lines.append(f"<li id='footnote_{index}'><p>{text}</p></li>\n")
|
lines.append(f"<li id='footnote_{index}'><p>{text}</p></li>\n")
|
||||||
lines.append("</ol>\n")
|
lines.append("</ol>\n")
|
||||||
|
|
||||||
@@ -482,9 +482,12 @@ class ToHtml(Tokenizer):
|
|||||||
for pos, fmt, data in reversed(tFmt):
|
for pos, fmt, data in reversed(tFmt):
|
||||||
html = ""
|
html = ""
|
||||||
if fmt == self.FMT_FNOTE:
|
if fmt == self.FMT_FNOTE:
|
||||||
self._usedNotes.add(data)
|
if data in self._footnotes:
|
||||||
index = self._footnotes.get(data, (0, ""))[0] or "ERR"
|
index = len(self._usedNotes) + 1
|
||||||
html = f"<sup><a href='#footnote_{index}'>[{index}]</a></sup>"
|
self._usedNotes[data] = index
|
||||||
|
html = f"<sup><a href='#footnote_{index}'>{index}</a></sup>"
|
||||||
|
else:
|
||||||
|
html = "<sup>ERR</sup>"
|
||||||
else:
|
else:
|
||||||
html = tags.get(fmt, "ERR")
|
html = tags.get(fmt, "ERR")
|
||||||
temp = f"{temp[:pos]}{html}{temp[pos:]}"
|
temp = f"{temp[:pos]}{html}{temp[pos:]}"
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ ESCAPES = {r"\*": "*", r"\~": "~", r"\_": "_", r"\[": "[", r"\]": "]", r"\ ": ""
|
|||||||
RX_ESC = re.compile("|".join([re.escape(k) for k in ESCAPES.keys()]), flags=re.DOTALL)
|
RX_ESC = re.compile("|".join([re.escape(k) for k in ESCAPES.keys()]), flags=re.DOTALL)
|
||||||
|
|
||||||
T_Formats = list[tuple[int, int, str]]
|
T_Formats = list[tuple[int, int, str]]
|
||||||
T_Comment = tuple[int, list[tuple[str, T_Formats]]]
|
T_Comment = tuple[str, T_Formats]
|
||||||
|
|
||||||
|
|
||||||
def stripEscape(text: str) -> str:
|
def stripEscape(text: str) -> str:
|
||||||
@@ -561,9 +561,7 @@ class Tokenizer(ABC):
|
|||||||
tmpMarkdown.append(f"{aLine}\n")
|
tmpMarkdown.append(f"{aLine}\n")
|
||||||
elif cStyle == nwComment.FOOTNOTE:
|
elif cStyle == nwComment.FOOTNOTE:
|
||||||
tLine, tFmt = self._extractFormats(cText, skip=self.FMT_FNOTE)
|
tLine, tFmt = self._extractFormats(cText, skip=self.FMT_FNOTE)
|
||||||
if cKey not in self._footnotes:
|
self._footnotes[cKey] = (tLine, tFmt)
|
||||||
self._footnotes[cKey] = (len(self._footnotes) + 1, [])
|
|
||||||
self._footnotes[cKey][1].append((tLine, tFmt))
|
|
||||||
else:
|
else:
|
||||||
tLine, tFmt = self._extractFormats(cText)
|
tLine, tFmt = self._extractFormats(cText)
|
||||||
self._tokens.append((
|
self._tokens.append((
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ class ToMarkdown(Tokenizer):
|
|||||||
self._genMode = self.M_STD
|
self._genMode = self.M_STD
|
||||||
self._fullMD: list[str] = []
|
self._fullMD: list[str] = []
|
||||||
self._preserveBreaks = True
|
self._preserveBreaks = True
|
||||||
self._usedNotes = set()
|
self._usedNotes: dict[str, int] = {}
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -208,11 +208,10 @@ class ToMarkdown(Tokenizer):
|
|||||||
|
|
||||||
lines = []
|
lines = []
|
||||||
lines.append(f"### {footnotes}\n\n")
|
lines.append(f"### {footnotes}\n\n")
|
||||||
for key, (index, content) in self._footnotes.items():
|
for key, index in self._usedNotes.items():
|
||||||
if key in self._usedNotes:
|
if content := self._footnotes.get(key):
|
||||||
marker = f"{index}. "
|
marker = f"{index}. "
|
||||||
indent = "\n\n"+" "*len(marker)
|
text = self._formatText(*content, tags)
|
||||||
text = indent.join(self._formatText(t, f, tags) for t, f in content)
|
|
||||||
lines.append(f"{marker}{text}\n")
|
lines.append(f"{marker}{text}\n")
|
||||||
lines.append("\n")
|
lines.append("\n")
|
||||||
|
|
||||||
@@ -247,9 +246,12 @@ class ToMarkdown(Tokenizer):
|
|||||||
for pos, fmt, data in reversed(tFmt):
|
for pos, fmt, data in reversed(tFmt):
|
||||||
md = ""
|
md = ""
|
||||||
if fmt == self.FMT_FNOTE:
|
if fmt == self.FMT_FNOTE:
|
||||||
self._usedNotes.add(data)
|
if data in self._footnotes:
|
||||||
index = self._footnotes.get(data, (0, ""))[0] or "ERR"
|
index = len(self._usedNotes) + 1
|
||||||
md = f"[{index}]"
|
self._usedNotes[data] = index
|
||||||
|
md = f"[{index}]"
|
||||||
|
else:
|
||||||
|
md = "[ERR]"
|
||||||
else:
|
else:
|
||||||
md = tags.get(fmt, "")
|
md = tags.get(fmt, "")
|
||||||
temp = f"{temp[:pos]}{md}{temp[pos:]}"
|
temp = f"{temp[:pos]}{md}{temp[pos:]}"
|
||||||
|
|||||||
+14
-23
@@ -30,7 +30,6 @@ import logging
|
|||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
from collections.abc import Sequence
|
from collections.abc import Sequence
|
||||||
from copy import deepcopy
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -412,7 +411,6 @@ class ToOdt(Tokenizer):
|
|||||||
def doConvert(self) -> None:
|
def doConvert(self) -> None:
|
||||||
"""Convert the list of text tokens into XML elements."""
|
"""Convert the list of text tokens into XML elements."""
|
||||||
self._result = "" # Not used, but cleared just in case
|
self._result = "" # Not used, but cleared just in case
|
||||||
self._preProcessNotes()
|
|
||||||
|
|
||||||
pFmt: list[T_Formats] = []
|
pFmt: list[T_Formats] = []
|
||||||
pText = []
|
pText = []
|
||||||
@@ -687,7 +685,9 @@ class ToOdt(Tokenizer):
|
|||||||
elif fFmt == self.FMT_SUB_E:
|
elif fFmt == self.FMT_SUB_E:
|
||||||
xFmt &= M_SUB
|
xFmt &= M_SUB
|
||||||
elif fFmt == self.FMT_FNOTE:
|
elif fFmt == self.FMT_FNOTE:
|
||||||
parProc.appendNode(self._etNotes.get(fData))
|
parProc.appendNode(self._generateFootnote(fData))
|
||||||
|
elif fFmt == self.FMT_STRIP:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
pErr += 1
|
pErr += 1
|
||||||
|
|
||||||
@@ -758,16 +758,11 @@ class ToOdt(Tokenizer):
|
|||||||
|
|
||||||
return style.name
|
return style.name
|
||||||
|
|
||||||
def _preProcessNotes(self) -> None:
|
def _generateFootnote(self, key: str) -> ET.Element | None:
|
||||||
"""Generate XML elements for footnotes."""
|
"""Generate a footnote XML object."""
|
||||||
fStyle = ODTParagraphStyle("New")
|
if content := self._footnotes.get(key):
|
||||||
sStyle = ODTParagraphStyle("New")
|
|
||||||
sStyle.setTextIndent("0.000cm")
|
|
||||||
sStyle.setMarginLeft(self._mLeftFoot)
|
|
||||||
update = [key for key in self._footnotes.keys() if key not in self._etNotes]
|
|
||||||
for key in update:
|
|
||||||
cStyle = fStyle
|
|
||||||
self._nNote += 1
|
self._nNote += 1
|
||||||
|
nStyle = ODTParagraphStyle("New")
|
||||||
xNote = ET.Element(_mkTag("text", "note"), attrib={
|
xNote = ET.Element(_mkTag("text", "note"), attrib={
|
||||||
_mkTag("text", "id"): f"ftn{self._nNote}",
|
_mkTag("text", "id"): f"ftn{self._nNote}",
|
||||||
_mkTag("text", "note-class"): "footnote",
|
_mkTag("text", "note-class"): "footnote",
|
||||||
@@ -775,11 +770,9 @@ class ToOdt(Tokenizer):
|
|||||||
xCite = ET.SubElement(xNote, _mkTag("text", "note-citation"))
|
xCite = ET.SubElement(xNote, _mkTag("text", "note-citation"))
|
||||||
xCite.text = str(self._nNote)
|
xCite.text = str(self._nNote)
|
||||||
xBody = ET.SubElement(xNote, _mkTag("text", "note-body"))
|
xBody = ET.SubElement(xNote, _mkTag("text", "note-body"))
|
||||||
for text, fmt in self._footnotes[key][1]:
|
self._addTextPar(xBody, "Footnote", nStyle, content[0], tFmt=content[1])
|
||||||
self._addTextPar(xBody, "Footnote", cStyle, text, tFmt=fmt)
|
return xNote
|
||||||
cStyle = sStyle
|
return None
|
||||||
self._etNotes[key] = xNote
|
|
||||||
return
|
|
||||||
|
|
||||||
def _emToCm(self, value: float) -> str:
|
def _emToCm(self, value: float) -> str:
|
||||||
"""Converts an em value to centimetres."""
|
"""Converts an em value to centimetres."""
|
||||||
@@ -1584,16 +1577,14 @@ class XMLParagraph:
|
|||||||
def appendNode(self, xNode: ET.Element | None) -> None:
|
def appendNode(self, xNode: ET.Element | None) -> None:
|
||||||
"""Append an XML node to the paragraph."""
|
"""Append an XML node to the paragraph."""
|
||||||
if xNode:
|
if xNode:
|
||||||
# We must make a copy in case the node is reused
|
|
||||||
xCopy = deepcopy(xNode)
|
|
||||||
if self._nState in (X_ROOT_TEXT, X_ROOT_TAIL):
|
if self._nState in (X_ROOT_TEXT, X_ROOT_TAIL):
|
||||||
self._xRoot.append(xCopy)
|
self._xRoot.append(xNode)
|
||||||
self._xTail = xCopy
|
self._xTail = xNode
|
||||||
self._xTail.tail = ""
|
self._xTail.tail = ""
|
||||||
self._nState = X_ROOT_TAIL
|
self._nState = X_ROOT_TAIL
|
||||||
elif self._nState in (X_SPAN_TEXT, X_SPAN_SING):
|
elif self._nState in (X_SPAN_TEXT, X_SPAN_SING):
|
||||||
self._xTail.append(xCopy)
|
self._xTail.append(xNode)
|
||||||
self._xSing = xCopy
|
self._xSing = xNode
|
||||||
self._xSing.tail = ""
|
self._xSing.tail = ""
|
||||||
self._nState = X_SPAN_SING
|
self._nState = X_SPAN_SING
|
||||||
return
|
return
|
||||||
|
|||||||
+7
-6
@@ -65,12 +65,13 @@ class nwItemLayout(Enum):
|
|||||||
class nwComment(Enum):
|
class nwComment(Enum):
|
||||||
|
|
||||||
PLAIN = 0
|
PLAIN = 0
|
||||||
SYNOPSIS = 1
|
IGNORE = 1
|
||||||
SHORT = 2
|
SYNOPSIS = 2
|
||||||
NOTE = 3
|
SHORT = 3
|
||||||
FOOTNOTE = 4
|
NOTE = 4
|
||||||
COMMENT = 5
|
FOOTNOTE = 5
|
||||||
STORY = 6
|
COMMENT = 6
|
||||||
|
STORY = 7
|
||||||
|
|
||||||
# END Enum nwComment
|
# END Enum nwComment
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user