Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Handle more cases of epub footnotes.
  • Loading branch information
calcnerd256 committed Mar 22, 2016
1 parent c2248a8 commit 6dc31b9
Showing 1 changed file with 113 additions and 18 deletions.
131 changes: 113 additions & 18 deletions Skripten/EOAconvert.py
Expand Up @@ -803,23 +803,30 @@ def cleanup():
intNoteNumber += 1


# the new-style footnotes that use LaTeX bigfoot show up in the following order:
footnote_groups = ["decimal", "lower-latin"]

def get_bigfoot_data(chapter):
# footnotes are per-chapter, with numbers resetting
"""
footnotes are per-chapter
footnote numbers reset for each chapter
this helper takes a chapter and returns a collection containing its new-style footnotes that use LaTeX bigfoot
the result is an association list: a list of key-value pairs
the values are, for each type of footnote, a list of the footnotes of that type, in the order in which they appear in the chapter
"""
xmlBigfootNotes = list(chapter.findall(".//EOAbigfoot"))
return [
(
grouping,
[
return [ # a list
( # of tuples
grouping, # the key
[ # the value: a filter of the above list
note
for note
in xmlBigfootNotes
if grouping == note.get("list-style-type")
],
)
for grouping
in footnote_groups
in footnote_groups # the types we support
]


Expand Down Expand Up @@ -1508,15 +1515,38 @@ def get_bigfoot_data(chapter):
print ("-----------------------------------------------------")
print ("Preparing Footnotes")

def alph_fndex(fndex):
def alph_footnote_index(fndex):
"""
lowercase Latin footnotes need to support more than 26 values
These are zero-indexed.
>>> alph_footnote_index(0)
'a'
>>> alph_footnote_index(1)
'b'
>>> alph_footnote_index(24)
'y'
>>> alph_footnote_index(25)
'z'
>>> alph_footnote_index(26)
'aa'
>>> alph_footnote_index(27)
'ab'
"""
alphabet = "abcdefghijklmnopqrstuvwxyz"
quotient, remainder = divmod(fndex, len(alphabet))
if not quotient: return alphabet[fndex]
return alph_fndex(quotient - 1) + alph_fndex(remainder)
return alph_footnote_index(quotient - 1) + alph_footnote_index(remainder)


def replace_footnote_equations(footnote):
# usage: contentopf = replace_footnote_equations(my_footnote)
"""
captures reusable behavior from the existing code
potentially, some of the old code could be replaced by calls to this helper
usage: contentopf = replace_footnote_equations(my_footnote)
unfortunately, returning the result seemed like a better idea than mutating the global variable
"""
result = contentopf
for equation in footnote.findall(".//EOAequationnonumber"):
filename = equation.get("filename")
Expand All @@ -1531,42 +1561,99 @@ def replace_footnote_equations(footnote):


def replace_footnote_with_sup(note):
"""
captures reusable behavior from the existing code
potentially, some of the old code could be replaced by calls to this helper
this behavior showed up in a few places
I thought I would be able to extract a little more, but this was all that was actually common
"""
tail = note.tail
note.clear()
note.tail = tail
note.tag = "sup"


def bring_footnote_down_epub(footnote, footnote_name, destination):
contentopf = replace_footnote_equations(footnote)
"""
captures reusable behavior from the existing code
potentially, some of the old code could be replaced by calls to this helper
"""

contentopf = replace_footnote_equations(footnote) # see usage note
kids = list(footnote.getchildren())
if len(kids):
first_child = kids[0]
first_child.text = "[%s] %s" % (footnote_name, (first_child.text or ""))
prefix = "[%s]" % footnote_name

# we would like to prepend this footnote identifier to the footnote element
if footnote.text is not None:
# if the element starts with some text anyway, prepend it there
footnote.text = "%s %s" (prefix, footnote.text)
else:
# if, however, the element begins with a child, prepend the text at the beginning of the first child instead
if len(kids):
first_child = kids[0]
child_text = prefix
# separate them with a space, unless the child had no text to begin with
child_suffix = first_child.text
if child_suffix is None:
child_suffix = ""
else:
child_prefix += " "
first_child.text = child_prefix + child_suffix
else:
# a totally empty footnote is weird, but who am I to judge?
footnote.text = prefix
footnote_text = footnote.text or ""
replace_footnote_with_sup(footnote)
footnote.text = "[%s] " % footnote_name
# append any text the footnote used to have to the destination
destkids = list(destination.getchildren())
if len(destkids):
# if the destination has children, append after the last one's tail
last_kid = destkids[-1]
prefix = last_kid.tail
if prefix is None:
prefix = ""
else:
prefix += " "
last_kid.tail = prefix + footnote_text
else:
# if the destination has no children, append to its text
prefix = destination.text
if prefix is None:
prefix = ""
else:
prefix += " "
destination.text = prefix + footnote_text
for kid in kids:
destination.append(kid)
return contentopf


class FootnoteError(Exception):
"""
we only support one type of footnote per chapter
don't try to mix-and-match
"""
pass


for xmlChapter in xmlChapters:
groupings = get_bigfoot_data(xmlChapter)
xmlFootnotes = list(xmlChapter.findall(".//note"))
has_old = 0 != len(xmlFootnotes)
has_new = 0 != len(
[
[ # flatten the association list whose values are lists, so we can take the length
note
for grouping, notes in groupings
for note in notes
]
)

# the XOR case falls through, the AND is an error, and the NOR skips to the next chapter
if has_old:
if has_new:
raise FootnoteError("This chapter contains both old-style footnotes and new-style footnotes")
raise FootnoteError("Chapter %s contains both \\EOAfn and footnotes in the style of \\EOAfnalph" % xmlChapter.get("id-text"))
else:
if not has_new:
continue
Expand All @@ -1575,10 +1662,11 @@ class FootnoteError(Exception):
xmlNewFootnotesHeader.text = dictLangFootnotes[xmlChapter.get("language")]
xmlNewFootnotes.append(xmlNewFootnotesHeader)
for grouping, notes in groupings:
# do for the new-style footnotes what was being done for the old
for index, note in enumerate(notes):
footnote_name = str(index + 1)
if "lower-latin" == grouping:
footnote_name = alph_fndex(index)
footnote_name = alph_footnote_index(index)
para = etree.Element("p")
para.text = "[%s] %s" % (footnote_name, note.text)
contentopf = bring_footnote_down_epub(note, footnote_name, para)
Expand Down Expand Up @@ -2792,6 +2880,11 @@ def djangoParseHeadline(xmlElement):
print ("Processing and linking Footnotes for django")

def bring_footnote_down_django(footnote, fragment, footnote_number, object_number, unique_id, destination):
"""
captures reusable behavior from the existing code
potentially, some of the old code could be replaced by calls to this helper
"""

kids = list(footnote.getchildren())
footnote_text = footnote.text or ""
replace_footnote_with_sup(footnote)
Expand Down Expand Up @@ -2834,12 +2927,13 @@ def bring_footnote_down_django(footnote, fragment, footnote_number, object_numbe
groupings = get_bigfoot_data(xmlEOAchapter)
has_old = 0 != len(xmlEOAchapter.findall(".//note"))
has_new = 0 != len(
[
[ # flatten
note
for grouping, notes in groupings
for note in notes
]
)
# XOR falls through, AND is an error (that should have already been thrown during the epub phase), and NOR skips to the next chapter
if has_old:
if has_new:
raise FootnoteError("This chapter contains both old-style footnotes and new-style footnotes")
Expand All @@ -2865,9 +2959,10 @@ def bring_footnote_down_django(footnote, fragment, footnote_number, object_numbe

for grouping, notes in groupings:
for index, note in enumerate(notes):
# do for the new-style notes what the old code did for the other footnotes
fntext = str(index+1)
if "lower-latin" == grouping:
fntext = alph_fndex(index)
fntext = alph_footnote_index(index)
unique_id = "fn%s" % fntext
intObjectNumber = bring_footnote_down_django(note, unique_id, fntext, intObjectNumber, unique_id, xmlResult)

Expand Down

0 comments on commit 6dc31b9

Please sign in to comment.