diff --git a/setup/publish.py b/setup/publish.py index 599c881be3..ba8a4992a7 100644 --- a/setup/publish.py +++ b/setup/publish.py @@ -73,11 +73,11 @@ class Manual(Command): os.makedirs(d) if not os.path.exists('.build'+os.sep+'html'): os.makedirs('.build'+os.sep+'html') - os.environ['__appname__']= __appname__ - os.environ['__version__']= __version__ - subprocess.check_call(['sphinx-build', '-b', 'custom', '-t', 'online', + os.environ['__appname__'] = __appname__ + os.environ['__version__'] = __version__ + subprocess.check_call(['sphinx-build', '-b', 'html', '-t', 'online', '-d', '.build/doctrees', '.', '.build/html']) - subprocess.check_call(['sphinx-build', '-b', 'epub', '-d', + subprocess.check_call(['sphinx-build', '-b', 'myepub', '-d', '.build/doctrees', '.', '.build/epub']) shutil.copyfile(self.j('.build', 'epub', 'calibre.epub'), self.j('.build', 'html', 'calibre.epub')) diff --git a/src/calibre/manual/Makefile b/src/calibre/manual/Makefile index c856e105fd..f991cb8777 100644 --- a/src/calibre/manual/Makefile +++ b/src/calibre/manual/Makefile @@ -37,7 +37,7 @@ qthelp: epub: mkdir -p .build/qthelp .build/doctrees - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) .build/epub + $(SPHINXBUILD) -b myepub $(ALLSPHINXOPTS) .build/epub @echo @echo "Build finished." diff --git a/src/calibre/manual/conf.py b/src/calibre/manual/conf.py index 3866008f1f..fc8962bcfd 100644 --- a/src/calibre/manual/conf.py +++ b/src/calibre/manual/conf.py @@ -23,9 +23,11 @@ custom # General configuration # --------------------- +needs_sphinx = '1.0' + # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.addons.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'custom'] +extensions = ['sphinx.ext.autodoc', 'custom', 'sphinx.ext.viewcode'] # Add any paths that contain templates here, relative to this directory. templates_path = ['templates'] @@ -36,6 +38,9 @@ source_suffix = '.rst' # The master toctree document. master_doc = 'index' +# The language +language = 'en' + # General substitutions. project = __appname__ copyright = '2008, Kovid Goyal' @@ -81,7 +86,6 @@ pygments_style = 'sphinx' # given in html_static_path. html_theme = 'default' html_theme_options = {'stickysidebar':'true', 'relbarbgcolor':'black'} -html_style = 'calibre.css' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, @@ -100,8 +104,16 @@ html_use_smartypants = True html_title = 'calibre User Manual' html_short_title = 'Start' html_logo = 'resources/logo.png' + epub_author = 'Kovid Goyal' -epub_cover = 'resources/epub_cover.jpg' +epub_cover = 'epub_cover.jpg' +epub_publisher = 'Kovid Goyal' +epub_identifier = 'http://calibre-ebook.com/user_manual' +epub_scheme = 'url' +epub_uid = 'S54a88f8e9d42455e9c6db000e989225f' +epub_tocdepth = 4 +epub_tocdup = True +epub_pre_files = [('epub_titlepage.html', 'Cover')] # Custom sidebar templates, maps document names to template names. #html_sidebars = {} diff --git a/src/calibre/manual/custom.py b/src/calibre/manual/custom.py index 917b927086..b50853f6d5 100644 --- a/src/calibre/manual/custom.py +++ b/src/calibre/manual/custom.py @@ -9,9 +9,6 @@ sys.path.insert(0, os.path.abspath('../../')) sys.extensions_location = '../plugins' sys.resources_location = '../../../resources' -from sphinx.builders.html import StandaloneHTMLBuilder -from qthelp import QtHelpBuilder -from epub import EPUBHelpBuilder from sphinx.util import rpartition from sphinx.util.console import bold from sphinx.ext.autodoc import prepare_docstring @@ -20,12 +17,7 @@ from docutils import nodes sys.path.append(os.path.abspath('../../../')) from calibre.linux import entry_points - -class CustomBuilder(StandaloneHTMLBuilder): - name = 'custom' - -class CustomQtBuild(QtHelpBuilder): - name = 'customqt' +from epub import EPUBHelpBuilder def substitute(app, doctree): pass @@ -305,9 +297,6 @@ def auto_member(dirname, arguments, options, content, lineno, def setup(app): app.add_config_value('epub_cover', None, False) - app.add_config_value('epub_author', '', False) - app.add_builder(CustomBuilder) - app.add_builder(CustomQtBuild) app.add_builder(EPUBHelpBuilder) app.add_directive('automember', auto_member, 1, (1, 0, 1)) app.connect('doctree-read', substitute) diff --git a/src/calibre/manual/epub.py b/src/calibre/manual/epub.py index d54eb99a8d..a162303b09 100644 --- a/src/calibre/manual/epub.py +++ b/src/calibre/manual/epub.py @@ -6,298 +6,53 @@ __license__ = 'GPL v3' __copyright__ = '2009, Kovid Goyal ' __docformat__ = 'restructuredtext en' -import os, mimetypes, uuid, shutil -from datetime import datetime -from docutils import nodes -from xml.sax.saxutils import escape, quoteattr -from urlparse import urldefrag -from zipfile import ZipFile, ZIP_STORED, ZipInfo +import os, time -from sphinx import addnodes -from sphinx.builders.html import StandaloneHTMLBuilder +from sphinx.builders.epub import EpubBuilder -NCX = '''\ - - - - - - - - - - Table of Contents - - {navpoints} - - -''' +class EPUBHelpBuilder(EpubBuilder): + name = 'myepub' -OPF = '''\ - - - - {title} - {author} - Sphinx - {uid} - {date} - - - - - {manifest} - - - {spine} - - - {guide} - - -''' + def add_cover(self, outdir, cover_fname): + href = '_static/'+cover_fname + opf = os.path.join(self.outdir, 'content.opf') -CONTAINER='''\ - - - - - - -''' - -SVG_TEMPLATE = '''\ - - - - - Cover - - - - - - - - -''' - -class TOC(list): - - def __init__(self, title=None, href=None): - list.__init__(self) - self.title, self.href = title, href - - def create_child(self, title, href): - self.append(TOC(title, href)) - return self[-1] - - def depth(self): - try: - return max(node.depth() for node in self)+1 - except ValueError: - return 1 + cover = '''\ + + + + + Cover + + + + + + + + + '''%href + self.files.append('epub_titlepage.html') + open(os.path.join(outdir, self.files[-1]), 'wb').write(cover) -class EPUBHelpBuilder(StandaloneHTMLBuilder): - """ - Builder that also outputs Qt help project, contents and index files. - """ - name = 'epub' - - # don't copy the reST source - copysource = False - - supported_image_types = ['image/svg+xml', 'image/png', 'image/gif', - 'image/jpeg'] - - # don't add links - add_permalinks = False - # don't add sidebar etc. - embedded = True - - def init(self): - StandaloneHTMLBuilder.init(self) - self.out_suffix = '.html' - self.link_suffix = '.html' - self.html_outdir = self.outdir = os.path.join(self.outdir, 'src') - self.conf = self.config - - def finish(self): - StandaloneHTMLBuilder.finish(self) - self.create_titlepage() - self.outdir = os.path.dirname(self.outdir) - cwd = os.getcwd() - os.chdir(self.html_outdir) - try: - self.generate_manifest() - self.generate_toc() - self.render_opf() - self.render_epub() - finally: - os.chdir(cwd) - - def render_epub(self): - container = CONTAINER.format('content.opf') - path = os.path.abspath('..'+os.sep+self.conf.project+'.epub') - zf = ZipFile(path, 'w') - zi = ZipInfo('mimetype') - zi.compress_type = ZIP_STORED - zf.writestr(zi, 'application/epub+zip') - zf.writestr('META-INF/container.xml', container) - for url in self.manifest: - fp = os.path.join(self.html_outdir, *url.split('/')) - zf.write(fp, url) - zf.close() - self.info('EPUB created at: '+path) - - - def render_opf(self): - manifest = [] - for href in self.manifest: - mt, id = self.manifest[href] - manifest.append(' '*8 + ''%\ - tuple(map(quoteattr, (id, href, mt)))) - manifest = '\n'.join(manifest) - spine = [' '*8+''%quoteattr(x) for x in self.spine] - spine = '\n'.join(spine) - guide = '' - - opf = OPF.format(title=escape(self.conf.html_title), - author=escape(self.conf.epub_author), uid=str(uuid.uuid4()), - date=datetime.now().isoformat(), manifest=manifest, spine=spine, - guide=guide) - open('content.opf', 'wb').write(opf) - self.manifest['content.opf'] = ('application/oebps-package+xml', 'opf') - - def create_titlepage(self): - self.cover_image_url = None - if self.conf.epub_cover: - img = '_static/'+os.path.basename(self.conf.epub_cover) - shutil.copyfile(self.conf.epub_cover, os.path.join(self.html_outdir, - *img.split('/'))) - self.cover_image_url = img - tp = SVG_TEMPLATE%img.split('/')[-1] - open(os.path.join(self.html_outdir, '_static', 'titlepage.html'), - 'wb').write(tp) - - def generate_manifest(self): - self.manifest = {} - id = 1 - for dirpath, dirnames, filenames in os.walk('.'): - for fname in filenames: - if fname == '.buildinfo': - continue - fpath = os.path.abspath(os.path.join(dirpath, fname)) - url = os.path.relpath(fpath).replace(os.sep, '/') - self.manifest[url] = mimetypes.guess_type(url, False)[0] - if self.manifest[url] is None: - self.warn('Unknown mimetype for: ' + url) - self.manifest[url] = 'application/octet-stream' - if self.manifest[url] == 'text/html': - self.manifest[url] = 'application/xhtml+xml' - if self.cover_image_url and url.endswith(self.cover_image_url): - id_ = 'cover' - else: - id_ = 'id'+str(id) - id += 1 - self.manifest[url] = (self.manifest[url], id_) - - def isdocnode(self, node): - if not isinstance(node, nodes.list_item): - return False - if len(node.children) != 2: - return False - if not isinstance(node.children[0], addnodes.compact_paragraph): - return False - if not isinstance(node.children[0][0], nodes.reference): - return False - if not isinstance(node.children[1], nodes.bullet_list): - return False - return True - - def generate_toc(self): - tocdoc = self.env.get_and_resolve_doctree(self.config.master_doc, self, - prune_toctrees=False) - istoctree = lambda node: ( - isinstance(node, addnodes.compact_paragraph) - and node.has_key('toctree')) - toc = TOC() - for node in tocdoc.traverse(istoctree): - self.extend_toc(toc, node) - self._parts = [] - self._po = 0 - self._po_map = {} - self.spine_map = {} - self.spine = [] - self.render_toc(toc) - navpoints = '\n'.join(self._parts).strip() - ncx = NCX.format(uid=str(uuid.uuid4()), depth=toc.depth(), - navpoints=navpoints) - open('toc.ncx', 'wb').write(ncx) - self.manifest['toc.ncx'] = ('application/x-dtbncx+xml', 'ncx') - self.spine.insert(0, self.manifest[self.conf.master_doc+'.html'][1]) - if self.conf.epub_cover: - self.spine.insert(0, self.manifest['_static/titlepage.html'][1]) - - def add_to_spine(self, href): - href = urldefrag(href)[0] - if href not in self.spine_map: - for url in self.manifest: - if url == href: - self.spine_map[href]= self.manifest[url][1] - self.spine.append(self.spine_map[href]) - - def render_toc(self, toc, level=2): - for child in toc: - if child.title and child.href: - href = child.href - self.add_to_spine(href) - title = escape(child.title) - if isinstance(title, unicode): - title = title.encode('utf-8') - if child.href in self._po_map: - po = self._po_map[child.href] - else: - self._po += 1 - po = self._po - self._parts.append(' '*(level*4)+ - ''%(uuid.uuid4(), - po)) - self._parts.append(' '*((level+1)*4)+ - '%s'%title) - self._parts.append(' '*((level+1)*4)+ - ''%quoteattr(href)) - self.render_toc(child, level+1) - self._parts.append(' '*(level*4)+'') - - - - - def extend_toc(self, toc, node): - if self.isdocnode(node): - refnode = node.children[0][0] - parent = toc.create_child(refnode.astext(), refnode['refuri']) - for subnode in node.children[1]: - self.extend_toc(parent, subnode) - elif isinstance(node, (nodes.list_item, nodes.bullet_list, - addnodes.compact_paragraph)): - for subnode in node: - self.extend_toc(toc, subnode) - elif isinstance(node, nodes.reference): - parent = toc.create_child(node.astext(), node['refuri']) - + raw = open(opf, 'rb').read() + raw = raw.replace('', + ('\n' + '%s\n') % + (href.replace('/', '_'), time.strftime('%Y-%m-%d'))) + raw = raw.replace('', + ('\n').\ + format('epub_titlepage.html')) + open(opf, 'wb').write(raw) + def build_epub(self, outdir, *args, **kwargs): + if self.config.epub_cover: + self.add_cover(outdir, self.config.epub_cover) + EpubBuilder.build_epub(self, outdir, *args, **kwargs) diff --git a/src/calibre/manual/resources/calibre.css b/src/calibre/manual/resources/calibre.css deleted file mode 100644 index f815378df4..0000000000 --- a/src/calibre/manual/resources/calibre.css +++ /dev/null @@ -1,5 +0,0 @@ - -@import url("default.css"); - -table.docutils td, table.docutils th { padding: 1em; border-bottom: 0; } - diff --git a/src/calibre/manual/resources/logo.png b/src/calibre/manual/resources/logo.png index 42b9568956..158bc9d1b5 100644 Binary files a/src/calibre/manual/resources/logo.png and b/src/calibre/manual/resources/logo.png differ