if no id, make up a good one, not an empty string
[objavi2.git] / objavi / epub_utils.py
blob00a40edace1751fa9615316c2a658839c2b23ea6
1 """Module for dealing with booki -> epub conversions."""
3 import os, sys
4 from pprint import pprint
5 #import zipfile
6 from cStringIO import StringIO
8 import lxml, lxml.html, lxml.cssselect
9 from lxml import etree
11 from objavi.cgi_utils import log
12 from objavi.config import DC, XHTML, XHTMLNS, NAVPOINT_ID_TEMPLATE
14 from booki.bookizip import get_metadata, get_metadata_schemes
16 ##Construct NCX
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')
25 el2.text = text
28 def make_ncx(toc, metadata, filemap):
29 log(filemap)
30 tree = etree.parse(StringIO(BARE_NCX))
31 root = tree.getroot()
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
36 for subtoc in toc:
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://book.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)
60 counter += 1
61 if depth > maxdepth:
62 maxdepth = depth
64 title = subtoc.get('title', '')
65 url = subtoc['url']
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']
72 if filemap:
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 log((parent, n, title, url))
83 """Make the actual navpoint node"""
84 navpoint = etree.SubElement(parent, 'navPoint',
85 id=(NAVPOINT_ID_TEMPLATE % (n - 1)),
86 playOrder=str(n))
87 add_ncxtext(navpoint, 'navLabel', title)
88 etree.SubElement(navpoint, 'content', src=url)
89 return navpoint