diff options
author | Dirk Baechle <dl9obn@darc.de> | 2013-12-21 01:24:25 +0100 |
---|---|---|
committer | Dirk Baechle <dl9obn@darc.de> | 2013-12-21 01:24:25 +0100 |
commit | 89122015d5a9a3c87fcba3e4ffc7538419f5aee4 (patch) | |
tree | 0a43edac19dbeb2682f2ae84813e1c3fafcdf877 /src/engine | |
parent | aebd22f11151aa6fbd78b97415a4f7eaad7d9f80 (diff) | |
download | scons-89122015d5a9a3c87fcba3e4ffc7538419f5aee4.tar.gz |
- added EPUB Builder to the DocBook Tool, based on the work of Andrew Featherstone
Diffstat (limited to 'src/engine')
-rw-r--r-- | src/engine/SCons/Tool/docbook/__init__.py | 135 | ||||
-rw-r--r-- | src/engine/SCons/Tool/docbook/__init__.xml | 34 |
2 files changed, 159 insertions, 10 deletions
diff --git a/src/engine/SCons/Tool/docbook/__init__.py b/src/engine/SCons/Tool/docbook/__init__.py index 1e88cfe8..a3369921 100644 --- a/src/engine/SCons/Tool/docbook/__init__.py +++ b/src/engine/SCons/Tool/docbook/__init__.py @@ -318,9 +318,14 @@ def __build_lxml(target, source, env): """ from lxml import etree + xslt_ac = etree.XSLTAccessControl(read_file=True, + write_file=True, + create_dir=True, + read_network=False, + write_network=False) xsl_style = env.subst('$DOCBOOK_XSL') xsl_tree = etree.parse(xsl_style) - transform = etree.XSLT(xsl_tree) + transform = etree.XSLT(xsl_tree, access_control=xslt_ac) doc = etree.parse(str(source[0])) # Support for additional parameters parampass = {} @@ -404,6 +409,116 @@ __fop_builder = SCons.Builder.Builder( src_suffix = '.fo', ensure_suffix=1) +def DocbookEpub(env, target, source=None, *args, **kw): + """ + A pseudo-Builder, providing a Docbook toolchain for ePub output. + """ + import zipfile + import shutil + from lxml import etree + + def build_open_container(target, source, env): + """Generate the *.epub file from intermediate outputs + + Constructs the epub file according to the Open Container Format. This + function could be replaced by a call to the SCons Zip builder if support + was added for different compression formats for separate source nodes. + """ + zf = zipfile.ZipFile(str(target[0]), 'w') + mime_file = open('mimetype', 'w') + mime_file.write('application/epub+zip') + mime_file.close() + zf.write(mime_file.name, compress_type = zipfile.ZIP_STORED) + for s in source: + for dirpath, dirnames, filenames in os.walk(str(s)): + for fname in filenames: + path = os.path.join(dirpath, fname) + if os.path.isfile(path): + zf.write(path, os.path.relpath(path, str(env.get('ZIPROOT', ''))), + zipfile.ZIP_DEFLATED) + zf.close() + + def add_resources(target, source, env): + """Add missing resources to the OEBPS directory + + Ensure all the resources in the manifest are present in the OEBPS directory. + """ + hrefs = [] + content_file = os.path.join(source[0].abspath, 'content.opf') + if not os.path.isfile(content_file): + return + + hrefs = [] + if has_libxml2: + nsmap = {'opf' : 'http://www.idpf.org/2007/opf'} + # Read file and resolve entities + doc = libxml2.readFile(content_file, None, 0) + opf = doc.getRootElement() + # Create xpath context + xpath_context = doc.xpathNewContext() + # Register namespaces + for key, val in nsmap.iteritems(): + xpath_context.xpathRegisterNs(key, val) + + if hasattr(opf, 'xpathEval') and xpath_context: + # Use the xpath context + xpath_context.setContextNode(opf) + items = xpath_context.xpathEval(".//opf:item") + else: + items = opf.findall(".//{'http://www.idpf.org/2007/opf'}item") + + for item in items: + if hasattr(item, 'prop'): + hrefs.append(item.prop('href')) + else: + hrefs.append(item.attrib['href']) + + doc.freeDoc() + xpath_context.xpathFreeContext() + elif has_lxml: + from lxml import etree + + opf = etree.parse(content_file) + # All the opf:item elements are resources + for item in opf.xpath('//opf:item', + namespaces= { 'opf': 'http://www.idpf.org/2007/opf' }): + hrefs.append(item.attrib['href']) + + for href in hrefs: + # If the resource was not already created by DocBook XSL itself, + # copy it into the OEBPS folder + referenced_file = os.path.join(source[0].abspath, href) + if not os.path.exists(referenced_file): + shutil.copy(href, os.path.join(source[0].abspath, href)) + + # Init list of targets/sources + target, source = __extend_targets_sources(target, source) + + # Init XSL stylesheet + __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_EPUB', ['epub','docbook.xsl']) + + # Setup builder + __builder = __select_builder(__lxml_builder, __libxml2_builder, __xsltproc_builder) + + # Create targets + result = [] + tlist = ['OEBPS/toc.ncx', 'META-INF/container.xml'] + dirs = [SCons.Script.Dir('OEBPS'), SCons.Script.Dir('META-INF')] + r = __builder.__call__(env, tlist, source[0], **kw) + + env.Depends(r, kw['DOCBOOK_XSL']) + result.extend(r) + + container = env.Command(__ensure_suffix(str(target[0]), '.epub'), + tlist, [add_resources, build_open_container]) + + env.Depends(container, r) + result.extend(container) + # Add supporting files for cleanup + env.Clean(r, dirs + [SCons.Script.File('mimetype')]) + + return result + def DocbookHtml(env, target, source=None, *args, **kw): """ A pseudo-Builder, providing a Docbook toolchain for HTML output. @@ -686,19 +801,19 @@ def DocbookXslt(env, target, source=None, *args, **kw): return result - def generate(env): """Add Builders and construction variables for docbook to an Environment.""" env.SetDefault( # Default names for customized XSL stylesheets - DOCBOOK_DEFAULT_XSL_HTML = '', - DOCBOOK_DEFAULT_XSL_HTMLCHUNKED = '', - DOCBOOK_DEFAULT_XSL_HTMLHELP = '', - DOCBOOK_DEFAULT_XSL_PDF = '', - DOCBOOK_DEFAULT_XSL_MAN = '', - DOCBOOK_DEFAULT_XSL_SLIDESPDF = '', - DOCBOOK_DEFAULT_XSL_SLIDESHTML = '', + DOCBOOK_DEFAULT_XSL_EPUB = '', + DOCBOOK_DEFAULT_XSL_HTML = '', + DOCBOOK_DEFAULT_XSL_HTMLCHUNKED = '', + DOCBOOK_DEFAULT_XSL_HTMLHELP = '', + DOCBOOK_DEFAULT_XSL_PDF = '', + DOCBOOK_DEFAULT_XSL_MAN = '', + DOCBOOK_DEFAULT_XSL_SLIDESPDF = '', + DOCBOOK_DEFAULT_XSL_SLIDESHTML = '', # Paths to the detected executables DOCBOOK_XSLTPROC = '', @@ -725,6 +840,7 @@ def generate(env): _detect(env) try: + env.AddMethod(DocbookEpub, "DocbookEpub") env.AddMethod(DocbookHtml, "DocbookHtml") env.AddMethod(DocbookHtmlChunked, "DocbookHtmlChunked") env.AddMethod(DocbookHtmlhelp, "DocbookHtmlhelp") @@ -737,6 +853,7 @@ def generate(env): except AttributeError: # Looks like we use a pre-0.98 version of SCons... from SCons.Script.SConscript import SConsEnvironment + SConsEnvironment.DocbookEpub = DocbookEpub SConsEnvironment.DocbookHtml = DocbookHtml SConsEnvironment.DocbookHtmlChunked = DocbookHtmlChunked SConsEnvironment.DocbookHtmlhelp = DocbookHtmlhelp diff --git a/src/engine/SCons/Tool/docbook/__init__.xml b/src/engine/SCons/Tool/docbook/__init__.xml index be2f2cab..07487384 100644 --- a/src/engine/SCons/Tool/docbook/__init__.xml +++ b/src/engine/SCons/Tool/docbook/__init__.xml @@ -97,7 +97,7 @@ accordingly. </para> </important> <para>The rules given above are valid for the Builders &b-link-DocbookHtml;, -&b-link-DocbookPdf;, &b-link-DocbookSlidesPdf; and &b-link-DocbookXInclude;. For the +&b-link-DocbookPdf;, &b-link-DocbookEpub;, &b-link-DocbookSlidesPdf; and &b-link-DocbookXInclude;. For the &b-link-DocbookMan; transformation you can specify a target name, but the actual output names are automatically set from the <literal>refname</literal> entries in your XML source. @@ -136,6 +136,7 @@ variables for setting the default XSL name is provided. These are: DOCBOOK_DEFAULT_XSL_HTMLCHUNKED DOCBOOK_DEFAULT_XSL_HTMLHELP DOCBOOK_DEFAULT_XSL_PDF +DOCBOOK_DEFAULT_XSL_EPUB DOCBOOK_DEFAULT_XSL_MAN DOCBOOK_DEFAULT_XSL_SLIDESPDF DOCBOOK_DEFAULT_XSL_SLIDESHTML @@ -153,6 +154,7 @@ env.DocbookHtml('manual') # now uses html.xsl <item>DOCBOOK_DEFAULT_XSL_HTMLCHUNKED</item> <item>DOCBOOK_DEFAULT_XSL_HTMLHELP</item> <item>DOCBOOK_DEFAULT_XSL_PDF</item> +<item>DOCBOOK_DEFAULT_XSL_EPUB</item> <item>DOCBOOK_DEFAULT_XSL_MAN</item> <item>DOCBOOK_DEFAULT_XSL_SLIDESPDF</item> <item>DOCBOOK_DEFAULT_XSL_SLIDESHTML</item> @@ -212,6 +214,15 @@ current environment, if no other XSLT gets specified via keyword. </summary> </cvar> +<cvar name="DOCBOOK_DEFAULT_XSL_EPUB"> +<summary> +<para> +The default XSLT file for the &b-link-DocbookEpub; builder within the +current environment, if no other XSLT gets specified via keyword. +</para> +</summary> +</cvar> + <cvar name="DOCBOOK_DEFAULT_XSL_MAN"> <summary> <para> @@ -473,6 +484,27 @@ env.DocbookPdf('manual') </summary> </builder> +<builder name="DocbookEpub"> +<summary> +<para> +A pseudo-Builder, providing a Docbook toolchain for EPUB output. +</para> + +<example_commands>env = Environment(tools=['docbook']) +env.DocbookEpub('manual.epub', 'manual.xml') +</example_commands> + +<para> +or simply +</para> + +<example_commands>env = Environment(tools=['docbook']) +env.DocbookEpub('manual') +</example_commands> + +</summary> +</builder> + <builder name="DocbookMan"> <summary> <para> |