ToC Editor: When auto-geenrating the table of contents from headings or XPath, if an element is at the top of the file, link only to the file instead of to the element. Fixes #1261099 [[Enhancement]ToC Editor senses when link is to top of file](https://bugs.launchpad.net/calibre/+bug/1261099)

This commit is contained in:
Kovid Goyal 2013-12-24 16:20:32 +05:30
parent b04b125f34
commit 741bf9577e
2 changed files with 28 additions and 19 deletions

View File

@ -484,31 +484,15 @@ class EPUBOutput(OutputFormatPlugin):
Perform toc link transforms to alleviate slow loading.
'''
from calibre.ebooks.oeb.base import urldefrag, XPath
from calibre.ebooks.oeb.polish.toc import item_at_top
def frag_is_at_top(root, frag):
body = XPath('//h:body')(root)
if body:
body = body[0]
else:
return False
tree = body.getroottree()
elem = XPath('//*[@id="%s" or @name="%s"]'%(frag, frag))(root)
if elem:
elem = elem[0]
else:
return False
path = tree.getpath(elem)
for el in body.iterdescendants():
epath = tree.getpath(el)
if epath == path:
break
if el.text and el.text.strip():
return False
if not path.startswith(epath):
# Only check tail of non-parent elements
if el.tail and el.tail.strip():
return False
return True
return item_at_top(elem)
def simplify_toc_entry(toc):
if toc.href:

View File

@ -211,6 +211,28 @@ def elem_to_toc_text(elem):
text = _('(Untitled)')
return text
def item_at_top(elem):
try:
body = XPath('//h:body')(elem.getroottree().getroot())[0]
except (TypeError, IndexError, KeyError, AttributeError):
return False
tree = body.getroottree()
path = tree.getpath(elem)
for el in body.iterdescendants(etree.Element):
epath = tree.getpath(el)
if epath == path:
break
try:
if el.tag.endswith('}img') or (el.text and el.text.strip()):
return False
except:
return False
if not path.startswith(epath):
# Only check tail of non-parent elements
if el.tail and el.tail.strip():
return False
return True
def from_xpaths(container, xpaths):
tocroot = TOC()
xpaths = [XPath(xp) for xp in xpaths]
@ -249,6 +271,9 @@ def from_xpaths(container, xpaths):
plvl -= 1
parent = level_prev[plvl]
lvl = plvl + 1
if item_at_top(item):
dirtied, elem_id = False, None
else:
dirtied, elem_id = ensure_id(item)
text = elem_to_toc_text(item)
item_dirtied = dirtied or item_dirtied