mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
Implement upgrade for NCX
This commit is contained in:
parent
6eb67b9b80
commit
0e9991c331
@ -19,7 +19,7 @@ from lxml.builder import ElementMaker
|
|||||||
|
|
||||||
from calibre import __version__
|
from calibre import __version__
|
||||||
from calibre.ebooks.oeb.base import (
|
from calibre.ebooks.oeb.base import (
|
||||||
XPath, uuid_id, xml2text, NCX, NCX_NS, XML, XHTML, XHTML_NS, serialize, EPUB_NS)
|
XPath, uuid_id, xml2text, NCX, NCX_NS, XML, XHTML, XHTML_NS, serialize, EPUB_NS, XML_NS, OEB_DOCS)
|
||||||
from calibre.ebooks.oeb.polish.errors import MalformedMarkup
|
from calibre.ebooks.oeb.polish.errors import MalformedMarkup
|
||||||
from calibre.ebooks.oeb.polish.utils import guess_type, extract
|
from calibre.ebooks.oeb.polish.utils import guess_type, extract
|
||||||
from calibre.ebooks.oeb.polish.opf import set_guide_item, get_book_language
|
from calibre.ebooks.oeb.polish.opf import set_guide_item, get_book_language
|
||||||
@ -625,19 +625,9 @@ def commit_ncx_toc(container, toc, lang=None, uid=None):
|
|||||||
container.pretty_print.add(tocname)
|
container.pretty_print.add(tocname)
|
||||||
|
|
||||||
|
|
||||||
def commit_nav_toc(container, toc, lang=None):
|
def ensure_single_nav_of_type(root, ntype='toc'):
|
||||||
from calibre.ebooks.oeb.polish.pretty import pretty_xml_tree
|
|
||||||
tocname = find_existing_nav_toc(container)
|
|
||||||
if tocname is None:
|
|
||||||
item = container.generate_item('nav.xhtml', id_prefix='nav')
|
|
||||||
item.set('properties', 'nav')
|
|
||||||
tocname = container.href_to_name(item.get('href'), base=container.opf_name)
|
|
||||||
try:
|
|
||||||
root = container.parsed(tocname)
|
|
||||||
except KeyError:
|
|
||||||
root = container.parse_xhtml(P('templates/new_nav.html', data=True).decode('utf-8'))
|
|
||||||
et = '{%s}type' % EPUB_NS
|
et = '{%s}type' % EPUB_NS
|
||||||
navs = [n for n in root.iterdescendants(XHTML('nav')) if n.get(et) == 'toc']
|
navs = [n for n in root.iterdescendants(XHTML('nav')) if n.get(et) == ntype]
|
||||||
for x in navs[1:]:
|
for x in navs[1:]:
|
||||||
extract(x)
|
extract(x)
|
||||||
if navs:
|
if navs:
|
||||||
@ -650,7 +640,26 @@ def commit_nav_toc(container, toc, lang=None):
|
|||||||
else:
|
else:
|
||||||
nav = root.makeelement(XHTML('nav'))
|
nav = root.makeelement(XHTML('nav'))
|
||||||
first_child(root, XHTML('body')).append(nav)
|
first_child(root, XHTML('body')).append(nav)
|
||||||
nav.set('{%s}type' % EPUB_NS, 'toc')
|
nav.set('{%s}type' % EPUB_NS, ntype)
|
||||||
|
return nav
|
||||||
|
|
||||||
|
|
||||||
|
def commit_nav_toc(container, toc, lang=None, landmarks=None):
|
||||||
|
from calibre.ebooks.oeb.polish.pretty import pretty_xml_tree
|
||||||
|
tocname = find_existing_nav_toc(container)
|
||||||
|
if tocname is None:
|
||||||
|
item = container.generate_item('nav.xhtml', id_prefix='nav')
|
||||||
|
item.set('properties', 'nav')
|
||||||
|
tocname = container.href_to_name(item.get('href'), base=container.opf_name)
|
||||||
|
root = container.parse_xhtml(P('templates/new_nav.html', data=True).decode('utf-8'))
|
||||||
|
container.replace(tocname, root)
|
||||||
|
else:
|
||||||
|
root = container.parsed(tocname)
|
||||||
|
if lang:
|
||||||
|
lang = lang_as_iso639_1(lang) or lang
|
||||||
|
root.set('lang', lang)
|
||||||
|
root.set('{%s}lang' % XML_NS, lang)
|
||||||
|
nav = ensure_single_nav_of_type(root, 'toc')
|
||||||
if toc.toc_title:
|
if toc.toc_title:
|
||||||
nav.append(nav.makeelement(XHTML('h1')))
|
nav.append(nav.makeelement(XHTML('h1')))
|
||||||
nav[-1].text = toc.toc_title
|
nav[-1].text = toc.toc_title
|
||||||
@ -679,11 +688,35 @@ def commit_nav_toc(container, toc, lang=None):
|
|||||||
li.append(ol)
|
li.append(ol)
|
||||||
process_node(ol, child)
|
process_node(ol, child)
|
||||||
process_node(rnode, toc)
|
process_node(rnode, toc)
|
||||||
pretty_xml_tree(rnode)
|
pretty_xml_tree(nav)
|
||||||
for li in rnode.iterdescendants(XHTML('li')):
|
|
||||||
|
def collapse_li(parent):
|
||||||
|
for li in parent.iterdescendants(XHTML('li')):
|
||||||
if len(li) == 1:
|
if len(li) == 1:
|
||||||
li.text = None
|
li.text = None
|
||||||
li[0].tail = None
|
li[0].tail = None
|
||||||
|
collapse_li(nav)
|
||||||
|
nav.tail = '\n'
|
||||||
|
|
||||||
|
if landmarks is not None:
|
||||||
|
nav = ensure_single_nav_of_type(root, 'landmarks')
|
||||||
|
nav.set('hidden', '')
|
||||||
|
ol = nav.makeelement(XHTML('ol'))
|
||||||
|
nav.append(ol)
|
||||||
|
for entry in landmarks:
|
||||||
|
if entry['type'] and container.has_name(entry['dest']) and container.mime_map[entry['dest']] in OEB_DOCS:
|
||||||
|
li = ol.makeelement(XHTML('li'))
|
||||||
|
ol.append(li)
|
||||||
|
a = li.makeelement(XHTML('a'))
|
||||||
|
li.append(a)
|
||||||
|
a.set('{%s}type' % EPUB_NS, entry['type'])
|
||||||
|
href = container.name_to_href(entry['dest'], tocname)
|
||||||
|
if entry['frag']:
|
||||||
|
href += '#' + entry['frag']
|
||||||
|
a.set('href', href)
|
||||||
|
a.text = entry['title'] or None
|
||||||
|
pretty_xml_tree(nav)
|
||||||
|
collapse_li(nav)
|
||||||
container.replace(tocname, root)
|
container.replace(tocname, root)
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,9 +4,15 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
from calibre.ebooks.metadata.opf_2_to_3 import upgrade_metadata
|
from calibre.ebooks.metadata.opf_2_to_3 import upgrade_metadata
|
||||||
from calibre.ebooks.oeb.base import OEB_DOCS, xpath
|
from calibre.ebooks.oeb.base import OEB_DOCS, xpath
|
||||||
from calibre.ebooks.oeb.polish.container import OEB_FONTS
|
from calibre.ebooks.oeb.polish.container import OEB_FONTS
|
||||||
|
from calibre.ebooks.oeb.polish.opf import get_book_language
|
||||||
|
from calibre.ebooks.oeb.polish.toc import (
|
||||||
|
commit_nav_toc, find_existing_ncx_toc, get_landmarks, get_toc
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def add_properties(item, *props):
|
def add_properties(item, *props):
|
||||||
@ -44,9 +50,76 @@ def collect_properties(container):
|
|||||||
add_properties(item, *tuple(properties))
|
add_properties(item, *tuple(properties))
|
||||||
|
|
||||||
|
|
||||||
|
guide_epubtype_map = {
|
||||||
|
'acknowledgements' : 'acknowledgments',
|
||||||
|
'other.afterword' : 'afterword',
|
||||||
|
'other.appendix' : 'appendix',
|
||||||
|
'other.backmatter' : 'backmatter',
|
||||||
|
'bibliography' : 'bibliography',
|
||||||
|
'text' : 'bodymatter',
|
||||||
|
'other.chapter' : 'chapter',
|
||||||
|
'colophon' : 'colophon',
|
||||||
|
'other.conclusion' : 'conclusion',
|
||||||
|
'other.contributors' : 'contributors',
|
||||||
|
'copyright-page' : 'copyright-page',
|
||||||
|
'cover' : 'cover',
|
||||||
|
'dedication' : 'dedication',
|
||||||
|
'other.division' : 'division',
|
||||||
|
'epigraph' : 'epigraph',
|
||||||
|
'other.epilogue' : 'epilogue',
|
||||||
|
'other.errata' : 'errata',
|
||||||
|
'other.footnotes' : 'footnotes',
|
||||||
|
'foreword' : 'foreword',
|
||||||
|
'other.frontmatter' : 'frontmatter',
|
||||||
|
'glossary' : 'glossary',
|
||||||
|
'other.halftitlepage': 'halftitlepage',
|
||||||
|
'other.imprint' : 'imprint',
|
||||||
|
'other.imprimatur' : 'imprimatur',
|
||||||
|
'index' : 'index',
|
||||||
|
'other.introduction' : 'introduction',
|
||||||
|
'other.landmarks' : 'landmarks',
|
||||||
|
'other.loa' : 'loa',
|
||||||
|
'loi' : 'loi',
|
||||||
|
'lot' : 'lot',
|
||||||
|
'other.lov' : 'lov',
|
||||||
|
'notes' : '',
|
||||||
|
'other.notice' : 'notice',
|
||||||
|
'other.other-credits': 'other-credits',
|
||||||
|
'other.part' : 'part',
|
||||||
|
'other.preamble' : 'preamble',
|
||||||
|
'preface' : 'preface',
|
||||||
|
'other.prologue' : 'prologue',
|
||||||
|
'other.rearnotes' : 'rearnotes',
|
||||||
|
'other.subchapter' : 'subchapter',
|
||||||
|
'title-page' : 'titlepage',
|
||||||
|
'toc' : 'toc',
|
||||||
|
'other.volume' : 'volume',
|
||||||
|
'other.warning' : 'warning'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def create_nav(container, toc, landmarks):
|
||||||
|
lang = get_book_language(container)
|
||||||
|
if lang == 'und':
|
||||||
|
lang = None
|
||||||
|
if landmarks:
|
||||||
|
for entry in landmarks:
|
||||||
|
entry['type'] = guide_epubtype_map.get(entry['type'].lower())
|
||||||
|
commit_nav_toc(container, toc, lang=lang, landmarks=landmarks)
|
||||||
|
|
||||||
|
|
||||||
def epub_2_to_3(container, report):
|
def epub_2_to_3(container, report):
|
||||||
upgrade_metadata(container.opf)
|
upgrade_metadata(container.opf)
|
||||||
collect_properties(container)
|
collect_properties(container)
|
||||||
|
toc = get_toc(container)
|
||||||
|
toc_name = find_existing_ncx_toc(container)
|
||||||
|
if toc_name:
|
||||||
|
container.remove_item(toc_name)
|
||||||
|
container.opf_xpath('./opf:spine')[0].attrib.pop('toc', None)
|
||||||
|
landmarks = get_landmarks(container)
|
||||||
|
for guide in container.opf_xpath('./opf:guide'):
|
||||||
|
guide.getparent().remove(guide)
|
||||||
|
create_nav(container, toc, landmarks)
|
||||||
container.opf.set('version', '3.0')
|
container.opf.set('version', '3.0')
|
||||||
fix_font_mime_types(container)
|
fix_font_mime_types(container)
|
||||||
container.dirty(container.opf_name)
|
container.dirty(container.opf_name)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user