1 """Module for dealing with booki -> epub conversions."""
6 from cStringIO
import StringIO
8 import lxml
.html
, lxml
.cssselect
11 from objavi
.book_utils
import log
12 from objavi
.config
import NAVPOINT_ID_TEMPLATE
14 from booki
.bookizip
import get_metadata
17 BARE_NCX
= ('<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN" '
18 '"http://www.daisy.org/z3986/2005/ncx-2005-1.dtd"> '
19 '<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1" />')
21 def add_ncxtext(parent
, tag
, text
):
22 """put text in a <text> subelement (as required by navLabel, navInfo)."""
23 el
= etree
.SubElement(parent
, tag
)
24 el2
= etree
.SubElement(el
, 'text')
28 def make_ncx(toc
, metadata
, filemap
):
30 tree
= etree
.parse(StringIO(BARE_NCX
))
32 head
= etree
.SubElement(root
, 'head')
33 add_ncxtext(root
, 'docTitle', get_metadata(metadata
, 'title')[0])
34 navmap
= etree
.SubElement(root
, 'navMap')
35 counter
, maxdepth
= 0, 0
37 counter
, maxdepth
= write_navtree(navmap
, subtoc
, counter
, 1, maxdepth
, filemap
)
38 ids
= get_metadata(metadata
, 'identifier')
39 if not ids
: #workaround for one-time broken booki
40 ids
= [time
.strftime('http://booki.cc/UNKNOWN/%Y.%m.%d-%H.%M.%S')]
42 for name
, content
in (('dtb:uid', ids
[0]),
43 ('dtb:depth', str(maxdepth
)),
44 ('dtb:totalPageCount', '0'),
45 ('dtb:maxPageNumber', '0')
47 etree
.SubElement(head
, 'meta', name
=name
, content
=content
)
48 return etree
.tostring(tree
, pretty_print
=True, encoding
='utf-8')
51 def write_navtree(parent
, subtoc
, counter
, depth
, maxdepth
, filemap
):
52 #subtoc has this structure:
54 # "title": division title (optional),
55 # "url": filename and possible fragment ID,
56 # "type": string indicating division type (optional),
57 # "role": epub guide type (optional),
58 # "children": list of TOC structures (optional)
64 title
= subtoc
.get('title', '')
66 children
= subtoc
.get('children', [])
68 if url
is None and children
:
69 # if the section has no url, it begins with its first child
70 url
= children
[0]['url']
73 url
= filemap
.get(url
, url
)
75 navpoint
= make_navpoint(parent
, counter
, title
, url
)
76 for point
in children
:
77 counter
, maxdepth
= write_navtree(navpoint
, point
, counter
, depth
+ 1, maxdepth
, filemap
)
79 return counter
, maxdepth
81 def make_navpoint(parent
, n
, title
, url
):
82 """Make the actual navpoint node"""
83 log((parent
, n
, title
, url
))
84 navpoint
= etree
.SubElement(parent
, 'navPoint',
85 id=(NAVPOINT_ID_TEMPLATE
% (n
- 1)),
87 add_ncxtext(navpoint
, 'navLabel', title
)
88 etree
.SubElement(navpoint
, 'content', src
=url
)