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. Perform toc link transforms to alleviate slow loading.
''' '''
from calibre.ebooks.oeb.base import urldefrag, XPath 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): 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) elem = XPath('//*[@id="%s" or @name="%s"]'%(frag, frag))(root)
if elem: if elem:
elem = elem[0] elem = elem[0]
else: else:
return False return False
path = tree.getpath(elem) return item_at_top(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
def simplify_toc_entry(toc): def simplify_toc_entry(toc):
if toc.href: if toc.href:

View File

@ -211,6 +211,28 @@ def elem_to_toc_text(elem):
text = _('(Untitled)') text = _('(Untitled)')
return text 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): def from_xpaths(container, xpaths):
tocroot = TOC() tocroot = TOC()
xpaths = [XPath(xp) for xp in xpaths] xpaths = [XPath(xp) for xp in xpaths]
@ -249,7 +271,10 @@ def from_xpaths(container, xpaths):
plvl -= 1 plvl -= 1
parent = level_prev[plvl] parent = level_prev[plvl]
lvl = plvl + 1 lvl = plvl + 1
dirtied, elem_id = ensure_id(item) if item_at_top(item):
dirtied, elem_id = False, None
else:
dirtied, elem_id = ensure_id(item)
text = elem_to_toc_text(item) text = elem_to_toc_text(item)
item_dirtied = dirtied or item_dirtied item_dirtied = dirtied or item_dirtied
toc = parent.add(text, name, elem_id) toc = parent.add(text, name, elem_id)