3 # Copyright The SCons Foundation
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 """Tool-specific initialization for Docbook.
26 There normally shouldn't be any need to import this module directly.
27 It will usually be imported through the generic SCons.Tool.Tool()
42 __debug_tool_location
= False
43 # Get full path to this script
44 scriptpath
= os
.path
.dirname(os
.path
.realpath(__file__
))
46 # Local folder for the collection of DocBook XSLs
47 db_xsl_folder
= 'docbook-xsl-1.76.1'
56 # Set this to True, to prefer xsltproc over lxml
57 prefer_xsltproc
= False
59 # Regexs for parsing Docbook XML sources of MAN pages
60 re_manvolnum
= re
.compile(r
"<manvolnum>([^<]*)</manvolnum>")
61 re_refname
= re
.compile(r
"<refname>([^<]*)</refname>")
64 # lxml etree XSLT global max traversal depth
67 lmxl_xslt_global_max_depth
= 3600
69 if has_lxml
and lmxl_xslt_global_max_depth
:
70 def __lxml_xslt_set_global_max_depth(max_depth
) -> None:
71 from lxml
import etree
72 etree
.XSLT
.set_global_max_depth(max_depth
)
73 __lxml_xslt_set_global_max_depth(lmxl_xslt_global_max_depth
)
78 def __extend_targets_sources(target
, source
):
79 """ Prepare the lists of target and source files. """
80 if not SCons
.Util
.is_List(target
):
84 elif not SCons
.Util
.is_List(source
):
86 if len(target
) < len(source
):
87 target
.extend(source
[len(target
):])
91 def __init_xsl_stylesheet(kw
, env
, user_xsl_var
, default_path
) -> None:
92 if kw
.get('DOCBOOK_XSL','') == '':
93 xsl_style
= kw
.get('xsl', env
.subst(user_xsl_var
))
95 path_args
= [scriptpath
, db_xsl_folder
] + default_path
96 xsl_style
= os
.path
.join(*path_args
)
97 kw
['DOCBOOK_XSL'] = xsl_style
99 def __select_builder(lxml_builder
, cmdline_builder
):
100 """ Selects a builder, based on which Python modules are present. """
101 if has_lxml
and not prefer_xsltproc
:
104 return cmdline_builder
106 def __ensure_suffix(t
, suffix
):
107 """ Ensure that the target t has the given suffix. """
109 if not tpath
.endswith(suffix
):
114 def __ensure_suffix_stem(t
, suffix
):
115 """ Ensure that the target t has the given suffix, and return the file's stem. """
117 if not tpath
.endswith(suffix
):
123 stem
, ext
= os
.path
.splitext(tpath
)
127 def __get_xml_text(root
):
128 """ Return the text for the given root node (xml.dom.minidom). """
130 for e
in root
.childNodes
:
131 if e
.nodeType
== e
.TEXT_NODE
:
135 def __create_output_dir(base_dir
) -> None:
136 """ Ensure that the output directory base_dir exists. """
137 root
, tail
= os
.path
.split(base_dir
)
140 if base_dir
.endswith('/'):
145 if base_dir
.endswith('/'):
148 if dir and not os
.path
.isdir(dir):
153 # Supported command line tools and their call "signature"
155 xsltproc_com_priority
= ['xsltproc', 'saxon', 'saxon-xslt', 'xalan']
157 # TODO: Set minimum version of saxon-xslt to be 8.x (lower than this only supports xslt 1.0.
158 # see: https://saxon.sourceforge.net/saxon6.5.5/
159 # see: https://saxon.sourceforge.net/
160 xsltproc_com
= {'xsltproc' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -o $TARGET $DOCBOOK_XSL $SOURCE',
161 'saxon' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -o $TARGET $DOCBOOK_XSL $SOURCE $DOCBOOK_XSLTPROCPARAMS',
162 # Note if saxon-xslt is version 5.5 the proper arguments are: (swap order of docbook_xsl and source)
163 # 'saxon-xslt' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -o $TARGET $SOURCE $DOCBOOK_XSL $DOCBOOK_XSLTPROCPARAMS',
164 'saxon-xslt' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -o $TARGET $DOCBOOK_XSL $SOURCE $DOCBOOK_XSLTPROCPARAMS',
165 'xalan' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -q -out $TARGET -xsl $DOCBOOK_XSL -in $SOURCE'}
166 xmllint_com
= {'xmllint' : '$DOCBOOK_XMLLINT $DOCBOOK_XMLLINTFLAGS --xinclude $SOURCE > $TARGET'}
167 fop_com
= {'fop' : '$DOCBOOK_FOP $DOCBOOK_FOPFLAGS -fo $SOURCE -pdf $TARGET',
168 'xep' : '$DOCBOOK_FOP $DOCBOOK_FOPFLAGS -valid -fo $SOURCE -pdf $TARGET',
169 'jw' : '$DOCBOOK_FOP $DOCBOOK_FOPFLAGS -f docbook -b pdf $SOURCE -o $TARGET'}
171 def __detect_cl_tool(env
, chainkey
, cdict
, cpriority
=None) -> None:
173 Helper function, picks a command line tool from the list
174 and initializes its environment variables.
176 if env
.get(chainkey
,'') == '':
179 if cpriority
is None:
180 cpriority
= cdict
.keys()
181 for cltool
in cpriority
:
182 if __debug_tool_location
:
183 print("DocBook: Looking for %s"%cltool
)
184 clpath
= env
.WhereIs(cltool
)
186 if __debug_tool_location
:
187 print("DocBook: Found:%s"%cltool
)
188 env
[chainkey
] = clpath
189 if not env
[chainkey
+ 'COM']:
190 env
[chainkey
+ 'COM'] = cdict
[cltool
]
193 def _detect(env
) -> None:
195 Detect all the command line tools that we might need for creating
196 the requested output formats.
198 global prefer_xsltproc
200 if env
.get('DOCBOOK_PREFER_XSLTPROC',''):
201 prefer_xsltproc
= True
203 if (not has_lxml
) or prefer_xsltproc
:
204 # Try to find the XSLT processors
205 __detect_cl_tool(env
, 'DOCBOOK_XSLTPROC', xsltproc_com
, xsltproc_com_priority
)
206 __detect_cl_tool(env
, 'DOCBOOK_XMLLINT', xmllint_com
)
208 __detect_cl_tool(env
, 'DOCBOOK_FOP', fop_com
, ['fop','xep','jw'])
213 include_re
= re
.compile(r
'fileref\\s*=\\s*["|\']([^
\\n
]*)["|\']')
214 sentity_re = re.compile(r'<!ENTITY\\s+%*\\s*[^\\s]+\\s+SYSTEM\\s+["|
\']([^
\\n
]*)["|\']>')
216 def __xml_scan(node, env, path, arg):
217 """ Simple XML file scanner, detecting local images and XIncludes as implicit dependencies. """
218 # Does the node exist yet?
219 if not os.path.isfile(str(node)):
222 if env.get('DOCBOOK_SCANENT',''):
223 # Use simple pattern matching for system entities..., no support
225 contents = node.get_text_contents()
226 return sentity_re.findall(contents)
228 xsl_file = os.path.join(scriptpath,'utils','xmldepend.xsl')
229 if not has_lxml or prefer_xsltproc:
230 # Try to call xsltproc
231 xsltproc = env.subst("$DOCBOOK_XSLTPROC
")
232 if xsltproc and xsltproc.endswith('xsltproc'):
233 result = env.backtick(' '.join([xsltproc, xsl_file, str(node)]))
234 depfiles = [x.strip() for x in str(result).splitlines() if x.strip() != "" and not x.startswith("<?xml
")]
237 # Use simple pattern matching, there is currently no support
239 contents = node.get_text_contents()
240 return include_re.findall(contents)
242 from lxml import etree
244 xsl_tree = etree.parse(xsl_file)
245 doc = etree.parse(str(node))
246 result = doc.xslt(xsl_tree)
248 depfiles = [x.strip() for x in str(result).splitlines() if x.strip() != "" and not x.startswith("<?xml
")]
251 # Creating the instance of our XML dependency scanner
252 docbook_xml_scanner = SCons.Script.Scanner(function = __xml_scan,
259 def __generate_xsltproc_action(source, target, env, for_signature):
260 cmd = env['DOCBOOK_XSLTPROCCOM']
261 # Does the environment have a base_dir defined?
262 base_dir = env.subst('$base_dir')
264 # Yes, so replace target path by its filename
265 return cmd.replace('$TARGET', os.path.join(base_dir, '${TARGET.file}'))
268 def __generate_xsltproc_nobase_action(source, target, env, for_signature):
269 cmd = env['DOCBOOK_XSLTPROCCOM']
270 # Does the environment have a base_dir defined?
271 base_dir = env.subst('$base_dir')
273 # Yes, so replace target path by its filename
274 return cmd.replace('$TARGET', '${TARGET.file}')
281 def __emit_xsl_basedir(target, source, env):
282 # Does the environment have a base_dir defined?
283 base_dir = env.subst('$base_dir')
285 # Yes, so prepend it to each target
286 return [os.path.join(base_dir, str(t)) for t in target], source
288 # No, so simply pass target and source names through
289 return target, source
295 def __build_lxml(target, source, env):
297 General XSLT builder (HTML/FO), using the lxml module.
299 from lxml import etree
301 xslt_ac = etree.XSLTAccessControl(read_file=True,
306 xsl_style = env.subst('$DOCBOOK_XSL')
307 xsl_tree = etree.parse(xsl_style)
308 transform = etree.XSLT(xsl_tree, access_control=xslt_ac)
309 doc = etree.parse(str(source[0]))
310 # Support for additional parameters
313 result = transform(doc, **parampass)
315 result = transform(doc)
318 with open(str(target[0]), "wb
") as of:
319 of.write(etree.tostring(result, encoding="utf
-8", pretty_print=True))
320 except Exception as e:
321 print(f"ERROR
: Failed to write
{str(target
[0])}")
326 def __build_lxml_noresult(target, source, env):
328 Specialized XSLT builder for transformations without a direct result where the Docbook
329 stylesheet itself creates the target file, using the lxml module.
331 from lxml import etree
333 xslt_ac = etree.XSLTAccessControl(read_file=True,
338 xsl_style = env.subst('$DOCBOOK_XSL')
339 xsl_tree = etree.parse(xsl_style)
340 transform = etree.XSLT(xsl_tree, access_control=xslt_ac)
341 doc = etree.parse(str(source[0]))
342 # Support for additional parameters
345 result = transform(doc, **parampass)
347 result = transform(doc)
352 def __xinclude_lxml(target, source, env):
354 Resolving XIncludes, using the lxml module.
356 from lxml import etree
358 doc = etree.parse(str(source[0]))
361 doc.write(str(target[0]), xml_declaration=True,
362 encoding="UTF
-8", pretty_print=True)
363 except Exception as e:
364 print(f"ERROR
: Failed to write
{str(target
[0])}")
369 __lxml_builder = SCons.Builder.Builder(
370 action = __build_lxml,
372 source_scanner = docbook_xml_scanner,
373 emitter = __emit_xsl_basedir)
375 __lxml_noresult_builder = SCons.Builder.Builder(
376 action = __build_lxml_noresult,
378 source_scanner = docbook_xml_scanner,
379 emitter = __emit_xsl_basedir)
381 __xinclude_lxml_builder = SCons.Builder.Builder(
382 action = __xinclude_lxml,
385 source_scanner = docbook_xml_scanner)
387 __xsltproc_builder = SCons.Builder.Builder(
388 action = SCons.Action.CommandGeneratorAction(__generate_xsltproc_action,
389 {'cmdstr' : '$DOCBOOK_XSLTPROCCOMSTR'}),
391 source_scanner = docbook_xml_scanner,
392 emitter = __emit_xsl_basedir)
393 __xsltproc_nobase_builder = SCons.Builder.Builder(
394 action = SCons.Action.CommandGeneratorAction(__generate_xsltproc_nobase_action,
395 {'cmdstr' : '$DOCBOOK_XSLTPROCCOMSTR'}),
397 source_scanner = docbook_xml_scanner,
398 emitter = __emit_xsl_basedir)
399 __xmllint_builder = SCons.Builder.Builder(
400 action = SCons.Action.Action('$DOCBOOK_XMLLINTCOM','$DOCBOOK_XMLLINTCOMSTR'),
403 source_scanner = docbook_xml_scanner)
404 __fop_builder = SCons.Builder.Builder(
405 action = SCons.Action.Action('$DOCBOOK_FOPCOM','$DOCBOOK_FOPCOMSTR'),
410 def DocbookEpub(env, target, source=None, *args, **kw):
412 A pseudo-Builder, providing a Docbook toolchain for ePub output.
417 def build_open_container(target, source, env) -> None:
418 """Generate the *.epub file from intermediate outputs
420 Constructs the epub file according to the Open Container Format. This
421 function could be replaced by a call to the SCons Zip builder if support
422 was added for different compression formats for separate source nodes.
424 with zipfile.ZipFile(str(target[0]), 'w') as zf:
425 with open('mimetype', 'w') as mime_file:
426 mime_file.write('application/epub+zip')
427 zf.write(mime_file.name, compress_type = zipfile.ZIP_STORED)
429 if os.path.isfile(str(s)):
430 head, tail = os.path.split(str(s))
434 for dirpath, dirnames, filenames in os.walk(str(s)):
435 for fname in filenames:
436 path = os.path.join(dirpath, fname)
437 if os.path.isfile(path):
438 zf.write(path, os.path.relpath(path, str(env.get('ZIPROOT', ''))),
439 zipfile.ZIP_DEFLATED)
441 def add_resources(target, source, env) -> None:
442 """Add missing resources to the OEBPS directory
444 Ensure all the resources in the manifest are present in the OEBPS directory.
447 content_file = os.path.join(source[0].get_abspath(), 'content.opf')
448 if not os.path.isfile(content_file):
453 from lxml import etree
455 opf = etree.parse(content_file)
456 # All the opf:item elements are resources
457 for item in opf.xpath('//opf:item',
458 namespaces= { 'opf': 'http://www.idpf.org/2007/opf' }):
459 hrefs.append(item.attrib['href'])
462 # If the resource was not already created by DocBook XSL itself,
463 # copy it into the OEBPS folder
464 referenced_file = os.path.join(source[0].get_abspath(), href)
465 if not os.path.exists(referenced_file):
466 shutil.copy(href, os.path.join(source[0].get_abspath(), href))
468 # Init list of targets/sources
469 target, source = __extend_targets_sources(target, source)
471 # Init XSL stylesheet
472 __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_EPUB', ['epub','docbook.xsl'])
475 __builder = __select_builder(__lxml_noresult_builder, __xsltproc_nobase_builder)
479 if not env.GetOption('clean'):
480 # Ensure that the folders OEBPS and META-INF exist
481 __create_output_dir('OEBPS/')
482 __create_output_dir('META-INF/')
483 dirs = env.Dir(['OEBPS', 'META-INF'])
485 # Set the fixed base_dir
486 kw['base_dir'] = 'OEBPS/'
487 tocncx = __builder(env, 'toc.ncx', source[0], **kw)
488 cxml = env.File('META-INF/container.xml')
489 env.SideEffect(cxml, tocncx)
491 env.Depends(tocncx, kw['DOCBOOK_XSL'])
492 result.extend(tocncx+[cxml])
494 container = env.Command(__ensure_suffix(str(target[0]), '.epub'),
495 tocncx+[cxml], [add_resources, build_open_container])
496 mimetype = env.File('mimetype')
497 env.SideEffect(mimetype, container)
499 result.extend(container)
500 # Add supporting files for cleanup
501 env.Clean(tocncx, dirs)
505 def DocbookHtml(env, target, source=None, *args, **kw):
507 A pseudo-Builder, providing a Docbook toolchain for HTML output.
509 # Init list of targets/sources
510 target, source = __extend_targets_sources(target, source)
512 # Init XSL stylesheet
513 __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_HTML', ['html','docbook.xsl'])
516 __builder = __select_builder(__lxml_builder, __xsltproc_builder)
520 for t,s in zip(target,source):
521 r = __builder(env, __ensure_suffix(t,'.html'), s, **kw)
522 env.Depends(r, kw['DOCBOOK_XSL'])
527 def DocbookHtmlChunked(env, target, source=None, *args, **kw):
529 A pseudo-Builder, providing a Docbook toolchain for chunked HTML output.
532 if not SCons.Util.is_List(target):
536 target = ['index.html']
537 elif not SCons.Util.is_List(source):
540 # Init XSL stylesheet
541 __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_HTMLCHUNKED', ['html','chunkfast.xsl'])
544 __builder = __select_builder(__lxml_noresult_builder, __xsltproc_nobase_builder)
547 base_dir = kw.get('base_dir', '')
549 __create_output_dir(base_dir)
553 r = __builder(env, __ensure_suffix(str(target[0]), '.html'), source[0], **kw)
554 env.Depends(r, kw['DOCBOOK_XSL'])
556 # Add supporting files for cleanup
557 env.Clean(r, glob.glob(os.path.join(base_dir, '*.html')))
562 def DocbookHtmlhelp(env, target, source=None, *args, **kw):
564 A pseudo-Builder, providing a Docbook toolchain for HTMLHELP output.
567 if not SCons.Util.is_List(target):
571 target = ['index.html']
572 elif not SCons.Util.is_List(source):
575 # Init XSL stylesheet
576 __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_HTMLHELP', ['htmlhelp','htmlhelp.xsl'])
579 __builder = __select_builder(__lxml_noresult_builder, __xsltproc_nobase_builder)
582 base_dir = kw.get('base_dir', '')
584 __create_output_dir(base_dir)
588 r = __builder(env, __ensure_suffix(str(target[0]), '.html'), source[0], **kw)
589 env.Depends(r, kw['DOCBOOK_XSL'])
591 # Add supporting files for cleanup
592 env.Clean(r, ['toc.hhc', 'htmlhelp.hhp', 'index.hhk'] +
593 glob.glob(os.path.join(base_dir, '[ar|bk|ch]*.html')))
597 def DocbookPdf(env, target, source=None, *args, **kw):
599 A pseudo-Builder, providing a Docbook toolchain for PDF output.
601 # Init list of targets/sources
602 target, source = __extend_targets_sources(target, source)
604 # Init XSL stylesheet
605 __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_PDF', ['fo','docbook.xsl'])
608 __builder = __select_builder(__lxml_builder, __xsltproc_builder)
612 for t,s in zip(target,source):
613 t, stem = __ensure_suffix_stem(t, '.pdf')
614 xsl = __builder(env, stem+'.fo', s, **kw)
616 env.Depends(xsl, kw['DOCBOOK_XSL'])
617 result.extend(__fop_builder(env, t, xsl, **kw))
621 def DocbookMan(env, target, source=None, *args, **kw):
623 A pseudo-Builder, providing a Docbook toolchain for Man page output.
625 # Init list of targets/sources
626 target, source = __extend_targets_sources(target, source)
628 # Init XSL stylesheet
629 __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_MAN', ['manpages','docbook.xsl'])
632 __builder = __select_builder(__lxml_noresult_builder, __xsltproc_builder)
636 for t,s in zip(target,source):
639 srcfile = __ensure_suffix(str(s),'.xml')
640 if os.path.isfile(srcfile):
642 import xml.dom.minidom
644 dom = xml.dom.minidom.parse(__ensure_suffix(str(s),'.xml'))
645 # Extract volume number, default is 1
646 for node in dom.getElementsByTagName('refmeta'):
647 for vol in node.getElementsByTagName('manvolnum'):
648 volnum = __get_xml_text(vol)
650 # Extract output filenames
651 for node in dom.getElementsByTagName('refnamediv'):
652 for ref in node.getElementsByTagName('refname'):
653 outfiles.append(__get_xml_text(ref)+'.'+volnum)
656 # Use simple regex parsing
657 with open(__ensure_suffix(str(s), '.xml')) as f:
660 for m in re_manvolnum.finditer(content):
663 for m in re_refname.finditer(content):
664 outfiles.append(m.group(1)+'.'+volnum)
667 # Use stem of the source file
669 if not spath.endswith('.xml'):
670 outfiles.append(spath+'.'+volnum)
672 stem, ext = os.path.splitext(spath)
673 outfiles.append(stem+'.'+volnum)
675 # We have to completely rely on the given target name
678 __builder(env, outfiles[0], s, **kw)
679 env.Depends(outfiles[0], kw['DOCBOOK_XSL'])
680 result.append(outfiles[0])
681 if len(outfiles) > 1:
682 env.Clean(outfiles[0], outfiles[1:])
687 def DocbookSlidesPdf(env, target, source=None, *args, **kw):
689 A pseudo-Builder, providing a Docbook toolchain for PDF slides output.
691 # Init list of targets/sources
692 target, source = __extend_targets_sources(target, source)
694 # Init XSL stylesheet
695 __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_SLIDESPDF', ['slides','fo','plain.xsl'])
698 __builder = __select_builder(__lxml_builder, __xsltproc_builder)
702 for t,s in zip(target,source):
703 t, stem = __ensure_suffix_stem(t, '.pdf')
704 xsl = __builder(env, stem+'.fo', s, **kw)
705 env.Depends(xsl, kw['DOCBOOK_XSL'])
707 result.extend(__fop_builder(env, t, xsl, **kw))
711 def DocbookSlidesHtml(env, target, source=None, *args, **kw):
713 A pseudo-Builder, providing a Docbook toolchain for HTML slides output.
715 # Init list of targets/sources
716 if not SCons.Util.is_List(target):
720 target = ['index.html']
721 elif not SCons.Util.is_List(source):
724 # Init XSL stylesheet
725 __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_SLIDESHTML', ['slides','xhtml','plain.xsl'])
728 __builder = __select_builder(__lxml_builder, __xsltproc_builder)
731 base_dir = kw.get('base_dir', '')
733 __create_output_dir(base_dir)
737 r = __builder(env, __ensure_suffix(str(target[0]), '.html'), source[0], **kw)
738 env.Depends(r, kw['DOCBOOK_XSL'])
740 # Add supporting files for cleanup
741 env.Clean(r, [os.path.join(base_dir, 'toc.html')] +
742 glob.glob(os.path.join(base_dir, 'foil*.html')))
746 def DocbookXInclude(env, target, source, *args, **kw):
748 A pseudo-Builder, for resolving XIncludes in a separate processing step.
750 # Init list of targets/sources
751 target, source = __extend_targets_sources(target, source)
754 __builder = __select_builder(__xinclude_lxml_builder,__xmllint_builder)
758 for t,s in zip(target,source):
759 result.extend(__builder(env, t, s, **kw))
763 def DocbookXslt(env, target, source=None, *args, **kw):
765 A pseudo-Builder, applying a simple XSL transformation to the input file.
767 # Init list of targets/sources
768 target, source = __extend_targets_sources(target, source)
770 # Init XSL stylesheet
771 kw['DOCBOOK_XSL'] = env.File(kw.get('xsl', 'transform.xsl'))
774 __builder = __select_builder(__lxml_builder, __xsltproc_builder)
778 for t,s in zip(target,source):
779 r = __builder(env, t, s, **kw)
780 env.Depends(r, kw['DOCBOOK_XSL'])
786 def generate(env) -> None:
787 """Add Builders and construction variables for docbook to an Environment."""
790 # Default names for customized XSL stylesheets
791 DOCBOOK_DEFAULT_XSL_EPUB = '',
792 DOCBOOK_DEFAULT_XSL_HTML = '',
793 DOCBOOK_DEFAULT_XSL_HTMLCHUNKED = '',
794 DOCBOOK_DEFAULT_XSL_HTMLHELP = '',
795 DOCBOOK_DEFAULT_XSL_PDF = '',
796 DOCBOOK_DEFAULT_XSL_MAN = '',
797 DOCBOOK_DEFAULT_XSL_SLIDESPDF = '',
798 DOCBOOK_DEFAULT_XSL_SLIDESHTML = '',
800 # Paths to the detected executables
801 DOCBOOK_XSLTPROC = '',
802 DOCBOOK_XMLLINT = '',
805 # Additional flags for the text processors
806 DOCBOOK_XSLTPROCFLAGS = SCons.Util.CLVar(''),
807 DOCBOOK_XMLLINTFLAGS = SCons.Util.CLVar(''),
808 DOCBOOK_FOPFLAGS = SCons.Util.CLVar(''),
809 DOCBOOK_XSLTPROCPARAMS = SCons.Util.CLVar(''),
811 # Default command lines for the detected executables
812 DOCBOOK_XSLTPROCCOM = xsltproc_com['xsltproc'],
813 DOCBOOK_XMLLINTCOM = xmllint_com['xmllint'],
814 DOCBOOK_FOPCOM = fop_com['fop'],
816 # Screen output for the text processors
817 DOCBOOK_XSLTPROCCOMSTR = None,
818 DOCBOOK_XMLLINTCOMSTR = None,
819 DOCBOOK_FOPCOMSTR = None,
824 env.AddMethod(DocbookEpub, "DocbookEpub
")
825 env.AddMethod(DocbookHtml, "DocbookHtml
")
826 env.AddMethod(DocbookHtmlChunked, "DocbookHtmlChunked
")
827 env.AddMethod(DocbookHtmlhelp, "DocbookHtmlhelp
")
828 env.AddMethod(DocbookPdf, "DocbookPdf
")
829 env.AddMethod(DocbookMan, "DocbookMan
")
830 env.AddMethod(DocbookSlidesPdf, "DocbookSlidesPdf
")
831 env.AddMethod(DocbookSlidesHtml, "DocbookSlidesHtml
")
832 env.AddMethod(DocbookXInclude, "DocbookXInclude
")
833 env.AddMethod(DocbookXslt, "DocbookXslt
")
836 def exists(env) -> bool: