base16-schemes: unstable-2024-06-21 -> unstable-2024-11-12 (#356361)
[NixPkgs.git] / pkgs / tools / typesetting / asciidoc / default.nix
blob24e1c6bc1a304becbee439504f4558dee4724701
1 { fetchurl, lib, stdenv, python3
2 , fetchFromGitHub, autoreconfHook
3 , installShellFiles
4 , enableStandardFeatures ? false
5 , sourceHighlight
6 , highlight
7 , pygments
8 , graphviz
9 , texliveMinimal
10 , dblatexFull
11 , libxslt
12 , w3m
13 , lynx
14 , imagemagick
15 , lilypond
16 , libxml2
17 , docbook_xml_dtd_45
18 , docbook_xsl_ns
19 , docbook_xsl
20 , fop
21 , epubcheck
22 , gnused
23 , coreutils
25 # if true, enable all the below filters and backends
26 , enableExtraPlugins ? false
28 # unzip is needed to extract filter and backend plugins
29 , unzip
30 # filters
31 , enableDitaaFilter ? false, jre
32 , enableMscgenFilter ? false, mscgen
33 , enableDiagFilter ? false, blockdiag, seqdiag, actdiag, nwdiag
34 , enableQrcodeFilter ? false, qrencode
35 , enableMatplotlibFilter ? false, matplotlib, numpy
36 , enableAafigureFilter ? false, aafigure, recursive-pth-loader
37 # backends
38 , enableDeckjsBackend ? false
39 , enableOdfBackend ? false
41 # java is problematic on some platforms, where it is unfree
42 , enableJava ? true
44 , buildPackages
47 let
49   _enableDitaaFilter = (enableExtraPlugins && enableJava) || enableDitaaFilter;
50   _enableMscgenFilter = enableExtraPlugins || enableMscgenFilter;
51   _enableDiagFilter = enableExtraPlugins || enableDiagFilter;
52   _enableQrcodeFilter = enableExtraPlugins || enableQrcodeFilter;
53   _enableMatplotlibFilter = enableExtraPlugins || enableMatplotlibFilter;
54   _enableAafigureFilter = enableExtraPlugins || enableAafigureFilter;
55   _enableDeckjsBackend = enableExtraPlugins || enableDeckjsBackend;
56   _enableOdfBackend = enableExtraPlugins || enableOdfBackend;
58   #
59   # texlive environment
60   #
61   texlive = texliveMinimal.withPackages (ps: [ ps.dvipng ]);
63   #
64   # filters
65   #
67   ditaaFilterSrc = fetchurl {
68     url = "https://asciidoc-ditaa-filter.googlecode.com/files/ditaa-filter-1.1.zip";
69     sha256 = "0p7hm2a1xywx982ia3vg4c0lam5sz0xknsc10i2a5vswy026naf6";
70   };
72   mscgenFilterSrc = fetchurl {
73     url = "https://asciidoc-mscgen-filter.googlecode.com/files/mscgen-filter-1.2.zip";
74     sha256 = "1nfwmj375gpv5dn9i770pjv59aihzy2kja0fflsk96xwnlqsqq61";
75   };
77   diagFilterSrc = fetchurl {
78     # unfortunately no version number
79     url = "https://asciidoc-diag-filter.googlecode.com/files/diag_filter.zip";
80     sha256 = "1qlqrdbqkdqqgfdhjsgdws1al0sacsyq6jmwxdfy7r8k7bv7n7mm";
81   };
83   qrcodeFilterSrc = fetchurl {
84     url = "https://asciidoc-qrencode-filter.googlecode.com/files/qrcode-filter-1.0.zip";
85     sha256 = "0h4bql1nb4y4fmg2yvlpfjhvy22ln8jsaxdr10f8bfcg5lr0zkxs";
86   };
88   # there are no archives or tags, using latest commit in master branch as per 2013-09-22
89   matplotlibFilterSrc = let commit = "75f0d009629f93f33fab04b83faca20cc35dd358"; in fetchurl {
90     name = "mplw-${commit}.tar.gz";
91     url = "https://api.github.com/repos/lvv/mplw/tarball/${commit}";
92     sha256 = "0yfhkm2dr8gnp0fcg25x89hwiymkri2m5cyqzmzragzwj0hbmcf1";
93   };
95   aafigureFilterSrc = fetchurl {
96     url = "https://asciidoc-aafigure-filter.googlecode.com/files/aafigure-filter-1.1.zip";
97     sha256 = "1hq2s30dvmv5dqvj0xm1qwdwafhgm9w1iyr0lr0c40cyk8h00j8j";
98   };
100   #
101   # backends
102   #
104   deckjsBackendSrc = fetchurl {
105     url = "https://github.com/downloads/houqp/asciidoc-deckjs/deckjs-1.6.2.zip";
106     sha256 = "1siy1j8naj5irrrrv5bfgl4d8nal6j9pyahy4f50wmrr9wv59s46";
107   };
109   # the odf backend is actually two plugins: odt + odp
110   odtBackendSrc = fetchurl {
111     url = "https://github.com/downloads/dagwieers/asciidoc-odf/odt-backend-0.1.zip";
112     sha256 = "1zaa97h9sx6ncxcdkl1x3ggydi7f8kjgvrnpjnkjiizi45k350kw";
113   };
115   odpBackendSrc = fetchurl {
116     url = "https://github.com/downloads/dagwieers/asciidoc-odf/odp-backend-0.1.zip";
117     sha256 = "08ya4bskygzqkfqwjllpg31qc5k08xp2k78z9b2480g8y57bfy10";
118   };
120 in python3.pkgs.buildPythonApplication rec {
121   pname = "asciidoc"
122     + lib.optionalString enableStandardFeatures "-full"
123     + lib.optionalString enableExtraPlugins "-with-plugins";
124   version = "10.2.1";
125   pyproject = true;
127   src = fetchFromGitHub {
128     owner = "asciidoc-py";
129     repo = "asciidoc-py";
130     rev = version;
131     hash = "sha256-td3C7xTWfSzdo9Bbz0dHW2oPaCQYmUE9H2sUFfg5HH0=";
132   };
134   nativeBuildInputs = [
135     autoreconfHook
136     installShellFiles
137     unzip
138   ];
140   # install filters early, so their shebangs are patched too
141   postPatch = ''
142     mkdir -p "$out/etc/asciidoc/filters"
143     mkdir -p "$out/etc/asciidoc/backends"
144   '' + lib.optionalString _enableDitaaFilter ''
145     echo "Extracting ditaa filter"
146     unzip -d "$out/etc/asciidoc/filters/ditaa" "${ditaaFilterSrc}"
147     sed -i -e "s|java -jar|${jre}/bin/java -jar|" \
148         "$out/etc/asciidoc/filters/ditaa/ditaa2img.py"
149   '' + lib.optionalString _enableMscgenFilter ''
150     echo "Extracting mscgen filter"
151     unzip -d "$out/etc/asciidoc/filters/mscgen" "${mscgenFilterSrc}"
152     sed -i -e "s|filter-wrapper.py mscgen|filter-wrapper.py ${mscgen}/bin/mscgen|" \
153         "$out/etc/asciidoc/filters/mscgen/mscgen-filter.conf"
154   '' + lib.optionalString _enableDiagFilter ''
155     echo "Extracting diag filter"
156     unzip -d "$out/etc/asciidoc/filters/diag" "${diagFilterSrc}"
157     sed -i \
158         -e "s|filter='blockdiag|filter=\'${blockdiag}/bin/blockdiag|" \
159         -e "s|filter='seqdiag|filter=\'${seqdiag}/bin/seqdiag|" \
160         -e "s|filter='actdiag|filter=\'${actdiag}/bin/actdiag|" \
161         -e "s|filter='nwdiag|filter=\'${nwdiag}/bin/nwdiag|" \
162         -e "s|filter='packetdiag|filter=\'${nwdiag}/bin/packetdiag|" \
163         "$out/etc/asciidoc/filters/diag/diag-filter.conf"
164   '' + lib.optionalString _enableQrcodeFilter ''
165     echo "Extracting qrcode filter"
166     unzip -d "$out/etc/asciidoc/filters/qrcode" "${qrcodeFilterSrc}"
167     sed -i -e "s|systemcmd('qrencode|systemcmd('${qrencode}/bin/qrencode|" \
168         "$out/etc/asciidoc/filters/qrcode/qrcode2img.py"
169   '' + lib.optionalString _enableMatplotlibFilter ''
170     echo "Extracting mpl (matplotlib) filter"
171     mkdir -p "$out/etc/asciidoc/filters/mpl"
172     tar xvf "${matplotlibFilterSrc}" -C "$out/etc/asciidoc/filters/mpl" --strip-components=1
173     # Stop asciidoc from loading mpl/.old/chart-filter.conf
174     rm -rf "$out/etc/asciidoc/filters/mpl/.old"
175     # Add matplotlib and numpy to sys.path
176     matplotlib_path="$(toPythonPath ${matplotlib})"
177     numpy_path="$(toPythonPath ${numpy})"
178     sed -i "/^import.*sys/asys.path.append(\"$matplotlib_path\"); sys.path.append(\"$numpy_path\");" \
179         "$out/etc/asciidoc/filters/mpl/mplw.py"
180   '' + lib.optionalString _enableAafigureFilter ''
181     echo "Extracting aafigure filter"
182     unzip -d "$out/etc/asciidoc/filters/aafigure" "${aafigureFilterSrc}"
183     # Add aafigure to sys.path (and it needs recursive-pth-loader)
184     pth_loader_path="$(toPythonPath ${recursive-pth-loader})"
185     aafigure_path="$(toPythonPath ${aafigure})"
186     sed -i "/^import.*sys/asys.path.append(\"$pth_loader_path\"); sys.path.append(\"$aafigure_path\"); import sitecustomize" \
187         "$out/etc/asciidoc/filters/aafigure/aafig2img.py"
188   '' + lib.optionalString _enableDeckjsBackend ''
189     echo "Extracting deckjs backend"
190     unzip -d "$out/etc/asciidoc/backends/deckjs" "${deckjsBackendSrc}"
191   '' + lib.optionalString _enableOdfBackend ''
192     echo "Extracting odf backend (odt + odp)"
193     unzip -d "$out/etc/asciidoc/backends/odt" "${odtBackendSrc}"
194     unzip -d "$out/etc/asciidoc/backends/odp" "${odpBackendSrc}"
195     # The odt backend has a TODO note about removing this hardcoded path, but
196     # the odp backend already has that fix. Copy it here until fixed upstream.
197     sed -i "s|'/etc/asciidoc/backends/odt/asciidoc.ott'|os.path.dirname(__file__),'asciidoc.ott'|" \
198         "$out/etc/asciidoc/backends/odt/a2x-backend.py"
199   '' + (if enableStandardFeatures then ''
200     sed -e "s|dot|${graphviz}/bin/dot|g" \
201         -e "s|neato|${graphviz}/bin/neato|g" \
202         -e "s|twopi|${graphviz}/bin/twopi|g" \
203         -e "s|circo|${graphviz}/bin/circo|g" \
204         -e "s|fdp|${graphviz}/bin/fdp|g" \
205         -i "asciidoc/resources/filters/graphviz/graphviz2png.py"
207     sed -e "s|run('latex|run('${texlive}/bin/latex|g" \
208         -e "s|cmd = 'dvipng'|cmd = '${texlive}/bin/dvipng'|g" \
209         -e "s|cmd = 'dvisvgm'|cmd = '${texlive}/bin/dvisvgm'|g" \
210         -i "asciidoc/resources/filters/latex/latex2img.py"
212     sed -e "s|run('abc2ly|run('${lilypond}/bin/abc2ly|g" \
213         -e "s|run('lilypond|run('${lilypond}/bin/lilypond|g" \
214         -e "s|run('convert|run('${imagemagick.out}/bin/convert|g" \
215         -i "asciidoc/resources/filters/music/music2png.py"
217     sed -e 's|filter="source-highlight|filter="${sourceHighlight}/bin/source-highlight|' \
218         -e 's|filter="highlight|filter="${highlight}/bin/highlight|' \
219         -e 's|filter="pygmentize|filter="${pygments}/bin/pygmentize|' \
220         -i "asciidoc/resources/filters/source/source-highlight-filter.conf"
222     # ENV is custom environment passed to programs that a2x invokes. Here we
223     # use it to work around an impurity in the tetex package; tetex tools
224     # cannot find their neighbours (e.g. pdflatex doesn't find mktextfm).
225     # We can remove PATH= when those impurities are fixed.
226     # TODO: Is this still necessary when using texlive?
227     sed -e "s|^ENV =.*|ENV = dict(XML_CATALOG_FILES='${docbook_xml_dtd_45}/xml/dtd/docbook/catalog.xml ${docbook_xsl_ns}/xml/xsl/docbook/catalog.xml ${docbook_xsl}/xml/xsl/docbook/catalog.xml', PATH='${lib.makeBinPath [ texlive coreutils gnused ]}', **(dict(filter(lambda v: v[0] == 'SOURCE_DATE_EPOCH', os.environ.items()))))|" \
228         -e "s|^ASCIIDOC =.*|ASCIIDOC = '$out/bin/asciidoc'|" \
229         -e "s|^XSLTPROC =.*|XSLTPROC = '${libxslt.bin}/bin/xsltproc'|" \
230         -e "s|^DBLATEX =.*|DBLATEX = '${dblatexFull}/bin/dblatex'|" \
231         ${lib.optionalString enableJava ''-e "s|^FOP =.*|FOP = '${fop}/bin/fop'|"''} \
232         -e "s|^W3M =.*|W3M = '${w3m}/bin/w3m'|" \
233         -e "s|^LYNX =.*|LYNX = '${lynx}/bin/lynx'|" \
234         -e "s|^XMLLINT =.*|XMLLINT = '${libxml2.bin}/bin/xmllint'|" \
235         -e "s|^EPUBCHECK =.*|EPUBCHECK = '${epubcheck}/bin/epubcheck'|" \
236         -i asciidoc/a2x.py
237   '' else ''
238     sed -e "s|^ENV =.*|ENV = dict(XML_CATALOG_FILES='${docbook_xml_dtd_45}/xml/dtd/docbook/catalog.xml ${docbook_xsl_ns}/xml/xsl/docbook/catalog.xml ${docbook_xsl}/xml/xsl/docbook/catalog.xml', **(dict(filter(lambda v: v[0] == 'SOURCE_DATE_EPOCH', os.environ.items()))))|" \
239         -e "s|^XSLTPROC =.*|XSLTPROC = '${libxslt.bin}/bin/xsltproc'|" \
240         -e "s|^XMLLINT =.*|XMLLINT = '${libxml2.bin}/bin/xmllint'|" \
241         -i asciidoc/a2x.py
242   '') + ''
243     # Fix tests
244     for f in $(grep -R --files-with-matches "2002-11-25") ; do
245       substituteInPlace $f --replace "2002-11-25" "1980-01-02"
246       substituteInPlace $f --replace "00:37:42" "00:00:00"
247     done
248   '' + lib.optionalString (stdenv.buildPlatform != stdenv.hostPlatform) ''
249     # We want to use asciidoc from the build platform to build the documentation.
250     substituteInPlace Makefile.in \
251       --replace "python3 -m asciidoc.a2x" "${buildPackages.asciidoc}/bin/a2x"
252   '';
254   build-system = with python3.pythonOnBuildForHost.pkgs; [ setuptools ];
256   postBuild = ''
257     make manpages
258   '';
260   postInstall = ''
261     installManPage doc/asciidoc.1 doc/a2x.1 doc/testasciidoc.1
262   '';
264   nativeCheckInputs = with python3.pkgs; [
265     pytest
266     pytest-mock
267   ];
269   checkPhase = ''
270     runHook preCheck
272     make test
274     runHook postCheck
275   '';
277   meta = {
278     description = "Text-based document generation system";
279     longDescription = ''
280       AsciiDoc is a text document format for writing notes, documentation,
281       articles, books, ebooks, slideshows, web pages, man pages and blogs.
282       AsciiDoc files can be translated to many formats including HTML, PDF,
283       EPUB, man page.
285       AsciiDoc is highly configurable: both the AsciiDoc source file syntax and
286       the backend output markups (which can be almost any type of SGML/XML
287       markup) can be customized and extended by the user.
288     '';
289     sourceProvenance = [ lib.sourceTypes.fromSource ]
290       ++ lib.optional _enableDitaaFilter lib.sourceTypes.binaryBytecode;
291     homepage = "https://asciidoc-py.github.io/";
292     changelog = "https://github.com/asciidoc-py/asciidoc-py/blob/${version}/CHANGELOG.adoc";
293     license = lib.licenses.gpl2Plus;
294     platforms = lib.platforms.unix;
295     maintainers = with lib.maintainers; [ bjornfor dotlambda ];
296   };