X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=lib%2Fscripts%2Fdocbook2epub.py;h=0e9d268a473288a361977aeadc47078349bc1d40;hb=940d3ceeb9e6d8ce216afedf18c898ec075cc27d;hp=e60a9d482c9a3d460dff64b2e2248344d2b4cd6e;hpb=6a99e885652ff68f89746ff65772718bd52b812d;p=lyx.git
diff --git a/lib/scripts/docbook2epub.py b/lib/scripts/docbook2epub.py
index e60a9d482c..0e9d268a47 100644
--- a/lib/scripts/docbook2epub.py
+++ b/lib/scripts/docbook2epub.py
@@ -9,62 +9,195 @@
# Full author contact details are available in file CREDITS
# Usage:
-# python docbook2epub.py in.docbook out.epub
+# python docbook2epub.py java_binary saxon_path xsltproc_path xslt_path in.docbook in.orig.path out.epub
from __future__ import print_function
+import glob
import os
import shutil
import sys
import tempfile
import zipfile
-import glob
+from io import open # Required for Python 2.
-if __name__ == '__main__':
- if len(sys.argv) != 4:
- sys.exit(1)
- own_path, java_path, input, output = sys.argv
- script_folder = os.path.dirname(own_path) + '/../'
-
- print('Generating ePub:')
- print(own_path)
- print(input)
- print(output)
-
- output_dir = tempfile.mkdtemp().replace('\\', '/')
- print('Temporary output directory:')
- print(output_dir)
-
- # Start the XSLT transformation.
- xslt = script_folder + 'docbook/epub3/chunk.xsl'
- saxon_jar = script_folder + 'scripts/saxon6.5.5.jar'
- saxon_params = 'base.dir=%s' % output_dir
- command = '"' + java_path + '" -jar "' + saxon_jar + '" ' + input + ' ' + xslt + ' ' + saxon_params
-
- print('XSLT style sheet to use:')
- print(xslt)
- print('Command to execute:')
- print(command)
-
- quoted_command = command
- if os.name == 'nt':
- # On Windows, it is typical to have spaces in folder names, and that requires to wrap the whole command
- # in quotes. On Linux, this might create errors when starting the command.
- quoted_command = '"' + command + '"'
-
- if os.system(quoted_command) != 0:
- print('docbook2epub fails')
- shutil.rmtree(output_dir, ignore_errors=True)
+
+def _parse_nullable_argument(arg):
+ return arg if arg != '' and arg != 'none' else None
+
+
+class ImageRename:
+ def __init__(self, opf_path, local_path, epub_path):
+ self.opf_path = opf_path
+ self.local_path = local_path
+ self.epub_path = epub_path
+
+
+class DocBookToEpub:
+ def __init__(self, args=None):
+ if args is None:
+ args = sys.argv
+
+ if len(args) != 8:
+ print('Exactly eight arguments are expected, only %s found: %s.' % (len(args), args))
+ sys.exit(1)
+
+ self.own_path = sys.argv[0]
+ self.java_path = _parse_nullable_argument(sys.argv[1])
+ self.saxon_path = _parse_nullable_argument(sys.argv[2])
+ self.xsltproc_path = _parse_nullable_argument(sys.argv[3])
+ self.xslt_path = _parse_nullable_argument(sys.argv[4])
+ self.input = sys.argv[5]
+ self.input_path = sys.argv[6]
+ self.output = sys.argv[7]
+ self.script_folder = os.path.dirname(self.own_path) + '/../'
+
+ print('Generating ePub with the following parameters:')
+ print(self.own_path)
+ print(self.java_path)
+ print(self.saxon_path)
+ print(self.xsltproc_path)
+ print(self.xslt_path)
+ print(self.input)
+ print(self.input_path)
+ print(self.output)
+
+ # Precompute paths that will be used later.
+ self.output_dir = tempfile.mkdtemp().replace('\\', '/')
+ self.package_opf = self.output_dir + '/OEBPS/package.opf' # Does not exist yet,
+ print('Temporary output directory: %s' % self.output_dir)
+
+ if self.xslt_path is None:
+ self.xslt = self.script_folder + 'docbook/epub3/chunk.xsl'
+ else:
+ self.xslt = self.xslt_path + '/epub3/chunk.xsl'
+ print('XSLT style sheet to use:')
+ print(self.xslt)
+
+ if self.saxon_path is None:
+ self.saxon_path = self.script_folder + 'scripts/saxon6.5.5.jar'
+
+ # These will be filled during the execution of the script.
+ self.renamed = None
+
+ def gracefully_fail(self, reason):
+ print('docbook2epub fails: %s' % reason)
+ shutil.rmtree(self.output_dir, ignore_errors=True)
sys.exit(1)
- print('Generated ePub contents.')
+ def start_xslt_transformation(self):
+ command = None
+ if self.xsltproc_path is not None:
+ command = self.start_xslt_transformation_xsltproc()
+ elif self.java_path is not None:
+ command = self.start_xslt_transformation_saxon6()
+
+ if command is None:
+ self.gracefully_fail('no XSLT processor available')
+
+ print('Command to execute:')
+ print(command)
+
+ quoted_command = command
+ if os.name == 'nt':
+ # On Windows, it is typical to have spaces in folder names, and that requires to wrap the whole command
+ # in quotes. On Linux, this might create errors when starting the command.
+ quoted_command = '"' + command + '"'
+ # This could be simplified by using subprocess.run, but this requires Python 3.5.
- # TODO: Copy the assets to the OEBPS/images/.
+ if os.system(quoted_command) != 0:
+ self.gracefully_fail('error from the XSLT processor')
- # Create the actual ePub file.
- with zipfile.ZipFile(output, 'w', zipfile.ZIP_DEFLATED) as zip:
- for file in glob.glob(output_dir + '/**/*', recursive=True):
- zip.write(file, os.path.relpath(file, output_dir), compress_type=zipfile.ZIP_STORED)
+ print('Generated ePub contents.')
- shutil.rmtree(output_dir)
- print('Generated ePub.')
+ def start_xslt_transformation_xsltproc(self):
+ params = '-stringparam base.dir "' + self.output_dir + '"'
+ return '"' + self.xsltproc_path + '" ' + params + ' "' + self.xslt + '" "' + self.input + '"'
+
+ def start_xslt_transformation_saxon6(self):
+ params = 'base.dir=%s' % self.output_dir
+ executable = '"' + self.java_path + '" -jar "' + self.saxon_path + '"'
+ return executable + ' "' + self.input + '" "' + self.xslt + '" "' + params + '"'
+
+ def get_images_from_package_opf(self):
+ images = []
+
+ # Example in the OPF file:
+ #
+ # The XHTML files are also - tags:
+ #
+ try:
+ with open(self.package_opf, 'r') as f:
+ for line in f.readlines():
+ if '- file in the ePub archive.
+ self.renamed = self.get_image_changes()
+
+ # Then, transform all paths (both OPF and XHTML files).
+ self.change_image_paths(self.output_dir + '/OEBPS/package.opf')
+ for file in glob.glob(self.output_dir + '/OEBPS/*.xhtml'):
+ self.change_image_paths(file)
+
+ # Ensure that the destination path exists. OEBPS exists due to the DocBook-to-ePub transformation.
+ if not os.path.exists(self.output_dir + '/OEBPS/images/'):
+ os.mkdir(self.output_dir + '/OEBPS/images/')
+
+ # Finally, actually copy the image files.
+ for change in self.renamed:
+ shutil.copyfile(change.local_path, self.output_dir + '/OEBPS/' + change.epub_path)
+
+ def create_zip_archive(self):
+ with zipfile.ZipFile(self.output, 'w', zipfile.ZIP_DEFLATED) as zip:
+ # Python 3.5 brings the `recursive` argument. For older versions, this trick is required...
+ # for file in glob.glob(output_dir + '/**/*', recursive=True):
+ for file in [os.path.join(dp, f) for dp, dn, filenames in os.walk(self.output_dir) for f in filenames]:
+ zip.write(file, os.path.relpath(file, self.output_dir), compress_type=zipfile.ZIP_STORED)
+
+ shutil.rmtree(self.output_dir)
+ print('Generated ePub.')
+
+ def transform(self):
+ self.start_xslt_transformation()
+ self.copy_images()
+ self.create_zip_archive()
+
+
+if __name__ == '__main__':
+ DocBookToEpub(sys.argv).transform()