diff options
author | Stuart Rackham <srackham@methods.co.nz> | 2012-03-01 12:55:30 +1300 |
---|---|---|
committer | Stuart Rackham <srackham@methods.co.nz> | 2012-03-01 12:55:30 +1300 |
commit | 61975c3b86dd74329ad645ab6417a157570941e9 (patch) | |
tree | f3b59c99c1120fbf43a0ebd18b005a7840d8074a | |
parent | 61f951e338a6425298aa3ae4c5a46eb2a77ffa89 (diff) | |
download | asciidoc-61975c3b86dd74329ad645ab6417a157570941e9.tar.gz |
- FIXED: All Python filters are executed with the same Python
interpreter that executes the asciidoc parent (previously filters
were hardwired to execute the 'python' interpreter). This prevents
Python mixups (see http://groups.google.com/group/asciidoc/browse_thread/thread/14e8fcb289a135b/3af3b4e57b827c78?lnk=gst&q=archlinux#3af3b4e57b827c78
- FIXED: Leaky file handles in a2x and music and latex filters which
created incompatibility problems for Jython. See
http://stackoverflow.com/questions/1832528/is-close-necessary-when-using-iterator-on-a-python-file-object
- FIXED: Jython AsciiDoc API (asciidocapi.py) StringIO incompatibility.
There is still an outstanding Jython related asciidocapi bug that
occurs when using a cStringIO output file: Jython throws an error when
non-ascii characters are found in included CSS or JavaScript files
(e.g. slidy.css), this only happens if you are executing asciidoc via
the asciidocapi and you are using a StringIO output file (as opposed
to a real file).
-rwxr-xr-x | a2x.py | 61 | ||||
-rw-r--r-- | asciidoc.conf | 4 | ||||
-rwxr-xr-x | asciidoc.py | 39 | ||||
-rw-r--r-- | doc/asciidoc.txt | 1 | ||||
-rwxr-xr-x | filters/latex/latex2png.py | 22 | ||||
-rwxr-xr-x | filters/music/music2png.py | 28 | ||||
-rw-r--r-- | html5.conf | 10 | ||||
-rwxr-xr-x | tests/testasciidoc.py | 9 | ||||
-rw-r--r-- | xhtml11-quirks.conf | 2 | ||||
-rw-r--r-- | xhtml11.conf | 10 |
10 files changed, 129 insertions, 57 deletions
@@ -144,6 +144,20 @@ def find_executable(file_name): result = _find_executable(file_name) return result +def write_file(filename, data, mode='w'): + f = open(filename, mode) + try: + f.write(data) + finally: + f.close() + +def read_file(filename, mode='r'): + f = open(filename, mode) + try: + return f.read() + finally: + f.close() + def shell_cd(path): verbose('chdir %s' % path) if not OPTIONS.dry_run: @@ -236,19 +250,20 @@ def find_resources(files, tagname, attrname, filter=None): if isinstance(files, str): files = [files] result = [] - for f in files: - verbose('finding resources in: %s' % f) + for filename in files: + verbose('finding resources in: %s' % filename) if OPTIONS.dry_run: continue parser = FindResources() # HTMLParser has problems with non-ASCII strings. # See http://bugs.python.org/issue3932 - mo = re.search(r'^<\?xml.* encoding="(.*?)"', open(f).readline()) + contents = read_file(filename) + mo = re.search(r'\A<\?xml.* encoding="(.*?)"', contents) if mo: encoding = mo.group(1) - parser.feed(open(f).read().decode(encoding)) + parser.feed(contents.decode(encoding)) else: - parser.feed(open(f).read()) + parser.feed(contents) parser.close() result = list(set(result)) # Drop duplicate values. result.sort() @@ -259,12 +274,12 @@ def copy_files(files, src_dir, dst_dir): ''' Copy list of relative file names from src_dir to dst_dir. ''' - for f in files: - f = os.path.normpath(f) - if os.path.isabs(f): + for filename in files: + filename = os.path.normpath(filename) + if os.path.isabs(filename): continue - src = os.path.join(src_dir, f) - dst = os.path.join(dst_dir, f) + src = os.path.join(src_dir, filename) + dst = os.path.join(dst_dir, filename) if not os.path.exists(dst): if not os.path.isfile(src): warning('missing file: %s' % src) @@ -323,10 +338,14 @@ def get_source_options(asciidoc_file): result = [] if os.path.isfile(asciidoc_file): options = '' - for line in open(asciidoc_file): - mo = re.search(r'^//\s*a2x:', line) - if mo: - options += ' ' + line[mo.end():].strip() + f = open(asciidoc_file) + try: + for line in f: + mo = re.search(r'^//\s*a2x:', line) + if mo: + options += ' ' + line[mo.end():].strip() + finally: + f.close() parse_options() return result @@ -435,8 +454,12 @@ class A2X(AttrDict): if self.resource_manifest: if not os.path.isfile(self.resource_manifest): die('missing --resource-manifest: %s' % self.resource_manifest) - for r in open(self.resource_manifest): - self.resources.append(r.strip()) + f = open(self.resource_manifest) + try: + for r in f: + self.resources.append(r.strip()) + finally: + f.close() for r in self.resources: r = os.path.expanduser(r) r = os.path.expandvars(r) @@ -710,7 +733,7 @@ class A2X(AttrDict): f = os.path.normpath(f) if f not in ['content.opf']: resource_files.append(f) - opf = xml.dom.minidom.parseString(open(opf_file).read()) + opf = xml.dom.minidom.parseString(read_file(opf_file)) manifest_files = [] manifest = opf.getElementsByTagName('manifest')[0] for el in manifest.getElementsByTagName('item'): @@ -731,7 +754,7 @@ class A2X(AttrDict): item.setAttribute('media-type', mimetype) manifest.appendChild(item) if count > 0: - open(opf_file, 'w').write(opf.toxml()) + write_file(opf_file, opf.toxml()) def to_epub(self): self.to_docbook() @@ -763,7 +786,7 @@ class A2X(AttrDict): try: # Create and add uncompressed mimetype file. verbose('archiving: mimetype') - open('mimetype','w').write('application/epub+zip') + write_file('mimetype', 'application/epub+zip') zip.write('mimetype', compress_type=zipfile.ZIP_STORED) # Compress all remaining files. for (p,dirs,files) in os.walk('.'): diff --git a/asciidoc.conf b/asciidoc.conf index 45a3be2..03c0934 100644 --- a/asciidoc.conf +++ b/asciidoc.conf @@ -519,7 +519,7 @@ emphasis-style=tags="emphasis" strong-style=tags="strong" monospaced-style=tags="monospaced" header-style=tags="header" -asciidoc-style=tags="asciidoc",subs=(),filter='python "{asciidoc-file}" -b {backend} {asciidoc-args}{lang? -a "lang={lang}@"}{icons? -a icons -a "iconsdir={iconsdir}"}{imagesdir? -a "imagesdir={imagesdir}"}{data-uri? -a data-uri} -a "indir={indir}"{trace? -a "trace={trace}"}{blockname? -a "blockname={blockname}"} -s -' +asciidoc-style=tags="asciidoc",subs=(),filter='"{python}" "{asciidoc-file}" -b {backend} {asciidoc-args}{lang? -a "lang={lang}@"}{icons? -a icons -a "iconsdir={iconsdir}"}{imagesdir? -a "imagesdir={imagesdir}"}{data-uri? -a data-uri} -a "indir={indir}"{trace? -a "trace={trace}"}{blockname? -a "blockname={blockname}"} -s -' [tabledef-nested] # Same as [tabledef-default] but with different delimiter and separator. @@ -533,7 +533,7 @@ emphasis-style=tags="emphasis" strong-style=tags="strong" monospaced-style=tags="monospaced" header-style=tags="header" -asciidoc-style=tags="asciidoc",subs=(),filter='python "{asciidoc-file}" -b {backend} {asciidoc-args}{lang? -a "lang={lang}@"}{icons? -a icons -a "iconsdir={iconsdir}"}{imagesdir? -a "imagesdir={imagesdir}"}{data-uri? -a data-uri} -a "indir={indir}"{trace? -a "trace={trace}"}{blockname? -a "blockname={blockname}"} -s -' +asciidoc-style=tags="asciidoc",subs=(),filter='"{python}" "{asciidoc-file}" -b {backend} {asciidoc-args}{lang? -a "lang={lang}@"}{icons? -a icons -a "iconsdir={iconsdir}"}{imagesdir? -a "imagesdir={imagesdir}"}{data-uri? -a data-uri} -a "indir={indir}"{trace? -a "trace={trace}"}{blockname? -a "blockname={blockname}"} -s -' #---------------------------------------- # Common block and macro markup templates diff --git a/asciidoc.py b/asciidoc.py index 953cae0..1b516be 100755 --- a/asciidoc.py +++ b/asciidoc.py @@ -799,14 +799,13 @@ def filter_lines(filter_cmd, lines, attrs={}): message.warning('filter not found: %s' % cmd) if found: filter_cmd = '"' + found + '"' + mo.group('tail') - if sys.platform == 'win32': - # Windows doesn't like running scripts directly so explicitly - # specify interpreter. - if found: - if cmd.endswith('.py'): - filter_cmd = 'python ' + filter_cmd - elif cmd.endswith('.rb'): - filter_cmd = 'ruby ' + filter_cmd + if found: + if cmd.endswith('.py'): + filter_cmd = '"%s" %s' % (document.attributes['python'], + filter_cmd) + elif cmd.endswith('.rb'): + filter_cmd = 'ruby ' + filter_cmd + message.verbose('filtering: ' + filter_cmd) try: p = subprocess.Popen(filter_cmd, shell=True, @@ -885,7 +884,11 @@ def system(name, args, is_macro=False, attrs=None): message.warning('%s: non-zero exit status' % syntax) try: if os.path.isfile(tmp): - lines = [s.rstrip() for s in open(tmp)] + f = open(tmp) + try: + lines = [s.rstrip() for s in f] + finally: + f.close() else: lines = [] except Exception: @@ -954,7 +957,11 @@ def system(name, args, is_macro=False, attrs=None): elif not is_safe_file(args): message.unsafe(syntax) else: - result = [s.rstrip() for s in open(args)] + f = open(args) + try: + result = [s.rstrip() for s in f] + finally: + f.close() if result: result = subs_attrs(result) result = separator.join(result) @@ -2745,8 +2752,7 @@ class List(AbstractBlock): AbstractBlock.__init__(self) self.CONF_ENTRIES += ('type','tags') self.PARAM_NAMES += ('tags',) -#ZZZ listdef? - # tabledef conf file parameters. + # listdef conf file parameters. self.type=None self.tags=None # Name of listtags-<tags> conf section. # Calculated parameters. @@ -4157,8 +4163,12 @@ class Reader1: message.verbose('include1: ' + fname, linenos=False) # Store the include file in memory for later # retrieval by the {include1:} system attribute. - config.include1[fname] = [ - s.rstrip() for s in open(fname)] + f = open(fname) + try: + config.include1[fname] = [ + s.rstrip() for s in f] + finally: + f.close() return '{include1:%s}' % fname else: # This is a configuration dump, just pass the macro @@ -5880,6 +5890,7 @@ def asciidoc(backend, doctype, confiles, infile, outfile, options): else: raise EAsciiDoc,'missing configuration file: %s' % f try: + document.attributes['python'] = sys.executable for f in config.filters: if not config.find_config_dir('filters', f): raise EAsciiDoc,'missing filter: %s' % f diff --git a/doc/asciidoc.txt b/doc/asciidoc.txt index dadd961..20d02d9 100644 --- a/doc/asciidoc.txt +++ b/doc/asciidoc.txt @@ -4598,6 +4598,7 @@ predefined intrinsic attributes: {notitle} do not display the document title {outdir} document output directory name (note 2) {outfile} output file name (note 2) + {python} the full path name of the Python interpreter executable {rdquo} Right double quote character (note 7) {reftext} running block xreflabel generated by BlockId elements {revdate} document revision date (from document header) diff --git a/filters/latex/latex2png.py b/filters/latex/latex2png.py index 65945a6..3cae7c9 100755 --- a/filters/latex/latex2png.py +++ b/filters/latex/latex2png.py @@ -90,6 +90,20 @@ def print_verbose(line): if verbose: print_stderr(line) +def write_file(filename, data, mode='w'): + f = open(filename, mode) + try: + f.write(data) + finally: + f.close() + +def read_file(filename, mode='r'): + f = open(filename, mode) + try: + return f.read() + finally: + f.close() + def run(cmd): global verbose if verbose: @@ -117,12 +131,12 @@ def latex2png(infile, outfile, dpi, modified): checksum = md5.new(tex).digest() md5_file = os.path.splitext(outfile)[0] + '.md5' if os.path.isfile(md5_file) and os.path.isfile(outfile) and \ - checksum == open(md5_file,'rb').read(): + checksum == read_file(md5_file,'rb'): skip = True else: if not os.path.isfile(infile): raise EApp, 'input file does not exist: %s' % infile - tex = open(infile).read() + tex = read_file(infile) if modified and os.path.isfile(outfile) and \ os.path.getmtime(infile) <= os.path.getmtime(outfile): skip = True @@ -131,7 +145,7 @@ def latex2png(infile, outfile, dpi, modified): return tex = '%s\n%s\n%s\n' % (TEX_HEADER, tex.strip(), TEX_FOOTER) print_verbose('tex:\n%s' % tex) - open(texfile, 'w').write(tex) + write_file(texfile, tex) saved_pwd = os.getcwd() os.chdir(outdir) try: @@ -152,7 +166,7 @@ def latex2png(infile, outfile, dpi, modified): os.remove(f) if 'md5_file' in locals(): print_verbose('writing: %s' % md5_file) - open(md5_file,'wb').write(checksum) + write_file(md5_file, checksum, 'wb') def usage(msg=''): if msg: diff --git a/filters/music/music2png.py b/filters/music/music2png.py index 9f1cda0..011cd1d 100755 --- a/filters/music/music2png.py +++ b/filters/music/music2png.py @@ -70,6 +70,20 @@ def print_verbose(line): if verbose: print_stderr(line) +def write_file(filename, data, mode='w'): + f = open(filename, mode) + try: + f.write(data) + finally: + f.close() + +def read_file(filename, mode='r'): + f = open(filename, mode) + try: + return f.read() + finally: + f.close() + def run(cmd): global verbose if not verbose: @@ -90,19 +104,20 @@ def music2png(format, infile, outfile, modified): if infile == '-': source = sys.stdin.read() checksum = md5.new(source).digest() - f = os.path.splitext(outfile)[0] + '.md5' + filename = os.path.splitext(outfile)[0] + '.md5' if modified: - if os.path.isfile(f) and os.path.isfile(outfile) and \ - checksum == open(f,'rb').read(): + if os.path.isfile(filename) and os.path.isfile(outfile) and \ + checksum == read_file(filename,'rb'): skip = True - open(f,'wb').write(checksum) + else: + write_file(filename, checksum, 'wb') else: if not os.path.isfile(infile): raise EApp, 'input file does not exist: %s' % infile if modified and os.path.isfile(outfile) and \ os.path.getmtime(infile) <= os.path.getmtime(outfile): skip = True - source = open(infile).read() + source = read_file(infile) if skip: print_verbose('skipped: no change: %s' % outfile) return @@ -111,7 +126,8 @@ def music2png(format, infile, outfile, modified): format = 'ly' else: format = 'abc' - open('%s.%s' % (basefile,format), 'w').write(source) # Temp source file. + # Write temporary source file. + write_file('%s.%s' % (basefile,format), source) abc = basefile + '.abc' ly = basefile + '.ly' png = basefile + '.png' @@ -81,7 +81,7 @@ latexmath-style=template="latexmathblock",subs=() <a class="image" href="{link}"> {data-uri%}<img src="{imagesdir=}{imagesdir?/}{target}" alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"}{title? title="{title}"}> {data-uri#}<img alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"}{title? title="{title}"} src="data:image/{eval:os.path.splitext(r'{target}')[1][1:]};base64, -{data-uri#}{sys3:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{imagesdir=}",r"{target}")}"}"> +{data-uri#}{sys3:"{python}" -u -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{imagesdir=}",r"{target}")}"}"> {link#}</a> </span> @@ -91,7 +91,7 @@ latexmath-style=template="latexmathblock",subs=() <a class="image" href="{link}"> {data-uri%}<img src="{imagesdir=}{imagesdir?/}{target}" alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"}> {data-uri#}<img alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"} src="data:image/{eval:os.path.splitext(r'{target}')[1][1:]};base64, -{data-uri#}{sys:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{imagesdir=}",r"{target}")}"}"> +{data-uri#}{sys:"{python}" -u -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{imagesdir=}",r"{target}")}"}"> {link#}</a> </div> <div class="title">{caption={figure-caption} {counter:figure-number}. }{title}</div> @@ -150,7 +150,7 @@ ifndef::data-uri[] endif::data-uri[] ifdef::data-uri[] <img alt="{index}" src="data:image/png;base64, -{sys:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/callouts/{index}.png}")}"}"> +{sys:"{python}" -u -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/callouts/{index}.png}")}"}"> endif::data-uri[] endif::icons[] @@ -213,7 +213,7 @@ ifndef::data-uri[] item=<tr><td><img src="{iconsdir}/callouts/{listindex}.png" alt="{listindex}"></td><td>|</td></tr> endif::data-uri[] ifdef::data-uri[] -item=<tr><td><img alt="{listindex}" src="data:image/png;base64, {sys:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/callouts/{listindex}.png}")}"}"></td><td>|</td></tr> +item=<tr><td><img alt="{listindex}" src="data:image/png;base64, {sys:"{python}" -u -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/callouts/{listindex}.png}")}"}"></td><td>|</td></tr> endif::data-uri[] text=| endif::icons[] @@ -378,7 +378,7 @@ template::[quoteblock] <td class="icon"> {data-uri%}{icons#}<img src="{icon={iconsdir}/{name}.png}" alt="{caption}"> {data-uri#}{icons#}<img alt="{caption}" src="data:image/png;base64, -{data-uri#}{icons#}{sys:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/{name}.png}")}"}"> +{data-uri#}{icons#}{sys:"{python}" -u -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/{name}.png}")}"}"> {icons%}<div class="title">{caption}</div> </td> <td class="content"> diff --git a/tests/testasciidoc.py b/tests/testasciidoc.py index aa185f1..679ad35 100755 --- a/tests/testasciidoc.py +++ b/tests/testasciidoc.py @@ -21,7 +21,14 @@ __version__ = '0.1.1' __copyright__ = 'Copyright (C) 2009 Stuart Rackham' -import os, sys, re, StringIO, difflib +import os, sys, re, difflib + +if sys.platform[:4] == 'java': + # Jython cStringIO is more compatible with CPython StringIO. + import cStringIO as StringIO +else: + import StringIO + import asciidocapi diff --git a/xhtml11-quirks.conf b/xhtml11-quirks.conf index c20376e..7c13366 100644 --- a/xhtml11-quirks.conf +++ b/xhtml11-quirks.conf @@ -10,7 +10,7 @@ <a class="image" href="{link}"> {data-uri%}<img src="{imagesdir=}{imagesdir?/}{target}" alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"} /> {data-uri#}<img alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"} src="data:image/{eval:os.path.splitext(r'{target}')[1][1:]};base64, -{data-uri#}{sys:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{imagesdir=}",r"{target}")}"}" /> +{data-uri#}{sys:"{python}" -u -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{imagesdir=}",r"{target}")}"}" /> {link#}</a> </div> <div class="image-title">{caption={figure-caption} {counter:figure-number}: }{title}</div> diff --git a/xhtml11.conf b/xhtml11.conf index ce5fa19..c1ebb91 100644 --- a/xhtml11.conf +++ b/xhtml11.conf @@ -80,7 +80,7 @@ latexmath-style=template="latexmathblock",subs=() <a class="image" href="{link}"> {data-uri%}<img src="{imagesdir=}{imagesdir?/}{target}" alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"}{title? title="{title}"} /> {data-uri#}<img alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"}{title? title="{title}"} src="data:image/{eval:os.path.splitext(r'{target}')[1][1:]};base64, -{data-uri#}{sys3:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{imagesdir=}",r"{target}")}"}" /> +{data-uri#}{sys3:"{python}" -u -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{imagesdir=}",r"{target}")}"}" /> {link#}</a> </span> @@ -90,7 +90,7 @@ latexmath-style=template="latexmathblock",subs=() <a class="image" href="{link}"> {data-uri%}<img src="{imagesdir=}{imagesdir?/}{target}" alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"} /> {data-uri#}<img alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"} src="data:image/{eval:os.path.splitext(r'{target}')[1][1:]};base64, -{data-uri#}{sys:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{imagesdir=}",r"{target}")}"}" /> +{data-uri#}{sys:"{python}" -u -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{imagesdir=}",r"{target}")}"}" /> {link#}</a> </div> <div class="title">{caption={figure-caption} {counter:figure-number}. }{title}</div> @@ -131,7 +131,7 @@ ifndef::data-uri[] endif::data-uri[] ifdef::data-uri[] <img alt="{index}" src="data:image/png;base64, -{sys:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/callouts/{index}.png}")}"}" /> +{sys:"{python}" -u -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/callouts/{index}.png}")}"}" /> endif::data-uri[] endif::icons[] @@ -194,7 +194,7 @@ ifndef::data-uri[] item=<tr><td><img src="{iconsdir}/callouts/{listindex}.png" alt="{listindex}" /></td><td>|</td></tr> endif::data-uri[] ifdef::data-uri[] -item=<tr><td><img alt="{listindex}" src="data:image/png;base64, {sys:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/callouts/{listindex}.png}")}"}" /></td><td>|</td></tr> +item=<tr><td><img alt="{listindex}" src="data:image/png;base64, {sys:"{python}" -u -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/callouts/{listindex}.png}")}"}" /></td><td>|</td></tr> endif::data-uri[] text=| endif::icons[] @@ -359,7 +359,7 @@ template::[quoteblock] <td class="icon"> {data-uri%}{icons#}<img src="{icon={iconsdir}/{name}.png}" alt="{caption}" /> {data-uri#}{icons#}<img alt="{caption}" src="data:image/png;base64, -{data-uri#}{icons#}{sys:python -uc "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/{name}.png}")}"}" /> +{data-uri#}{icons#}{sys:"{python}" -u -c "import base64,sys; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{icon={iconsdir}/{name}.png}")}"}" /> {icons%}<div class="title">{caption}</div> </td> <td class="content"> |