def transform(provider, slug=None, file_path=None, output_file=None, output_dir=None, make_dir=False, verbose=False,
+ style=None,
sample=None, cover=None, flags=None):
""" produces a EPUB file
make_dir: writes output to <output_dir>/<author>/<slug>.epub instead of <output_dir>/<slug>.epub
sample=n: generate sample e-book (with at least n paragraphs)
cover: a cover.Cover object
- flags: less-advertising,
+ flags: less-advertising, without-fonts
"""
def transform_file(input_xml, chunk_counter=1, first=True, sample=None):
'<rootfiles><rootfile full-path="OPS/content.opf" ' \
'media-type="application/oebps-package+xml" />' \
'</rootfiles></container>')
- zip.write(get_resource('epub/style.css'), os.path.join('OPS', 'style.css'))
zip.write(get_resource('res/wl-logo-small.png'), os.path.join('OPS', 'logo_wolnelektury.png'))
zip.write(get_resource('res/jedenprocent.png'), os.path.join('OPS', 'jedenprocent.png'))
+ if not style:
+ style = get_resource('epub/style.css')
+ zip.write(style, os.path.join('OPS', 'style.css'))
opf = xslt(metadata, get_resource('epub/xsltContent.xsl'))
manifest = opf.find('.//' + OPFNS('manifest'))
zip.writestr('OPS/last.html', etree.tostring(
html_tree, method="html", pretty_print=True))
- # strip fonts
- tmpdir = mkdtemp('-librarian-epub')
- cwd = os.getcwd()
-
- os.chdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'font-optimizer'))
- for fname in 'DejaVuSerif.ttf', 'DejaVuSerif-Bold.ttf', 'DejaVuSerif-Italic.ttf', 'DejaVuSerif-BoldItalic.ttf':
- optimizer_call = ['perl', 'subset.pl', '--chars', ''.join(chars).encode('utf-8'),
- get_resource('fonts/' + fname), os.path.join(tmpdir, fname)]
- if verbose:
- print "Running font-optimizer"
- subprocess.check_call(optimizer_call)
- else:
- subprocess.check_call(optimizer_call, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- zip.write(os.path.join(tmpdir, fname), os.path.join('OPS', fname))
- rmtree(tmpdir)
- os.chdir(cwd)
+ if not flags or not 'without-fonts' in flags:
+ # strip fonts
+ tmpdir = mkdtemp('-librarian-epub')
+ cwd = os.getcwd()
+
+ os.chdir(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'font-optimizer'))
+ for fname in 'DejaVuSerif.ttf', 'DejaVuSerif-Bold.ttf', 'DejaVuSerif-Italic.ttf', 'DejaVuSerif-BoldItalic.ttf':
+ optimizer_call = ['perl', 'subset.pl', '--chars', ''.join(chars).encode('utf-8'),
+ get_resource('fonts/' + fname), os.path.join(tmpdir, fname)]
+ if verbose:
+ print "Running font-optimizer"
+ subprocess.check_call(optimizer_call)
+ else:
+ subprocess.check_call(optimizer_call, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ zip.write(os.path.join(tmpdir, fname), os.path.join('OPS', fname))
+ manifest.append(etree.fromstring(
+ '<item id="%s" href="%s" media-type="font/ttf" />' % (fname, fname)))
+ rmtree(tmpdir)
+ os.chdir(cwd)
zip.writestr('OPS/content.opf', etree.tostring(opf, pretty_print=True))
contents = []
text-align: left;
}
-.annotation
+.annotation-anchor
{
font-style: normal;
font-weight: normal;
font-size: 0.875em;
-}
-
-#footnotes .annotation
-{
display: block;
float: left;
width: 2.5em;
clear: both;
}
-#footnotes div
+.annotation
{
margin: 0;
margin-top: 1.5em;
}
-#footnotes p
+.annotation-body
{
margin-left: 2.5em;
font-size: 0.875em;
</xsl:template>
<xsl:template match="pa|pe|pr|pt" mode="przypis">
- <div xmlns="http://www.w3.org/1999/xhtml">
+ <div xmlns="http://www.w3.org/1999/xhtml" class="annotation">
<p id="annotation-{@number}" xmlns="http://www.w3.org/1999/xhtml"></p>
- <a class="annotation" href="part{@part}.html#anchor-{@number}" xmlns="http://www.w3.org/1999/xhtml">
+ <a class="annotation-anchor" href="part{@part}.html#anchor-{@number}" xmlns="http://www.w3.org/1999/xhtml">
[<xsl:value-of select="@number" />]
</a>
- <p xmlns="http://www.w3.org/1999/xhtml">
+ <p class="annotation-body" xmlns="http://www.w3.org/1999/xhtml">
<xsl:apply-templates />
<xsl:if test="name()='pa'"> [przypis autorski]</xsl:if>
</p>
<item id="titlePage" href="title.html" media-type="application/xhtml+xml" />
<item id="logo_wolnelektury" href="logo_wolnelektury.png" media-type="image/png" />
<item id="jedenprocent" href="jedenprocent.png" media-type="image/png" />
- <item id="DejaVuSerif.ttf" href="DejaVuSerif.ttf" media-type="font/ttf" />
- <item id="DejaVuSerif-Bold.ttf" href="DejaVuSerif-Bold.ttf" media-type="font/ttf" />
- <item id="DejaVuSerif-BoldItalic.ttf" href="DejaVuSerif-BoldItalic.ttf" media-type="font/ttf" />
- <item id="DejaVuSerif-Italic.ttf" href="DejaVuSerif-Italic.ttf" media-type="font/ttf" />
</manifest>
<spine toc="toc">
<itemref idref="titlePage" />
--- /dev/null
+# -*- coding: utf-8 -*-
+#
+# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+from __future__ import with_statement
+
+import os
+import os.path
+import subprocess
+from StringIO import StringIO
+from copy import deepcopy
+from lxml import etree
+import zipfile
+from tempfile import NamedTemporaryFile
+from shutil import rmtree
+
+import sys
+
+from librarian import epub
+
+from librarian import functions, get_resource
+
+
+def transform(provider, slug=None, file_path=None, output_file=None, output_dir=None, make_dir=False, verbose=False,
+ sample=None, cover=None, flags=None):
+ """ produces a MOBI file
+
+ provider: a DocProvider
+ slug: slug of file to process, available by provider
+ output_file: path to output file
+ output_dir: path to directory to save output file to; either this or output_file must be present
+ make_dir: writes output to <output_dir>/<author>/<slug>.epub instead of <output_dir>/<slug>.epub
+ sample=n: generate sample e-book (with at least n paragraphs)
+ cover: a cover.Cover object
+ flags: less-advertising,
+ """
+
+ # if output to dir, create the file
+ if output_dir is not None:
+ if make_dir:
+ author = unicode(book_info.author)
+ output_dir = os.path.join(output_dir, author)
+ try:
+ os.makedirs(output_dir)
+ except OSError:
+ pass
+ if slug:
+ output_file = os.path.join(output_dir, '%s.mobi' % slug)
+ else:
+ output_file = os.path.join(output_dir, os.path.splitext(os.path.basename(file_path))[0] + '.mobi')
+
+ epub_file = NamedTemporaryFile(suffix='.epub', delete=False)
+ if not flags:
+ flags = []
+ flags = list(flags) + ['without-fonts']
+ epub.transform(provider, file_path=file_path, output_file=epub_file, verbose=verbose,
+ sample=sample, cover=None, flags=flags, style=get_resource('mobi/style.css'))
+ subprocess.check_call(['ebook-convert', epub_file.name, output_file])
+ os.unlink(epub_file.name)
--- /dev/null
+/* =================================================== */
+/* = Common elements: headings, paragraphs and lines = */
+/* =================================================== */
+
+
+.h2
+{
+ font-size: 2em;
+ margin: 0;
+ margin-top: 1.5em;
+ font-weight: bold;
+ line-height: 1.5em;
+}
+
+.h3
+{
+ text-align:left;
+ font-size: 1.5em;
+ margin-top: 1.5em;
+ font-weight: normal;
+ line-height: 1.5em;
+}
+
+.h4
+{
+ font-size: 1em;
+ margin: 0;
+ margin-top: 1.5em;
+ line-height: 1.5em;
+}
+
+p
+{
+ margin: 0;
+}
+
+/* ======================== */
+/* = Footnotes and themes = */
+/* ======================== */
+
+.annotation-anchor
+{
+ font-style: normal;
+ font-weight: normal;
+ font-size: 0.875em;
+ display: block;
+ float: left;
+ width: 2.5em;
+ clear: both;
+}
+
+.annotation
+{
+ margin: 0;
+ margin-top: 1.5em;
+}
+
+.annotation-body
+{
+ margin-left: 2.5em;
+ font-size: 0.875em;
+}
+
+.block
+{
+ font-size: 0.875em;
+ padding: 1em;
+}
+
+/* ============= */
+/* = Numbering = */
+/* ============= */
+
+.anchor
+{
+ margin: -0.25em -0.5em;
+ color: #777;
+ font-size: 0.875em;
+ width: 2em;
+ text-align: center;
+ padding: 0.25em 0.5em;
+ line-height: 1.5em;
+}
+
+/* =================== */
+/* = Custom elements = */
+/* =================== */
+
+.title-page
+{
+ margin-top: 1.5em;
+}
+
+.title
+{
+ font-size: 3em;
+ text-align: center;
+ line-height: 1.5em;
+ font-weight: bold;
+}
+
+.author
+{
+ margin: 0;
+ text-align: center;
+ font-weight: bold;
+
+ font-size: 1.5em;
+ line-height: 1.5em;
+ margin-bottom: 0.25em;
+}
+
+.intitle
+{
+ margin: 0;
+ text-align: center;
+ font-weight: bold;
+
+ font-size: 1.5em;
+ line-height: 1.5em;
+ margin-bottom: 0.25em;
+}
+
+.insubtitle
+{
+ margin: 0;
+ text-align: center;
+ font-weight: bold;
+
+ font-size: 1em;
+ line-height: 1.5em;
+ margin-bottom: 0.25em;
+}
+
+.collection
+{
+ margin: 0;
+ text-align: center;
+ font-weight: bold;
+
+ font-size: 1.125em;
+ line-height: 1.5em;
+ margin-bottom: -0.25em;
+}
+
+.subtitle
+{
+ margin: 0;
+ text-align: center;
+ font-weight: bold;
+
+ font-size: 1.5em;
+ line-height: 1.5em;
+ margin-top: -0.25em;
+}
+
+div.didaskalia
+{
+ font-style: italic;
+ margin-top: 0.5em;
+ margin-left: 1.5em;
+}
+
+div.kwestia
+{
+ margin-top: 0.5em;
+}
+
+.paragraph
+{
+ text-align: justify;
+ margin-top: 1.5em;
+}
+
+.motto
+{
+ text-align: justify;
+ font-style: italic;
+ margin-top: 1.5em;
+}
+
+.motto_podpis
+{
+ font-size: 0.875em;
+ text-align: right;
+}
+
+div.fragment
+{
+ border-bottom: 0.1em solid #999;
+ padding-bottom: 1.5em;
+}
+
+div.note
+{
+ text-align: right;
+ font-style: italic;
+}
+div.note div.paragraph
+{
+ text-align: right;
+ font-style: italic;
+}
+div.dedication
+{
+ text-align: right;
+ font-style: italic;
+}
+div.dedication div.paragaph
+{
+ text-align: right;
+ font-style: italic;
+}
+
+
+hr.spacer
+{
+ height: 3em;
+ visibility: hidden;
+}
+
+hr.spacer-line
+{
+ margin: 0;
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+ border: none;
+ border-bottom: 0.1em solid #000;
+}
+
+.spacer-asterisk
+{
+ padding: 0;
+ margin: 0;
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+ text-align: center;
+}
+
+div.person-list ol
+{
+ list-style: none;
+ padding: 0;
+ padding-left: 1.5em;
+}
+
+.place-and-time
+{
+ font-style: italic;
+}
+
+em.math
+{
+ font-style: italic;
+}
+em.foreign-word
+{
+ font-style: italic;
+}
+em.book-title
+{
+ font-style: italic;
+}
+em.didaskalia
+{
+ font-style: italic;
+}
+
+em.author-emphasis
+{
+ letter-spacing: 0.1em;
+}
+
+.person-list em.person
+{
+ font-style: normal;
+ font-variant: small-caps;
+ /*text-transform: uppercase;*/
+}
+
+.info
+{
+ text-align: center;
+ margin-bottom: 1em;
+}
+.info div
+{
+ text-align: center;
+}
+
+.info img
+{
+ margin: 0;
+ margin-left: 2em;
+ margin-right: 2em;
+}
+
+p.minor {
+ font-size: 0.75em;
+}
+p.footer {
+ margin-top: 2em;
+}
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# This file is part of Librarian, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+import os.path
+import optparse
+
+from librarian import mobi, DirDocProvider, ParseError
+
+
+if __name__ == '__main__':
+ # Parse commandline arguments
+ usage = """Usage: %prog [options] SOURCE [SOURCE...]
+ Convert SOURCE files to MOBI format."""
+
+ parser = optparse.OptionParser(usage=usage)
+
+ parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False,
+ help='print status messages to stdout')
+ parser.add_option('-d', '--make-dir', action='store_true', dest='make_dir', default=False,
+ help='create a directory for author and put the PDF in it')
+ parser.add_option('-o', '--output-file', dest='output_file', metavar='FILE',
+ help='specifies the output file')
+ parser.add_option('-O', '--output-dir', dest='output_dir', metavar='DIR',
+ help='specifies the directory for output')
+
+ options, input_filenames = parser.parse_args()
+
+ if len(input_filenames) < 1:
+ parser.print_help()
+ exit(1)
+
+ # Do some real work
+ try:
+ for main_input in input_filenames:
+ if options.verbose:
+ print main_input
+ path, fname = os.path.realpath(main_input).rsplit('/', 1)
+ provider = DirDocProvider(path)
+
+ output_dir = output_file = None
+ if options.output_dir:
+ output_dir = options.output_dir
+ elif options.output_file:
+ output_file = options.output_file
+ else:
+ output_dir = path
+
+ mobi.transform(provider, file_path=main_input, output_dir=output_dir, output_file=output_file, make_dir=options.make_dir)
+ except ParseError, e:
+ print '%(file)s:%(name)s:%(message)s' % {
+ 'file': main_input,
+ 'name': e.__class__.__name__,
+ 'message': e
+ }
maintainer_email='radek.czajka@gmail.com',
url='http://github.com/fnp/librarian',
packages=['librarian'],
- package_data={'librarian': ['xslt/*.xslt', 'epub/*', 'pdf/*', 'fonts/*', 'res/*'] +
+ package_data={'librarian': ['xslt/*.xslt', 'epub/*', 'mobi/*', 'pdf/*', 'fonts/*', 'res/*'] +
whole_tree(os.path.join(os.path.dirname(__file__), 'librarian'), 'font-optimizer')},
include_package_data=True,
install_requires=['lxml>=2.2'],
scripts=['scripts/book2html',
'scripts/book2txt',
'scripts/book2epub',
+ 'scripts/book2mobi',
'scripts/book2pdf',
'scripts/book2partner',
'scripts/bookfragments',