push sheeet
Some checks failed
Periodic Merges (6h) / master → staging-nixos (push) Failing after 12m50s
Periodic Merges (6h) / master → staging-next (push) Failing after 12m54s
Periodic Merges (24h) / merge-base(master,staging) → haskell-updates (push) Failing after 11m54s
Periodic Merges (6h) / staging-next → staging (push) Failing after 12m13s
Periodic Merges (24h) / staging-next-25.05 → staging-25.05 (push) Failing after 13m24s
Periodic Merges (24h) / release-25.05 → staging-next-25.05 (push) Failing after 14m28s

This commit is contained in:
Dark Steveneq
2025-10-09 14:15:47 +02:00
commit 646b892680
49168 changed files with 5897842 additions and 0 deletions

View File

@@ -0,0 +1,346 @@
{
fetchurl,
lib,
stdenv,
python3,
fetchFromGitHub,
autoreconfHook,
installShellFiles,
enableStandardFeatures ? false,
sourceHighlight,
highlight,
pygments,
graphviz,
texliveMinimal,
dblatexFull,
libxslt,
w3m,
lynx,
imagemagick,
lilypond,
libxml2,
docbook_xml_dtd_45,
docbook_xsl_ns,
docbook_xsl,
fop,
epubcheck,
gnused,
coreutils,
# if true, enable all the below filters and backends
enableExtraPlugins ? false,
# unzip is needed to extract filter and backend plugins
unzip,
# filters
enableDitaaFilter ? false,
jre,
enableMscgenFilter ? false,
mscgen,
enableDiagFilter ? false,
blockdiag,
seqdiag,
actdiag,
nwdiag,
enableQrcodeFilter ? false,
qrencode,
enableMatplotlibFilter ? false,
matplotlib,
numpy,
enableAafigureFilter ? false,
aafigure,
recursive-pth-loader,
# backends
enableDeckjsBackend ? false,
enableOdfBackend ? false,
# java is problematic on some platforms, where it is unfree
enableJava ? true,
buildPackages,
}:
let
_enableDitaaFilter = (enableExtraPlugins && enableJava) || enableDitaaFilter;
_enableMscgenFilter = enableExtraPlugins || enableMscgenFilter;
_enableDiagFilter = enableExtraPlugins || enableDiagFilter;
_enableQrcodeFilter = enableExtraPlugins || enableQrcodeFilter;
_enableMatplotlibFilter = enableExtraPlugins || enableMatplotlibFilter;
_enableAafigureFilter = enableExtraPlugins || enableAafigureFilter;
_enableDeckjsBackend = enableExtraPlugins || enableDeckjsBackend;
_enableOdfBackend = enableExtraPlugins || enableOdfBackend;
#
# texlive environment
#
texlive = texliveMinimal.withPackages (ps: [ ps.dvipng ]);
#
# filters
#
ditaaFilterSrc = fetchurl {
url = "https://asciidoc-ditaa-filter.googlecode.com/files/ditaa-filter-1.1.zip";
sha256 = "0p7hm2a1xywx982ia3vg4c0lam5sz0xknsc10i2a5vswy026naf6";
};
mscgenFilterSrc = fetchurl {
url = "https://asciidoc-mscgen-filter.googlecode.com/files/mscgen-filter-1.2.zip";
sha256 = "1nfwmj375gpv5dn9i770pjv59aihzy2kja0fflsk96xwnlqsqq61";
};
diagFilterSrc = fetchurl {
# unfortunately no version number
url = "https://asciidoc-diag-filter.googlecode.com/files/diag_filter.zip";
sha256 = "1qlqrdbqkdqqgfdhjsgdws1al0sacsyq6jmwxdfy7r8k7bv7n7mm";
};
qrcodeFilterSrc = fetchurl {
url = "https://asciidoc-qrencode-filter.googlecode.com/files/qrcode-filter-1.0.zip";
sha256 = "0h4bql1nb4y4fmg2yvlpfjhvy22ln8jsaxdr10f8bfcg5lr0zkxs";
};
# there are no archives or tags, using latest commit in master branch as per 2013-09-22
matplotlibFilterSrc =
let
commit = "75f0d009629f93f33fab04b83faca20cc35dd358";
in
fetchurl {
name = "mplw-${commit}.tar.gz";
url = "https://api.github.com/repos/lvv/mplw/tarball/${commit}";
sha256 = "0yfhkm2dr8gnp0fcg25x89hwiymkri2m5cyqzmzragzwj0hbmcf1";
};
aafigureFilterSrc = fetchurl {
url = "https://asciidoc-aafigure-filter.googlecode.com/files/aafigure-filter-1.1.zip";
sha256 = "1hq2s30dvmv5dqvj0xm1qwdwafhgm9w1iyr0lr0c40cyk8h00j8j";
};
#
# backends
#
deckjsBackendSrc = fetchurl {
url = "https://github.com/downloads/houqp/asciidoc-deckjs/deckjs-1.6.2.zip";
sha256 = "1siy1j8naj5irrrrv5bfgl4d8nal6j9pyahy4f50wmrr9wv59s46";
};
# the odf backend is actually two plugins: odt + odp
odtBackendSrc = fetchurl {
url = "https://github.com/downloads/dagwieers/asciidoc-odf/odt-backend-0.1.zip";
sha256 = "1zaa97h9sx6ncxcdkl1x3ggydi7f8kjgvrnpjnkjiizi45k350kw";
};
odpBackendSrc = fetchurl {
url = "https://github.com/downloads/dagwieers/asciidoc-odf/odp-backend-0.1.zip";
sha256 = "08ya4bskygzqkfqwjllpg31qc5k08xp2k78z9b2480g8y57bfy10";
};
in
python3.pkgs.buildPythonApplication rec {
pname =
"asciidoc"
+ lib.optionalString enableStandardFeatures "-full"
+ lib.optionalString enableExtraPlugins "-with-plugins";
version = "10.2.1";
pyproject = true;
src = fetchFromGitHub {
owner = "asciidoc-py";
repo = "asciidoc-py";
rev = version;
hash = "sha256-td3C7xTWfSzdo9Bbz0dHW2oPaCQYmUE9H2sUFfg5HH0=";
};
nativeBuildInputs = [
autoreconfHook
installShellFiles
unzip
];
# install filters early, so their shebangs are patched too
postPatch = ''
mkdir -p "$out/etc/asciidoc/filters"
mkdir -p "$out/etc/asciidoc/backends"
''
+ lib.optionalString _enableDitaaFilter ''
echo "Extracting ditaa filter"
unzip -d "$out/etc/asciidoc/filters/ditaa" "${ditaaFilterSrc}"
sed -i -e "s|java -jar|${jre}/bin/java -jar|" \
"$out/etc/asciidoc/filters/ditaa/ditaa2img.py"
''
+ lib.optionalString _enableMscgenFilter ''
echo "Extracting mscgen filter"
unzip -d "$out/etc/asciidoc/filters/mscgen" "${mscgenFilterSrc}"
sed -i -e "s|filter-wrapper.py mscgen|filter-wrapper.py ${mscgen}/bin/mscgen|" \
"$out/etc/asciidoc/filters/mscgen/mscgen-filter.conf"
''
+ lib.optionalString _enableDiagFilter ''
echo "Extracting diag filter"
unzip -d "$out/etc/asciidoc/filters/diag" "${diagFilterSrc}"
sed -i \
-e "s|filter='blockdiag|filter=\'${blockdiag}/bin/blockdiag|" \
-e "s|filter='seqdiag|filter=\'${seqdiag}/bin/seqdiag|" \
-e "s|filter='actdiag|filter=\'${actdiag}/bin/actdiag|" \
-e "s|filter='nwdiag|filter=\'${nwdiag}/bin/nwdiag|" \
-e "s|filter='packetdiag|filter=\'${nwdiag}/bin/packetdiag|" \
"$out/etc/asciidoc/filters/diag/diag-filter.conf"
''
+ lib.optionalString _enableQrcodeFilter ''
echo "Extracting qrcode filter"
unzip -d "$out/etc/asciidoc/filters/qrcode" "${qrcodeFilterSrc}"
sed -i -e "s|systemcmd('qrencode|systemcmd('${qrencode}/bin/qrencode|" \
"$out/etc/asciidoc/filters/qrcode/qrcode2img.py"
''
+ lib.optionalString _enableMatplotlibFilter ''
echo "Extracting mpl (matplotlib) filter"
mkdir -p "$out/etc/asciidoc/filters/mpl"
tar xvf "${matplotlibFilterSrc}" -C "$out/etc/asciidoc/filters/mpl" --strip-components=1
# Stop asciidoc from loading mpl/.old/chart-filter.conf
rm -rf "$out/etc/asciidoc/filters/mpl/.old"
# Add matplotlib and numpy to sys.path
matplotlib_path="$(toPythonPath ${matplotlib})"
numpy_path="$(toPythonPath ${numpy})"
sed -i "/^import.*sys/asys.path.append(\"$matplotlib_path\"); sys.path.append(\"$numpy_path\");" \
"$out/etc/asciidoc/filters/mpl/mplw.py"
''
+ lib.optionalString _enableAafigureFilter ''
echo "Extracting aafigure filter"
unzip -d "$out/etc/asciidoc/filters/aafigure" "${aafigureFilterSrc}"
# Add aafigure to sys.path (and it needs recursive-pth-loader)
pth_loader_path="$(toPythonPath ${recursive-pth-loader})"
aafigure_path="$(toPythonPath ${aafigure})"
sed -i "/^import.*sys/asys.path.append(\"$pth_loader_path\"); sys.path.append(\"$aafigure_path\"); import sitecustomize" \
"$out/etc/asciidoc/filters/aafigure/aafig2img.py"
''
+ lib.optionalString _enableDeckjsBackend ''
echo "Extracting deckjs backend"
unzip -d "$out/etc/asciidoc/backends/deckjs" "${deckjsBackendSrc}"
''
+ lib.optionalString _enableOdfBackend ''
echo "Extracting odf backend (odt + odp)"
unzip -d "$out/etc/asciidoc/backends/odt" "${odtBackendSrc}"
unzip -d "$out/etc/asciidoc/backends/odp" "${odpBackendSrc}"
# The odt backend has a TODO note about removing this hardcoded path, but
# the odp backend already has that fix. Copy it here until fixed upstream.
sed -i "s|'/etc/asciidoc/backends/odt/asciidoc.ott'|os.path.dirname(__file__),'asciidoc.ott'|" \
"$out/etc/asciidoc/backends/odt/a2x-backend.py"
''
+ (
if enableStandardFeatures then
''
sed -e "s|dot|${graphviz}/bin/dot|g" \
-e "s|neato|${graphviz}/bin/neato|g" \
-e "s|twopi|${graphviz}/bin/twopi|g" \
-e "s|circo|${graphviz}/bin/circo|g" \
-e "s|fdp|${graphviz}/bin/fdp|g" \
-i "asciidoc/resources/filters/graphviz/graphviz2png.py"
sed -e "s|run('latex|run('${texlive}/bin/latex|g" \
-e "s|cmd = 'dvipng'|cmd = '${texlive}/bin/dvipng'|g" \
-e "s|cmd = 'dvisvgm'|cmd = '${texlive}/bin/dvisvgm'|g" \
-i "asciidoc/resources/filters/latex/latex2img.py"
sed -e "s|run('abc2ly|run('${lilypond}/bin/abc2ly|g" \
-e "s|run('lilypond|run('${lilypond}/bin/lilypond|g" \
-e "s|run('convert|run('${imagemagick.out}/bin/convert|g" \
-i "asciidoc/resources/filters/music/music2png.py"
sed -e 's|filter="source-highlight|filter="${sourceHighlight}/bin/source-highlight|' \
-e 's|filter="highlight|filter="${highlight}/bin/highlight|' \
-e 's|filter="pygmentize|filter="${pygments}/bin/pygmentize|' \
-i "asciidoc/resources/filters/source/source-highlight-filter.conf"
# ENV is custom environment passed to programs that a2x invokes. Here we
# use it to work around an impurity in the tetex package; tetex tools
# cannot find their neighbours (e.g. pdflatex doesn't find mktextfm).
# We can remove PATH= when those impurities are fixed.
# TODO: Is this still necessary when using texlive?
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()))))|" \
-e "s|^ASCIIDOC =.*|ASCIIDOC = '$out/bin/asciidoc'|" \
-e "s|^XSLTPROC =.*|XSLTPROC = '${libxslt.bin}/bin/xsltproc'|" \
-e "s|^DBLATEX =.*|DBLATEX = '${dblatexFull}/bin/dblatex'|" \
${lib.optionalString enableJava ''-e "s|^FOP =.*|FOP = '${fop}/bin/fop'|"''} \
-e "s|^W3M =.*|W3M = '${w3m}/bin/w3m'|" \
-e "s|^LYNX =.*|LYNX = '${lynx}/bin/lynx'|" \
-e "s|^XMLLINT =.*|XMLLINT = '${libxml2.bin}/bin/xmllint'|" \
-e "s|^EPUBCHECK =.*|EPUBCHECK = '${epubcheck}/bin/epubcheck'|" \
-i asciidoc/a2x.py
''
else
''
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()))))|" \
-e "s|^XSLTPROC =.*|XSLTPROC = '${libxslt.bin}/bin/xsltproc'|" \
-e "s|^XMLLINT =.*|XMLLINT = '${libxml2.bin}/bin/xmllint'|" \
-i asciidoc/a2x.py
''
)
+ ''
# Fix tests
for f in $(grep -R --files-with-matches "2002-11-25") ; do
substituteInPlace $f --replace "2002-11-25" "1980-01-02"
substituteInPlace $f --replace "00:37:42" "00:00:00"
done
''
+ lib.optionalString (stdenv.buildPlatform != stdenv.hostPlatform) ''
# We want to use asciidoc from the build platform to build the documentation.
substituteInPlace Makefile.in \
--replace "python3 -m asciidoc.a2x" "${buildPackages.asciidoc}/bin/a2x"
'';
build-system = with python3.pythonOnBuildForHost.pkgs; [ setuptools ];
postBuild = ''
make manpages
'';
postInstall = ''
installManPage doc/asciidoc.1 doc/a2x.1 doc/testasciidoc.1
'';
nativeCheckInputs = with python3.pkgs; [
pytest
pytest-mock
];
checkPhase = ''
runHook preCheck
make test
runHook postCheck
'';
meta = {
description = "Text-based document generation system";
longDescription = ''
AsciiDoc is a text document format for writing notes, documentation,
articles, books, ebooks, slideshows, web pages, man pages and blogs.
AsciiDoc files can be translated to many formats including HTML, PDF,
EPUB, man page.
AsciiDoc is highly configurable: both the AsciiDoc source file syntax and
the backend output markups (which can be almost any type of SGML/XML
markup) can be customized and extended by the user.
'';
sourceProvenance = [
lib.sourceTypes.fromSource
]
++ lib.optional _enableDitaaFilter lib.sourceTypes.binaryBytecode;
homepage = "https://asciidoc-py.github.io/";
changelog = "https://github.com/asciidoc-py/asciidoc-py/blob/${version}/CHANGELOG.adoc";
license = lib.licenses.gpl2Plus;
platforms = lib.platforms.unix;
maintainers = with lib.maintainers; [
bjornfor
dotlambda
];
};
}

View File

@@ -0,0 +1,14 @@
source 'https://rubygems.org'
gem 'asciidoctor'
gem 'asciidoctor-bibtex'
gem 'asciidoctor-diagram'
gem 'asciidoctor-epub3'
gem 'asciidoctor-html5s'
gem 'asciidoctor-mathematical'
gem 'asciidoctor-multipage'
gem 'asciidoctor-pdf'
gem 'asciidoctor-reducer'
gem 'asciidoctor-revealjs'
gem 'coderay'
gem 'pygments.rb'
gem 'rouge'

View File

@@ -0,0 +1,154 @@
GEM
remote: https://rubygems.org/
specs:
Ascii85 (1.1.1)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
afm (0.2.2)
asciidoctor (2.0.23)
asciidoctor-bibtex (0.9.0)
asciidoctor (~> 2.0)
bibtex-ruby (~> 6.1)
citeproc-ruby (~> 1)
csl-styles (~> 1)
latex-decode (~> 0.2)
asciidoctor-diagram (2.3.1)
asciidoctor (>= 1.5.7, < 3.x)
asciidoctor-diagram-ditaamini (~> 1.0)
asciidoctor-diagram-plantuml (~> 1.2021)
rexml
asciidoctor-diagram-batik (1.17)
asciidoctor-diagram-ditaamini (1.0.3)
asciidoctor-diagram-plantuml (1.2024.6)
asciidoctor-diagram-batik (~> 1.17)
asciidoctor-epub3 (2.1.3)
asciidoctor (~> 2.0)
gepub (>= 1.0.0, <= 1.0.15)
mime-types (~> 3.0)
sass
asciidoctor-html5s (0.5.1)
asciidoctor (>= 1.5.7, < 3.0)
thread_safe (~> 0.3.4)
asciidoctor-mathematical (0.3.5)
asciidoctor (~> 2.0)
asciimath (~> 2.0)
mathematical (~> 1.6.0)
asciidoctor-multipage (0.0.19)
asciidoctor (>= 2.0.11, < 2.1)
asciidoctor-pdf (2.3.19)
asciidoctor (~> 2.0)
concurrent-ruby (~> 1.1)
matrix (~> 0.4)
prawn (~> 2.4.0)
prawn-icon (~> 3.0.0)
prawn-svg (~> 0.34.0)
prawn-table (~> 0.2.0)
prawn-templates (~> 0.1.0)
treetop (~> 1.6.0)
ttfunk (~> 1.7.0)
asciidoctor-reducer (1.0.6)
asciidoctor (~> 2.0)
asciidoctor-revealjs (5.1.0)
asciidoctor (>= 2.0.0, < 3.0.0)
asciimath (2.0.5)
bibtex-ruby (6.1.0)
latex-decode (~> 0.0)
racc (~> 1.7)
citeproc (1.0.10)
namae (~> 1.0)
citeproc-ruby (1.1.14)
citeproc (~> 1.0, >= 1.0.9)
csl (~> 1.6)
coderay (1.1.3)
concurrent-ruby (1.3.4)
csl (1.6.0)
namae (~> 1.0)
rexml
csl-styles (1.0.1.11)
csl (~> 1.0)
css_parser (1.19.1)
addressable
ffi (1.17.0)
gepub (1.0.15)
nokogiri (>= 1.8.2, < 2.0)
rubyzip (> 1.1.1, < 2.4)
hashery (2.1.2)
latex-decode (0.4.0)
logger (1.6.1)
mathematical (1.6.20)
ruby-enum (>= 0.4, < 2.0)
matrix (0.4.2)
mime-types (3.6.0)
logger
mime-types-data (~> 3.2015)
mime-types-data (3.2024.1001)
mini_portile2 (2.8.7)
namae (1.2.0)
racc (~> 1.7)
nokogiri (1.16.7)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
pdf-core (0.9.0)
pdf-reader (2.12.0)
Ascii85 (~> 1.0)
afm (~> 0.2.1)
hashery (~> 2.0)
ruby-rc4
ttfunk
polyglot (0.3.5)
prawn (2.4.0)
pdf-core (~> 0.9.0)
ttfunk (~> 1.7)
prawn-icon (3.0.0)
prawn (>= 1.1.0, < 3.0.0)
prawn-svg (0.34.2)
css_parser (~> 1.6)
matrix (~> 0.4.2)
prawn (>= 0.11.1, < 3)
rexml (~> 3.2)
prawn-table (0.2.2)
prawn (>= 1.3.0, < 3.0.0)
prawn-templates (0.1.2)
pdf-reader (~> 2.0)
prawn (~> 2.2)
public_suffix (6.0.1)
pygments.rb (3.0.0)
racc (1.8.1)
rb-fsevent (0.11.2)
rb-inotify (0.11.1)
ffi (~> 1.0)
rexml (3.3.9)
rouge (4.4.0)
ruby-enum (1.0.0)
ruby-rc4 (0.1.5)
rubyzip (2.3.2)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
thread_safe (0.3.6)
treetop (1.6.12)
polyglot (~> 0.3)
ttfunk (1.7.0)
PLATFORMS
ruby
DEPENDENCIES
asciidoctor
asciidoctor-bibtex
asciidoctor-diagram
asciidoctor-epub3
asciidoctor-html5s
asciidoctor-mathematical
asciidoctor-multipage
asciidoctor-pdf
asciidoctor-reducer
asciidoctor-revealjs
coderay
pygments.rb
rouge
BUNDLED WITH
2.5.16

View File

@@ -0,0 +1,46 @@
{
lib,
bundlerApp,
bundlerUpdateScript,
makeWrapper,
withJava ? true,
jre, # Used by asciidoctor-diagram for ditaa and PlantUML
}:
let
path = lib.makeBinPath (lib.optional withJava jre);
in
bundlerApp rec {
pname = "asciidoctor";
gemdir = ./.;
exes = [
"asciidoctor"
"asciidoctor-epub3"
"asciidoctor-multipage"
"asciidoctor-pdf"
"asciidoctor-reducer"
"asciidoctor-revealjs"
];
nativeBuildInputs = [ makeWrapper ];
postBuild = lib.optionalString (path != "") (
lib.concatMapStrings (exe: ''
wrapProgram $out/bin/${exe} \
--prefix PATH : ${path}
'') exes
);
passthru = {
updateScript = bundlerUpdateScript "asciidoctor-with-extensions";
};
meta = with lib; {
description = "Faster Asciidoc processor written in Ruby, with many extensions enabled";
homepage = "https://asciidoctor.org/";
license = licenses.mit;
maintainers = with maintainers; [ doronbehar ];
platforms = platforms.unix;
};
}

View File

@@ -0,0 +1,706 @@
{
addressable = {
dependencies = [ "public_suffix" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0cl2qpvwiffym62z991ynks7imsm87qmgxf0yfsmlwzkgi9qcaa6";
type = "gem";
};
version = "2.8.7";
};
afm = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "06kj9hgd0z8pj27bxp2diwqh6fv7qhwwm17z64rhdc4sfn76jgn8";
type = "gem";
};
version = "0.2.2";
};
Ascii85 = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1c62cx96r0v265mywnlik43qx0wf6bjbzl54qa47x6dzjg861mvk";
type = "gem";
};
version = "1.1.1";
};
asciidoctor = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1wyxgwmnz9bw377r3lba26b090hbsq9qnbw8575a1prpy83qh82j";
type = "gem";
};
version = "2.0.23";
};
asciidoctor-bibtex = {
dependencies = [
"asciidoctor"
"bibtex-ruby"
"citeproc-ruby"
"csl-styles"
"latex-decode"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "16l7s926h6cjzy4y582sf3x32l4w10klmdnphxi7p4g6d8vhb61y";
type = "gem";
};
version = "0.9.0";
};
asciidoctor-diagram = {
dependencies = [
"asciidoctor"
"asciidoctor-diagram-ditaamini"
"asciidoctor-diagram-plantuml"
"rexml"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1214scxm36k409gfy3wilfqx3akrm52r530zmra6cmmf6d22c5q4";
type = "gem";
};
version = "2.3.1";
};
asciidoctor-diagram-batik = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0220xqxmkmimxmhsqhlbr0hslijvnhzdds3s6h6fxbxqrrmm0jrl";
type = "gem";
};
version = "1.17";
};
asciidoctor-diagram-ditaamini = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "13h65bfbq7hc7z3kqn0m28w9c6ap7fikpjcvsdga6jg01slb4c56";
type = "gem";
};
version = "1.0.3";
};
asciidoctor-diagram-plantuml = {
dependencies = [ "asciidoctor-diagram-batik" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "173mp5vnzvn3yv9fw0p66rsbxaip9lhphw22yn19l62d1drlmhia";
type = "gem";
};
version = "1.2024.6";
};
asciidoctor-epub3 = {
dependencies = [
"asciidoctor"
"gepub"
"mime-types"
"sass"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1yn2nhr7fr5rx7fn0nhw44gf7iampiy53bw59agpfl7h2dyazjll";
type = "gem";
};
version = "2.1.3";
};
asciidoctor-html5s = {
dependencies = [
"asciidoctor"
"thread_safe"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1zfbfcqyrsk8bnd526ang3b4j3m5pbns7x3fdxarrm8vv1qplss1";
type = "gem";
};
version = "0.5.1";
};
asciidoctor-mathematical = {
dependencies = [
"asciidoctor"
"asciimath"
"mathematical"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1lxfq7qn3ql642pva6jh3h1abm9j9daxg5icfn1h73k6cjsmcisp";
type = "gem";
};
version = "0.3.5";
};
asciidoctor-multipage = {
dependencies = [ "asciidoctor" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1hjqqiibqrmx0147m8b372s57rmhixmpxgv4kwdpnkqbkqgykh7i";
type = "gem";
};
version = "0.0.19";
};
asciidoctor-pdf = {
dependencies = [
"asciidoctor"
"concurrent-ruby"
"matrix"
"prawn"
"prawn-icon"
"prawn-svg"
"prawn-table"
"prawn-templates"
"treetop"
"ttfunk"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1ybkw3xjv75xsc0wbwg76bk83sfspr50k2phshpvh9ynchli8jh3";
type = "gem";
};
version = "2.3.19";
};
asciidoctor-reducer = {
dependencies = [ "asciidoctor" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1fbrk97mdn26zk118dav2ckyiw6kgrlbkkhdcasawsl42hj16slw";
type = "gem";
};
version = "1.0.6";
};
asciidoctor-revealjs = {
dependencies = [ "asciidoctor" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0jgazcfzn577xlichfj0rvci0fayp63xcng11ss9mmwqgk48ri53";
type = "gem";
};
version = "5.1.0";
};
asciimath = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1ny2qql3lgh7gx54psji2lm4mmbwyiwy00a17w26rjyh6cy55491";
type = "gem";
};
version = "2.0.5";
};
bibtex-ruby = {
dependencies = [
"latex-decode"
"racc"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1ggx2j1gi46f1a6p45l1abk3nryfg1pj0cdlyrnilnqqpr1cfc96";
type = "gem";
};
version = "6.1.0";
};
citeproc = {
dependencies = [ "namae" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "13vl5sjmksk5a8kjcqnjxh7kn9gn1n4f9p1rvqfgsfhs54p0m6l2";
type = "gem";
};
version = "1.0.10";
};
citeproc-ruby = {
dependencies = [
"citeproc"
"csl"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0a8ahyhhmdinl4kcyv51r74ipnclmfyz4zjv366dns8v49n5vkk3";
type = "gem";
};
version = "1.1.14";
};
coderay = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0jvxqxzply1lwp7ysn94zjhh57vc14mcshw1ygw14ib8lhc00lyw";
type = "gem";
};
version = "1.1.3";
};
concurrent-ruby = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0chwfdq2a6kbj6xz9l6zrdfnyghnh32si82la1dnpa5h75ir5anl";
type = "gem";
};
version = "1.3.4";
};
csl = {
dependencies = [
"namae"
"rexml"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0n8iqmzvvqy2b1wfr4c7yj28x4z3zgm36628y8ybl49dgnmjycrk";
type = "gem";
};
version = "1.6.0";
};
csl-styles = {
dependencies = [ "csl" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0l29qlk7i74088fpba5iqhhgiqkj7glcmc42nbmvgqysx577nag8";
type = "gem";
};
version = "1.0.1.11";
};
css_parser = {
dependencies = [ "addressable" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "17i0fn99kswvfps8r698zw2cr16rc98xdrl0d26y36rv3vhdqh0r";
type = "gem";
};
version = "1.19.1";
};
ffi = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "07139870npj59jnl8vmk39ja3gdk3fb5z9vc0lf32y2h891hwqsi";
type = "gem";
};
version = "1.17.0";
};
gepub = {
dependencies = [
"nokogiri"
"rubyzip"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "08fny807zd4700f263ckc76bladjipsniyk3clv8a7x76x3fqshx";
type = "gem";
};
version = "1.0.15";
};
hashery = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0qj8815bf7q6q7llm5rzdz279gzmpqmqqicxnzv066a020iwqffj";
type = "gem";
};
version = "2.1.2";
};
latex-decode = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1y5xn3zwghpqr6lvs4s0mn5knms8zw3zk7jb58zkkiagb386nq72";
type = "gem";
};
version = "0.4.0";
};
logger = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0lwncq2rf8gm79g2rcnnyzs26ma1f4wnfjm6gs4zf2wlsdz5in9s";
type = "gem";
};
version = "1.6.1";
};
mathematical = {
dependencies = [ "ruby-enum" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0y103dvfjswm5r0xafyjrw6ybvz1qrqfa4lvpk9gdhbzwpaiwy4r";
type = "gem";
};
version = "1.6.20";
};
matrix = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1h2cgkpzkh3dd0flnnwfq6f3nl2b1zff9lvqz8xs853ssv5kq23i";
type = "gem";
};
version = "0.4.2";
};
mime-types = {
dependencies = [
"logger"
"mime-types-data"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0r34mc3n7sxsbm9mzyzy8m3dvq7pwbryyc8m452axkj0g2axnwbg";
type = "gem";
};
version = "3.6.0";
};
mime-types-data = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "06dbn0j13jwdrmlvrjd50mxqrjlkh3lvxp0afh4glyzbliqvqpsd";
type = "gem";
};
version = "3.2024.1001";
};
mini_portile2 = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1q1f2sdw3y3y9mnym9dhjgsjr72sq975cfg5c4yx7gwv8nmzbvhk";
type = "gem";
};
version = "2.8.7";
};
namae = {
dependencies = [ "racc" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "17fmp6p74ai2w984xayv3kz2nh44w81hqqvn4cfrim3g115wwh9m";
type = "gem";
};
version = "1.2.0";
};
nokogiri = {
dependencies = [
"mini_portile2"
"racc"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "15gysw8rassqgdq3kwgl4mhqmrgh7nk2qvrcqp4ijyqazgywn6gq";
type = "gem";
};
version = "1.16.7";
};
pdf-core = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1fz0yj4zrlii2j08kaw11j769s373ayz8jrdhxwwjzmm28pqndjg";
type = "gem";
};
version = "0.9.0";
};
pdf-reader = {
dependencies = [
"Ascii85"
"afm"
"hashery"
"ruby-rc4"
"ttfunk"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0n0pp7blk3np3fqsb54l34fsamrww80cp3dhlhskfayg7542mrv1";
type = "gem";
};
version = "2.12.0";
};
polyglot = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1bqnxwyip623d8pr29rg6m8r0hdg08fpr2yb74f46rn1wgsnxmjr";
type = "gem";
};
version = "0.3.5";
};
prawn = {
dependencies = [
"pdf-core"
"ttfunk"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1g9avv2rprsjisdk137s9ljr05r7ajhm78hxa1vjsv0jyx22f1l2";
type = "gem";
};
version = "2.4.0";
};
prawn-icon = {
dependencies = [ "prawn" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1xdnjik5zinnkjavmybbh2s52wzcpb8hzaqckiv0mxp0vs0x9j6s";
type = "gem";
};
version = "3.0.0";
};
prawn-svg = {
dependencies = [
"css_parser"
"matrix"
"prawn"
"rexml"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "143sfwadbdrgi57am8ikalryjijdyl82h2sdc1cns3wl6b9pkzxg";
type = "gem";
};
version = "0.34.2";
};
prawn-table = {
dependencies = [ "prawn" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1nxd6qmxqwl850icp18wjh5k0s3amxcajdrkjyzpfgq0kvilcv9k";
type = "gem";
};
version = "0.2.2";
};
prawn-templates = {
dependencies = [
"pdf-reader"
"prawn"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1w9irn3rllm992c6j7fsx81gg539i7yy8zfddyw7q53hnlys0yhi";
type = "gem";
};
version = "0.1.2";
};
public_suffix = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0vqcw3iwby3yc6avs1vb3gfd0vcp2v7q310665dvxfswmcf4xm31";
type = "gem";
};
version = "6.0.1";
};
"pygments.rb" = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "14xhvfnj188pypy6pxj29hrn60pznv6dc4ycdgyd6jv2d769wwj1";
type = "gem";
};
version = "3.0.0";
};
racc = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0byn0c9nkahsl93y9ln5bysq4j31q8xkf2ws42swighxd4lnjzsa";
type = "gem";
};
version = "1.8.1";
};
rb-fsevent = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1zmf31rnpm8553lqwibvv3kkx0v7majm1f341xbxc0bk5sbhp423";
type = "gem";
};
version = "0.11.2";
};
rb-inotify = {
dependencies = [ "ffi" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0vmy8xgahixcz6hzwy4zdcyn2y6d6ri8dqv5xccgzc1r292019x0";
type = "gem";
};
version = "0.11.1";
};
rexml = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1j9p66pmfgxnzp76ksssyfyqqrg7281dyi3xyknl3wwraaw7a66p";
type = "gem";
};
version = "3.3.9";
};
rouge = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0r0b48945hakgy0y7lg6h1bb7pkfz8jqd0r6777f80ij3sansvbs";
type = "gem";
};
version = "4.4.0";
};
ruby-enum = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1ry6ha94a5jqbj5y3x9k0szyy3jgnsfyxvva98nivg6yx1dfyrz7";
type = "gem";
};
version = "1.0.0";
};
ruby-rc4 = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "00vci475258mmbvsdqkmqadlwn6gj9m01sp7b5a3zd90knil1k00";
type = "gem";
};
version = "0.1.5";
};
rubyzip = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0grps9197qyxakbpw02pda59v45lfgbgiyw48i0mq9f2bn9y6mrz";
type = "gem";
};
version = "2.3.2";
};
sass = {
dependencies = [ "sass-listen" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0p95lhs0jza5l7hqci1isflxakz83xkj97lkvxl919is0lwhv2w0";
type = "gem";
};
version = "3.7.4";
};
sass-listen = {
dependencies = [
"rb-fsevent"
"rb-inotify"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0xw3q46cmahkgyldid5hwyiwacp590zj2vmswlll68ryvmvcp7df";
type = "gem";
};
version = "4.0.0";
};
thread_safe = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0nmhcgq6cgz44srylra07bmaw99f5271l0dpsvl5f75m44l0gmwy";
type = "gem";
};
version = "0.3.6";
};
treetop = {
dependencies = [ "polyglot" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0adc8qblz8ii668r3rksjx83p675iryh52rvdvysimx2hkbasj7d";
type = "gem";
};
version = "1.6.12";
};
ttfunk = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "15iaxz9iak5643bq2bc0jkbjv8w2zn649lxgvh5wg48q9d4blw13";
type = "gem";
};
version = "1.7.0";
};
}

View File

@@ -0,0 +1,7 @@
source 'https://rubygems.org'
gem 'asciidoctor'
gem 'asciidoctor-pdf'
gem 'coderay'
gem 'pygments.rb'
gem 'rouge'
gem 'tilt'

View File

@@ -0,0 +1,71 @@
GEM
remote: https://rubygems.org/
specs:
Ascii85 (1.1.1)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
afm (0.2.2)
asciidoctor (2.0.23)
asciidoctor-pdf (2.3.19)
asciidoctor (~> 2.0)
concurrent-ruby (~> 1.1)
matrix (~> 0.4)
prawn (~> 2.4.0)
prawn-icon (~> 3.0.0)
prawn-svg (~> 0.34.0)
prawn-table (~> 0.2.0)
prawn-templates (~> 0.1.0)
treetop (~> 1.6.0)
ttfunk (~> 1.7.0)
coderay (1.1.3)
concurrent-ruby (1.3.4)
css_parser (1.19.1)
addressable
hashery (2.1.2)
matrix (0.4.2)
pdf-core (0.9.0)
pdf-reader (2.12.0)
Ascii85 (~> 1.0)
afm (~> 0.2.1)
hashery (~> 2.0)
ruby-rc4
ttfunk
polyglot (0.3.5)
prawn (2.4.0)
pdf-core (~> 0.9.0)
ttfunk (~> 1.7)
prawn-icon (3.0.0)
prawn (>= 1.1.0, < 3.0.0)
prawn-svg (0.34.2)
css_parser (~> 1.6)
matrix (~> 0.4.2)
prawn (>= 0.11.1, < 3)
rexml (~> 3.2)
prawn-table (0.2.2)
prawn (>= 1.3.0, < 3.0.0)
prawn-templates (0.1.2)
pdf-reader (~> 2.0)
prawn (~> 2.2)
public_suffix (6.0.1)
pygments.rb (3.0.0)
rexml (3.3.9)
rouge (4.4.0)
ruby-rc4 (0.1.5)
tilt (2.4.0)
treetop (1.6.12)
polyglot (~> 0.3)
ttfunk (1.7.0)
PLATFORMS
ruby
DEPENDENCIES
asciidoctor
asciidoctor-pdf
coderay
pygments.rb
rouge
tilt
BUNDLED WITH
2.5.16

View File

@@ -0,0 +1,30 @@
{
lib,
bundlerApp,
bundlerUpdateScript,
}:
bundlerApp {
pname = "asciidoctor";
gemdir = ./.;
exes = [
"asciidoctor"
"asciidoctor-pdf"
];
passthru = {
updateScript = bundlerUpdateScript "asciidoctor";
};
meta = with lib; {
description = "Faster Asciidoc processor written in Ruby";
homepage = "https://asciidoctor.org/";
license = licenses.mit;
maintainers = with maintainers; [
gpyh
nicknovitski
];
platforms = platforms.unix;
};
}

View File

@@ -0,0 +1,300 @@
{
addressable = {
dependencies = [ "public_suffix" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0cl2qpvwiffym62z991ynks7imsm87qmgxf0yfsmlwzkgi9qcaa6";
type = "gem";
};
version = "2.8.7";
};
afm = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "06kj9hgd0z8pj27bxp2diwqh6fv7qhwwm17z64rhdc4sfn76jgn8";
type = "gem";
};
version = "0.2.2";
};
Ascii85 = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1c62cx96r0v265mywnlik43qx0wf6bjbzl54qa47x6dzjg861mvk";
type = "gem";
};
version = "1.1.1";
};
asciidoctor = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1wyxgwmnz9bw377r3lba26b090hbsq9qnbw8575a1prpy83qh82j";
type = "gem";
};
version = "2.0.23";
};
asciidoctor-pdf = {
dependencies = [
"asciidoctor"
"concurrent-ruby"
"matrix"
"prawn"
"prawn-icon"
"prawn-svg"
"prawn-table"
"prawn-templates"
"treetop"
"ttfunk"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1ybkw3xjv75xsc0wbwg76bk83sfspr50k2phshpvh9ynchli8jh3";
type = "gem";
};
version = "2.3.19";
};
coderay = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0jvxqxzply1lwp7ysn94zjhh57vc14mcshw1ygw14ib8lhc00lyw";
type = "gem";
};
version = "1.1.3";
};
concurrent-ruby = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0chwfdq2a6kbj6xz9l6zrdfnyghnh32si82la1dnpa5h75ir5anl";
type = "gem";
};
version = "1.3.4";
};
css_parser = {
dependencies = [ "addressable" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "17i0fn99kswvfps8r698zw2cr16rc98xdrl0d26y36rv3vhdqh0r";
type = "gem";
};
version = "1.19.1";
};
hashery = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0qj8815bf7q6q7llm5rzdz279gzmpqmqqicxnzv066a020iwqffj";
type = "gem";
};
version = "2.1.2";
};
matrix = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1h2cgkpzkh3dd0flnnwfq6f3nl2b1zff9lvqz8xs853ssv5kq23i";
type = "gem";
};
version = "0.4.2";
};
pdf-core = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1fz0yj4zrlii2j08kaw11j769s373ayz8jrdhxwwjzmm28pqndjg";
type = "gem";
};
version = "0.9.0";
};
pdf-reader = {
dependencies = [
"Ascii85"
"afm"
"hashery"
"ruby-rc4"
"ttfunk"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0n0pp7blk3np3fqsb54l34fsamrww80cp3dhlhskfayg7542mrv1";
type = "gem";
};
version = "2.12.0";
};
polyglot = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1bqnxwyip623d8pr29rg6m8r0hdg08fpr2yb74f46rn1wgsnxmjr";
type = "gem";
};
version = "0.3.5";
};
prawn = {
dependencies = [
"pdf-core"
"ttfunk"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1g9avv2rprsjisdk137s9ljr05r7ajhm78hxa1vjsv0jyx22f1l2";
type = "gem";
};
version = "2.4.0";
};
prawn-icon = {
dependencies = [ "prawn" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1xdnjik5zinnkjavmybbh2s52wzcpb8hzaqckiv0mxp0vs0x9j6s";
type = "gem";
};
version = "3.0.0";
};
prawn-svg = {
dependencies = [
"css_parser"
"matrix"
"prawn"
"rexml"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "143sfwadbdrgi57am8ikalryjijdyl82h2sdc1cns3wl6b9pkzxg";
type = "gem";
};
version = "0.34.2";
};
prawn-table = {
dependencies = [ "prawn" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1nxd6qmxqwl850icp18wjh5k0s3amxcajdrkjyzpfgq0kvilcv9k";
type = "gem";
};
version = "0.2.2";
};
prawn-templates = {
dependencies = [
"pdf-reader"
"prawn"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1w9irn3rllm992c6j7fsx81gg539i7yy8zfddyw7q53hnlys0yhi";
type = "gem";
};
version = "0.1.2";
};
public_suffix = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0vqcw3iwby3yc6avs1vb3gfd0vcp2v7q310665dvxfswmcf4xm31";
type = "gem";
};
version = "6.0.1";
};
"pygments.rb" = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "14xhvfnj188pypy6pxj29hrn60pznv6dc4ycdgyd6jv2d769wwj1";
type = "gem";
};
version = "3.0.0";
};
rexml = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1j9p66pmfgxnzp76ksssyfyqqrg7281dyi3xyknl3wwraaw7a66p";
type = "gem";
};
version = "3.3.9";
};
rouge = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0r0b48945hakgy0y7lg6h1bb7pkfz8jqd0r6777f80ij3sansvbs";
type = "gem";
};
version = "4.4.0";
};
ruby-rc4 = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "00vci475258mmbvsdqkmqadlwn6gj9m01sp7b5a3zd90knil1k00";
type = "gem";
};
version = "0.1.5";
};
tilt = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0kds7wkxmb038cwp6ravnwn8k65ixc68wpm8j5jx5bhx8ndg4x6z";
type = "gem";
};
version = "2.4.0";
};
treetop = {
dependencies = [ "polyglot" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0adc8qblz8ii668r3rksjx83p675iryh52rvdvysimx2hkbasj7d";
type = "gem";
};
version = "1.6.12";
};
ttfunk = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "15iaxz9iak5643bq2bc0jkbjv8w2zn649lxgvh5wg48q9d4blw13";
type = "gem";
};
version = "1.7.0";
};
}

View File

@@ -0,0 +1,2 @@
source 'https://rubygems.org'
gem 'kramdown-asciidoc'

View File

@@ -0,0 +1,21 @@
GEM
remote: https://rubygems.org/
specs:
kramdown (2.4.0)
rexml
kramdown-asciidoc (2.1.0)
kramdown (~> 2.4.0)
kramdown-parser-gfm (~> 1.1.0)
rexml (~> 3.2.0)
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
rexml (3.2.6)
PLATFORMS
ruby
DEPENDENCIES
kramdown-asciidoc
BUNDLED WITH
2.4.22

View File

@@ -0,0 +1,40 @@
{
lib,
bundlerApp,
makeWrapper,
# Optional dependencies, can be null
epubcheck,
bundlerUpdateScript,
}:
let
app = bundlerApp {
pname = "kramdown-asciidoc";
gemdir = ./.;
exes = [
"kramdoc"
];
# nativeBuildInputs = [ makeWrapper ];
# postBuild = ''
# wrapProgram "$out/bin/asciidoctor-epub3" \
# ${lib.optionalString (epubcheck != null) "--set EPUBCHECK ${epubcheck}/bin/epubcheck"}
# '';
# passthru = {
# updateScript = bundlerUpdateScript "kramdown-asciidoc";
# };
meta = with lib; {
description = "Kramdown extension for converting Markdown documents to AsciiDoc";
homepage = "https://asciidoctor.org/";
license = licenses.mit;
maintainers = [ ];
platforms = platforms.unix;
mainProgram = "kramdoc";
};
};
in
app

View File

@@ -0,0 +1,49 @@
{
kramdown = {
dependencies = [ "rexml" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1ic14hdcqxn821dvzki99zhmcy130yhv5fqfffkcf87asv5mnbmn";
type = "gem";
};
version = "2.4.0";
};
kramdown-asciidoc = {
dependencies = [
"kramdown"
"kramdown-parser-gfm"
"rexml"
];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "1j7qbpq6zhgcf9ykhz5r1wlr3r8fls6hvhdisxzz4v35rni5kwp9";
type = "gem";
};
version = "2.1.0";
};
kramdown-parser-gfm = {
dependencies = [ "kramdown" ];
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "0a8pb3v951f4x7h968rqfsa19c8arz21zw1vaj42jza22rap8fgv";
type = "gem";
};
version = "1.1.0";
};
rexml = {
groups = [ "default" ];
platforms = [ ];
source = {
remotes = [ "https://rubygems.org" ];
sha256 = "05i8518ay14kjbma550mv0jm8a6di8yp5phzrd8rj44z9qnrlrp0";
type = "gem";
};
version = "3.2.6";
};
}

View File

@@ -0,0 +1,82 @@
{
fetchurl,
lib,
makeWrapper,
writeShellScriptBin,
ghostscriptX,
ocamlPackages,
texliveMedium,
which,
}:
let
# simplified fake-opam edited from tweag's opam-nix
fake-opam = writeShellScriptBin "opam" ''
case "$1 $2" in
"config var")
case "$3" in
man) echo "$out/share/man";;
etc) echo "$out/etc";;
doc) echo "$out/share/doc";;
share) echo "$out/share";;
prefix) echo "$out";;
*) echo "fake-opam does not understand arguments: $@" ; exit 1 ;;
esac;;
*) echo "fake-opam does not understand arguments: $@" ; exit 1 ;;
esac
'';
# texlive currently does not symlink kpsexpand
kpsexpand = writeShellScriptBin "kpsexpand" ''
exec kpsetool -v
'';
in
ocamlPackages.buildDunePackage rec {
pname = "advi";
version = "2.0.0";
minimalOCamlVersion = "4.11";
src = fetchurl {
url = "http://advi.inria.fr/advi-${version}.tar.gz";
hash = "sha256-c0DQHlvdekJyXCxmR4+Ut/njtoCzmqX6hNazNv8PpBQ=";
};
postPatch = ''
substituteInPlace ./Makefile \
--replace "\$(DUNE) install \$(DUNEROOT) --display=short" \
"\$(DUNE) install \$(DUNEROOT) --prefix $out --docdir $out/share/doc --mandir $out/share/man"
substituteInPlace ./src/discover.sh \
--replace 'gs_path=$(which gs)' 'gs_path=${ghostscriptX}/bin/gs'
'';
duneVersion = "3";
nativeBuildInputs = [
fake-opam
kpsexpand
makeWrapper
texliveMedium
which
];
buildInputs = with ocamlPackages; [
camlimages
ghostscriptX
graphics
];
# install additional files (such as man pages)
preInstall = ''
make install
'';
# TODO: redirect /share/advi/tex/latex to tex output compatible with texlive.combine
# (requires patching check() in advi-latex-files)
meta = with lib; {
homepage = "http://advi.inria.fr/";
description = "Unix-platform DVI previewer and a programmable presenter for slides written in LaTeX";
license = licenses.lgpl21Only;
maintainers = [ maintainers.xworld21 ];
};
}

View File

@@ -0,0 +1,7 @@
mkdir -p $out
for ((i = 1; i <= $nrFrames; i++)); do
echo "producing frame $i...";
targetName=$out/$(basename $(stripHash $dotGraph) .dot)-f-$i.dot
cpp -DFRAME=$i < $dotGraph > $targetName
done

View File

@@ -0,0 +1,43 @@
use strict;
use File::Basename;
sub createDirs;
sub createDirs {
my $path = shift;
return unless $path =~ /^(.*)\/([^\/]*)$/;
my $dir = $1;
return if -d $dir;
return if -e $dir;
createDirs $dir;
mkdir $dir or die "cannot create directory `$dir'";
}
my $maxParents = 0;
for (my $n = 0; $n < @ARGV; $n += 2) {
my $fullPath = $ARGV[$n];
my $relPath = $ARGV[$n + 1];
my $parents = 0;
foreach my $comp (split /\//, $relPath) {
$parents++ if ($comp eq "..")
}
$maxParents = $parents if $parents > $maxParents;
}
my $startDir = "./";
for (my $n = 0; $n < $maxParents; $n++) {
$startDir .= "dotdot/";
mkdir "$startDir" or die "cannot create directory `$startDir': $!";
}
chdir $startDir or die;
for (my $n = 0; $n < @ARGV; $n += 2) {
my $fullPath = $ARGV[$n];
my $relPath = $ARGV[$n + 1];
createDirs $relPath;
symlink $fullPath, $relPath or die "cannot create symlink `$relPath'";
}
print "$startDir\n";

View File

@@ -0,0 +1,310 @@
pkgs:
rec {
runLaTeX =
{
rootFile,
generatePDF ? true, # generate PDF, not DVI
generatePS ? false, # generate PS in addition to DVI
extraFiles ? [ ],
compressBlanksInIndex ? true,
packages ? [ ],
texPackages ? { },
copySources ? false,
}:
assert generatePDF -> !generatePS;
let
tex =
pkgs.texlive.combine
# always include basic stuff you need for LaTeX
({ inherit (pkgs.texlive) scheme-basic; } // texPackages);
in
pkgs.stdenv.mkDerivation {
name = "doc";
builder = ./run-latex.sh;
copyIncludes = ./copy-includes.pl;
inherit
rootFile
generatePDF
generatePS
extraFiles
compressBlanksInIndex
copySources
;
includes =
map
(x: [
x.key
(baseNameOf (toString x.key))
])
(findLaTeXIncludes {
inherit rootFile;
});
buildInputs = [
tex
pkgs.perl
]
++ packages;
};
# Returns the closure of the "dependencies" of a LaTeX source file.
# Dependencies are other LaTeX source files (e.g. included using
# \input{}), images (e.g. \includegraphics{}), bibliographies, and
# so on.
findLaTeXIncludes =
{
rootFile,
}:
builtins.genericClosure {
startSet = [ { key = rootFile; } ];
operator =
{ key, ... }:
let
# `find-includes.pl' returns the dependencies of the current
# source file (`key') as a list, e.g. [{type = "tex"; name =
# "introduction.tex";} {type = "img"; name = "example"}].
# The type denotes the kind of dependency, which determines
# what extensions we use to look for it.
deps = import (
pkgs.runCommand "latex-includes" {
rootFile = baseNameOf (toString rootFile);
src = key;
} "${pkgs.perl}/bin/perl ${./find-includes.pl}"
);
# Look for the dependencies of `key', trying various
# extensions determined by the type of each dependency.
# TODO: support a search path.
foundDeps =
dep: xs:
let
exts =
if dep.type == "img" then
[
".pdf"
".png"
".ps"
".jpg"
]
else if dep.type == "tex" then
[
".tex"
""
]
else
[ "" ];
fn = pkgs.lib.findFirst (fn: builtins.pathExists fn) null (
map (ext: dirOf key + ("/" + dep.name + ext)) exts
);
in
if fn != null then [ { key = fn; } ] ++ xs else xs;
in
pkgs.lib.foldr foundDeps [ ] deps;
};
findLhs2TeXIncludes =
{
lib,
rootFile,
}:
builtins.genericClosure {
startSet = [ { key = rootFile; } ];
operator =
{ key, ... }:
let
deps = import (
pkgs.runCommand "lhs2tex-includes" {
src = key;
} "${pkgs.stdenv.bash}/bin/bash ${./find-lhs2tex-includes.sh}"
);
in
pkgs.lib.concatMap (x: lib.optionals (builtins.pathExists x) [ { key = x; } ]) (
map (x: dirOf key + ("/" + x)) deps
);
};
dot2pdf =
{
dotGraph,
}:
pkgs.stdenv.mkDerivation {
name = "pdf";
builder = ./dot2pdf.sh;
inherit dotGraph fontsConf;
buildInputs = [
pkgs.perl
pkgs.graphviz
];
};
dot2ps =
{
dotGraph,
}:
pkgs.stdenv.mkDerivation {
name = "ps";
builder = ./dot2ps.sh;
inherit dotGraph;
buildInputs = [
pkgs.perl
pkgs.graphviz
pkgs.ghostscript
];
};
lhs2tex =
{
source,
flags ? null,
}:
pkgs.stdenv.mkDerivation {
name = "tex";
builder = ./lhs2tex.sh;
inherit source flags;
buildInputs = [
pkgs.lhs2tex
pkgs.perl
];
copyIncludes = ./copy-includes.pl;
includes =
map
(x: [
x.key
(baseNameOf (toString x.key))
])
(findLhs2TeXIncludes {
rootFile = source;
});
};
animateDot =
dotGraph: nrFrames:
pkgs.stdenv.mkDerivation {
name = "dot-frames";
builder = ./animatedot.sh;
inherit dotGraph nrFrames;
};
# Wrap a piece of TeX code in a document. Useful when generating
# inline images from TeX code.
wrapSimpleTeX =
{
preamble ? null,
body,
name ? baseNameOf (toString body),
}:
pkgs.stdenv.mkDerivation {
inherit name preamble body;
buildCommand = ''
touch $out
echo '\documentclass{article}' >> $out
echo '\pagestyle{empty}' >> $out
if test -n "$preamble"; then cat $preamble >> $out; fi
echo '\begin{document}' >> $out
cat $body >> $out
echo '\end{document}' >> $out
'';
};
# Convert a Postscript file to a PNG image, trimming it so that
# there is no unnecessary surrounding whitespace.
postscriptToPNG =
{
postscript,
}:
pkgs.stdenv.mkDerivation {
name = "png";
inherit postscript;
buildInputs = [
pkgs.imagemagick
pkgs.ghostscript
];
buildCommand = ''
if test -d $postscript; then
input=$(ls $postscript/*.ps)
else
input=$(stripHash $postscript)
ln -s $postscript $input
fi
mkdir -p $out
convert -units PixelsPerInch \
-density 600 \
-trim \
-matte \
-transparent '#ffffff' \
-type PaletteMatte \
+repage \
$input \
"$out/$(basename $input .ps).png"
''; # */
};
# Convert a piece of TeX code to a PNG image.
simpleTeXToPNG =
{
preamble ? null,
body,
packages ? [ ],
}:
postscriptToPNG {
postscript = runLaTeX {
rootFile = wrapSimpleTeX {
inherit body preamble;
};
inherit packages;
generatePDF = false;
generatePS = true;
};
};
# Convert a piece of TeX code to a PDF.
simpleTeXToPDF =
{
preamble ? null,
body,
packages ? [ ],
}:
runLaTeX {
rootFile = wrapSimpleTeX {
inherit body preamble;
};
inherit packages;
};
# Some tools (like dot) need a fontconfig configuration file.
# This should be extended to allow the called to add additional
# fonts.
fontsConf = pkgs.makeFontsConf {
fontDirectories = [
"${pkgs.ghostscript.fonts}/share/fonts"
];
};
}

View File

@@ -0,0 +1,18 @@
mkdir -p $out
dot2pdf() {
sourceFile=$1
targetName=$out/$(basename $(stripHash $sourceFile) .dot).pdf
echo "converting $sourceFile to $targetName..."
export FONTCONFIG_FILE=$fontsConf
dot -Tpdf $sourceFile > $targetName
}
for i in $dotGraph; do
if test -d $i; then
for j in $i/*; do dot2pdf $j; done
else
dot2pdf $i
fi
done

View File

@@ -0,0 +1,17 @@
mkdir -p $out
dot2ps() {
sourceFile=$1
targetName=$out/$(basename $(stripHash $sourceFile) .dot).ps
echo "converting $sourceFile to $targetName..."
dot -Tps $sourceFile > $targetName
}
for i in $dotGraph; do
if test -d $i; then
for j in $i/*; do dot2ps $j; done
else
dot2ps $i
fi
done

View File

@@ -0,0 +1,69 @@
use strict;
use File::Basename;
my $src = $ENV{"src"};
my $out = $ENV{"out"};
my $path = $ENV{"searchRelativeTo"};
open OUT, ">$out" or die;
print OUT "[\n";
open FILE, "< $src" or die;
sub addName {
my ($type, $name) = @_;
print OUT "{ type = \"$type\"; name = \"$name\"; }\n";
}
while (<FILE>) {
if (/\\input\{(.*)\}/) {
my $fn2 = $1;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "tex", "$fn2";
} elsif (/\\input (.*)$/) {
my $fn2 = $1;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "tex", "$fn2";
} elsif (/\\RequirePackage(\[.*\])?\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "misc", "$fn2.sty";
} elsif (/\\usepackage(\[.*\])?\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "misc", "$fn2.sty";
} elsif (/\\documentclass(\[.*\])?\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "misc", "$fn2.cls";
} elsif (/\\bibliographystyle\{(.*)\}/) {
my $fn2 = $1;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "misc", "$fn2.bst";
} elsif (/\\bibliography\{(.*)\}/) {
foreach my $bib (split /,/, $1) {
$bib =~ s/^\s+//; # remove leading / trailing whitespace
$bib =~ s/\s+$//;
addName "misc", "$bib.bib";
addName "misc", (basename($ENV{"rootFile"}, ".tex", ".ltx") . ".bbl");
}
} elsif (/\\includegraphics(\[.*\])?\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "img", "$fn2";
} elsif (/\\pgfdeclareimage(\[.*\])?\{.*\}\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "img", "$fn2";
} elsif (/\\pgfimage(\[.*\])?\{(.*)\}/) {
my $fn2 = $2;
die "absolute path! $fn2" if substr($fn2, 0, 1) eq "/";
addName "img", "$fn2";
}
# !!! also support \usepackage
}
close FILE;
print OUT "]\n";
close OUT;

View File

@@ -0,0 +1,3 @@
echo '[' > $out
grep '^%include ' $src | cut -d ' ' -f 2 | sed 's/^\(.*\)$/"\1"/' >> $out
echo ']' >> $out

View File

@@ -0,0 +1,17 @@
mkdir -p $out
mkdir root
cd root
startDir=$(perl $copyIncludes $includes)
cd $startDir
lhstex() {
sourceFile=$1
targetName=$out/$(basename $(stripHash $sourceFile) .lhs).tex
echo "converting $sourceFile to $targetName..."
lhs2TeX -o "$targetName" $flags "$sourceFile"
}
lhstex $source

View File

@@ -0,0 +1,162 @@
mkdir -p $out
export VARTEXFONTS=$TMPDIR/texfonts
export TEXMFCNF=$TMPDIR:
echo 'max_print_line = 8192' >> $TMPDIR/texmf.cnf
mkdir root
cd root
startDir=$(perl $copyIncludes $includes)
cd $startDir
for i in $extraFiles; do
if test -d $i; then
ln -s $i/* .
else
ln -s $i $(stripHash $i)
fi
done
rootName=$(basename $(stripHash "$rootFile"))
rootNameBase=$(echo "$rootName" | sed 's/\..*//')
if test -n "$generatePDF"; then
latex=pdflatex
else
latex=latex
fi
latexFlags="-file-line-error"
tmpFile=$out/log
showError() {
echo
echo "LATEX ERROR (LAST LOG LINES SHOWN):"
tail -n 20 $tmpFile
bzip2 $tmpFile
exit 1
}
pass=0
runLaTeX() {
((pass=pass+1))
echo "PASS $pass..."
if ! $latex $latexFlags $rootName >$tmpFile 2>&1; then showError; fi
runNeeded=
if fgrep -q \
-e "LaTeX Warning: Label(s) may have changed." \
-e "Rerun to get citations correct." \
-e "Please rerun LaTeX." \
"$tmpFile"; then
runNeeded=1
fi
echo
}
echo
if test -n "$copySources"; then
cp -prd $TMPDIR/root $out/tex-srcs
fi
runLaTeX
for auxFile in $(find . -name "*.aux"); do
# Run bibtex to process all bibliographies. There may be several
# when we're using the multibib package.
if grep -q '\\citation' $auxFile; then
auxBase=$(basename $auxFile .aux)
if [ -e $auxBase.bbl ]; then
echo "SKIPPING BIBTEX ON $auxFile!"
else
echo "RUNNING BIBTEX ON $auxFile..."
bibtex --terse $auxBase
cp $auxBase.bbl $out
runNeeded=1
fi
echo
fi
# "\pgfsyspdfmark" in the aux file seems to indicate that PGF/TikZ
# requires a second run (e.g. to resolve arrows between pictures).
if grep -q pgfsyspdfmark $auxFile; then
runNeeded=1
fi
done
if test "$runNeeded"; then
runLaTeX
fi
if test -f $rootNameBase.idx; then
echo "MAKING INDEX..."
if test -n "$compressBlanksInIndex"; then
appendToVar makeindexFlags "-c"
fi
makeindex $makeindexFlags $rootNameBase.idx
runNeeded=1
echo
fi
# We check that pass is less than 2 to catch situations where the document is
# simple enough (no bibtex, etc.) so that it would otherwise require only one
# pass but also contains a ToC.
# In essence this check ensures that we do at least two passes on all documents.
if test "$runNeeded" = 1 -o "$pass" -lt 2 ; then
runLaTeX
fi
if test "$runNeeded"; then
runLaTeX
fi
if test "$runNeeded"; then
echo "Hm, still not done :-("
echo
fi
if test -n "$generatePDF"; then
cp $rootNameBase.pdf $out
else
cp $rootNameBase.dvi $out
if test -n "$generatePS"; then
echo "CONVERTING TO POSTSCRIPT..."
dvips $rootNameBase.dvi -o $out/$rootNameBase.ps
echo
fi
fi
echo "WARNINGS:"
cat $tmpFile | grep "Warning:" | grep -v "Citation.*undefined" || true
echo
echo "OVERFULL/UNDERFULL:"
cat $tmpFile | egrep "Overfull|Underfull" || true
echo
echo "UNDEFINED REFERENCES:"
cat $tmpFile | grep "Reference.*undefined" || true
echo
echo "UNDEFINED CITATIONS:"
cat $tmpFile | grep "Citation.*undefined" || true
echo
echo "STATS:"
printf "%5d overfull/underfull h/vboxes\n" $(cat $tmpFile | egrep -c "Overfull|Underfull" || true)
printf "%5d undefined references\n" $(cat $tmpFile | grep -c "Reference.*undefined" || true)
printf "%5d undefined citations\n" $(cat $tmpFile | grep -c "Citation.*undefined" || true)
printf "%5d pages\n" \
$(cat $tmpFile | grep "Output written.*(.*pages" | sed "s/.*(\([0-9]*\) pages.*/\1/" || true)
echo
bzip2 $tmpFile

View File

@@ -0,0 +1,13 @@
diff --git a/texk/ps2pkm/type1.c b/texk/ps2pkm/type1.c
index 027bf1f..4dcbad0 100644
--- a/texk/ps2pkm/type1.c
+++ b/texk/ps2pkm/type1.c
@@ -800,7 +800,7 @@ static void PSFakePush(Num)
static DOUBLE PSFakePop ()
{
if (PSFakeTop >= 0) return(PSFakeStack[PSFakeTop--]);
- else Error0("PSFakePop : Stack empty\n");
+ else { CC; IfTrace0(TRUE, "PSFakePop : Stack empty\n"); errflag = TRUE; return 0; }
/*NOTREACHED*/
}

View File

@@ -0,0 +1,95 @@
{
lib,
stdenv,
fetchurl,
flex,
bison,
zlib,
libpng,
ncurses,
ed,
automake,
}:
stdenv.mkDerivation rec {
pname = "tetex";
version = "3.0";
src = fetchurl {
url = "http://mirrors.ctan.org/obsolete/systems/unix/teTeX/${version}/distrib/tetex-src-${version}.tar.gz";
sha256 = "16v44465ipd9yyqri9rgxp6rbgs194k4sh1kckvccvdsnnp7w3ww";
};
texmf = fetchurl {
url = "http://mirrors.ctan.org/obsolete/systems/unix/teTeX/${version}/distrib/tetex-texmf-${version}.tar.gz";
sha256 = "1hj06qvm02a2hx1a67igp45kxlbkczjlg20gr8lbp73l36k8yfvc";
};
buildInputs = [
flex
bison
zlib
libpng
ncurses
ed
];
hardeningDisable = [ "format" ];
# fixes "error: conflicting types for 'calloc'", etc.
preBuild = lib.optionalString stdenv.hostPlatform.isDarwin ''
sed -i 57d texk/kpathsea/c-std.h
'';
preConfigure =
if stdenv.hostPlatform.isCygwin then
''
find ./ -name "config.guess" -exec rm {} \; -exec ln -s ${automake}/share/automake-*/config.guess {} \;
''
else
null;
patches = [
./environment.patch
./getline.patch
./clang.patch
./extramembot.patch
];
setupHook = ./setup-hook.sh;
env = {
CFLAGS = "-std=gnu89";
CXXFLAGS = "-std=c++03";
};
configureFlags = [
"--disable-multiplatform"
"--without-x11"
"--without-xdvik"
"--without-oxdvik"
"--without-texinfo"
"--without-texi2html"
"--with-system-zlib"
"--with-system-pnglib"
"--with-system-ncurses"
]
# couldn't get gsftopk working on darwin
++ lib.optional stdenv.hostPlatform.isDarwin "--without-gsftopk";
postUnpack = ''
mkdir -p $out/share/texmf
mkdir -p $out/share/texmf-dist
gunzip < $texmf | (cd $out/share/texmf-dist && tar xvf -)
substituteInPlace ./tetex-src-3.0/configure --replace /usr/bin/install $(type -P install)
'';
meta = with lib; {
description = "Full-featured (La)TeX distribution";
homepage = "http://www.tug.org/tetex/";
maintainers = with maintainers; [ lovek323 ];
platforms = platforms.unix;
hydraPlatforms = [ ];
};
}

View File

@@ -0,0 +1,35 @@
diff -rc --exclude=texmf.in tetex-src-3.0.orig/texk/kpathsea/texmf.in-teTeX tetex-src-3.0/texk/kpathsea/texmf.in-teTeX
*** tetex-src-3.0.orig/texk/kpathsea/texmf.in-teTeX 2006-01-27 17:33:11.000000000 +0100
--- tetex-src-3.0/texk/kpathsea/texmf.in-teTeX 2006-01-27 17:38:35.000000000 +0100
***************
*** 104,109 ****
--- 104,115 ----
% TEXMFCONFIG = @texmf@-config
TEXMFCONFIG = $HOME/.texmf-config
+ % TEXMFNIX is supposed to be unset. It's used by the Nix
+ % system to add trees during the build of nix-expressions.
+
+ % TEXMFNIXHOME, for packages in the user environment.
+ TEXMFNIXHOME = $HOME/.nix-profile/share/texmf-nix
+
% Now, list all the texmf trees. If you have multiple trees you can
% use shell brace notation, like this:
% TEXMF = {$TEXMFHOME,!!$TEXMFLOCAL,!!$TEXMFMAIN}
***************
*** 111,117 ****
%
% For texconfig to work properly, TEXMFCONGIG and TEXMFVAR should be named
% explicitly and before all other trees.
! TEXMF = {!!$TEXMFCONFIG,!!$TEXMFVAR,$TEXMFHOME,!!$TEXMFSYSCONFIG,!!$TEXMFSYSVAR,!!$TEXMFMAIN,!!$TEXMFLOCAL,!!$TEXMFDIST}
% The system trees. These are the trees that are shared by all the users.
SYSTEXMF = $TEXMFLOCAL;$TEXMFMAIN;$TEXMFDIST
--- 117,123 ----
%
% For texconfig to work properly, TEXMFCONGIG and TEXMFVAR should be named
% explicitly and before all other trees.
! TEXMF = {!!$TEXMFCONFIG,!!$TEXMFVAR,$TEXMFNIX,$TEXMFHOME,$TEXMFNIXHOME,!!$TEXMFSYSCONFIG,!!$TEXMFSYSVAR,!!$TEXMFMAIN,!!$TEXMFLOCAL,!!$TEXMFDIST}
% The system trees. These are the trees that are shared by all the users.
SYSTEXMF = $TEXMFLOCAL;$TEXMFMAIN;$TEXMFDIST

View File

@@ -0,0 +1,12 @@
diff -up texlive-2007/texk/web2c/tex.ch.extramembot texlive-2007/texk/web2c/tex.ch
--- texlive-2007/texk/web2c/tex.ch.extramembot 2006-12-19 02:11:11.000000000 +0100
+++ texlive-2007/texk/web2c/tex.ch 2011-11-30 12:03:32.052795763 +0100
@@ -365,7 +365,7 @@ for i:=@'177 to @'377 do xchr[i]:=i;
{Initialize enc\TeX\ data.}
for i:=0 to 255 do mubyte_read[i]:=null;
for i:=0 to 255 do mubyte_write[i]:=0;
-for i:=0 to 128 do mubyte_cswrite[i]:=null;
+for i:=0 to 127 do mubyte_cswrite[i]:=null;
mubyte_keep := 0; mubyte_start := false;
write_noexpanding := false; cs_converting := false;
special_printing := false; message_printing := false;

View File

@@ -0,0 +1,96 @@
Glibc 2.10 has a `getline' symbol that clashes with teTeX's.
Taken from http://lists.ibiblio.org/pipermail/sm-commit/2009-July/024831.html
diff -rc -x '*~' tetex-src-3.0-orig/texk/dvipsk/afm2tfm.c tetex-src-3.0/texk/dvipsk/afm2tfm.c
*** tetex-src-3.0-orig/texk/dvipsk/afm2tfm.c 2005-01-30 14:17:09.000000000 +0100
--- tetex-src-3.0/texk/dvipsk/afm2tfm.c 2010-02-03 13:50:21.000000000 +0100
***************
*** 257,263 ****
}
int
! getline P1H(void) {
register char *p ;
register int c ;
--- 257,263 ----
}
int
! tetex_getline P1H(void) {
register char *p ;
register int c ;
***************
*** 606,612 ****
ai = newchar() ;
ai->adobenum = -1 ;
ai->adobename = "||" ; /* boundary character name */
! while (getline()) {
switch(interest(paramstring())) {
case FontName:
fontname = paramnewstring() ;
--- 606,612 ----
ai = newchar() ;
ai->adobenum = -1 ;
ai->adobename = "||" ; /* boundary character name */
! while (tetex_getline()) {
switch(interest(paramstring())) {
case FontName:
fontname = paramnewstring() ;
***************
*** 1882,1888 ****
while (1) {
while (param == 0 || *param == 0) {
! if (getline() == 0)
error("! premature end in encoding file") ;
for (p=buffer; *p; p++)
if (*p == '%') {
--- 1882,1888 ----
while (1) {
while (param == 0 || *param == 0) {
! if (tetex_getline() == 0)
error("! premature end in encoding file") ;
for (p=buffer; *p; p++)
if (*p == '%') {
***************
*** 1973,1979 ****
p = gettoken() ;
if (strcmp(p, "]"))
error("! token 258 in encoding must be make-array (])") ;
! while (getline()) {
for (p=buffer; *p; p++)
if (*p == '%') {
if (ignoreligkern == 0)
--- 1973,1979 ----
p = gettoken() ;
if (strcmp(p, "]"))
error("! token 258 in encoding must be make-array (])") ;
! while (tetex_getline()) {
for (p=buffer; *p; p++)
if (*p == '%') {
if (ignoreligkern == 0)
diff -rc -x '*~' tetex-src-3.0-orig/texk/web2c/cpascal.h tetex-src-3.0/texk/web2c/cpascal.h
*** tetex-src-3.0-orig/texk/web2c/cpascal.h 2004-08-28 22:49:59.000000000 +0200
--- tetex-src-3.0/texk/web2c/cpascal.h 2010-02-03 13:51:04.000000000 +0100
***************
*** 240,245 ****
--- 240,255 ----
#undef getname
#define getname vms_getname
#endif
+
+ /* Apparently POSIX 2008 has getline and glibc 2.9.90 exports it.
+ * tangle, weave, et al. use that symbol; try to define it away so
+ * something that a standard won't usurp.
+ * From http://tutimura.ath.cx/ptetex/?%C6%B0%BA%EE%CA%F3%B9%F0%2F134 */
+ #ifdef getline
+ #undef getline
+ #endif
+ #define getline web2c_getline
+
/* Declarations for the routines we provide ourselves in lib/. */

View File

@@ -0,0 +1,7 @@
addTeXMFPath () {
if test -d "$1/share/texmf-nix"; then
export TEXINPUTS="${TEXINPUTS}${TEXINPUTS:+:}$1/share/texmf-nix//:"
fi
}
addEnvHooks "$targetOffset" addTeXMFPath

View File

@@ -0,0 +1,139 @@
# Notes on maintaining/upgrading
## Upgrading `texlive.bin`
`texlive` contains a few binaries, defined in `bin.nix` and released once a year.
In order to reduce closure size for users who just need a few of them, we split it into
packages such as `core`, `core-big`, `xdvi`, etc. This requires making assumptions
about dependencies between the projects that may change between releases; if
you upgrade you may have to do some work here.
## Updating the package set
`texlive` contains several thousand packages from CTAN, defined in `tlpdb.nix`.
The CTAN mirrors are not version-controlled and continuously moving,
with more than 100 updates per month.
To create a consistent and reproducible package set in nixpkgs, we generate nix
expressions for all packages in TeX Live at a certain day.
To upgrade the package snapshot, follow this process.
### Upgrade package information from texlive package database
Update `version` in `default.nix` with the day of the new snapshot, the new TeX
Live year, and the final status of the snapshot. Then update
`texlive.tlpdbxz.hash` to match the new hash of `texlive.tlpdb.xz` and run
```bash
nix-build ../../../../.. -A texlive.tlpdb.nix --no-out-link
```
This will download either the daily or the final snapshot of the TeX Live
package database `texlive.tlpdb.xz` and extract the relevant package info
(including version numbers and sha512 hashes) for the selected upstream
distribution.
Finally, replace `tlpdb.nix` with the generated file. Note that if the
`version` info does not match the metadata of `tlpdb.nix` (as found in the
`00texlive.config` package), TeX Live packages will not evaluate.
The test `pkgs.tests.texlive.tlpdbNix` verifies that the file `tlpdb.nix`
in Nixpkgs matches the one that generated from `texlive.tlpdb.xz`.
### Build packages locally and generate fix hashes
To prevent unnecessary rebuilds, texlive packages are built as fixed-output
derivations whose hashes are contained in `fixed-hashes.nix`.
Updating the list of fixed hashes requires a local build of all new packages,
which is a resource-intensive process. First build the hashes for the new
packages. Consider tweaking the `-j` option to maximise core usage.
```bash
nix-build generate-fixed-hashes.nix -A newHashes -j 8
```
Then build the Nix expression containing all the hashes, old and new. This step
cannot be parallelized because it relies on 'import from derivation'.
```bash
nix-build generate-fixed-hashes.nix -A fixedHashesNix
```
Finally, copy the result to `fixed-hashes.nix`.
**Warning.** The expression `fixedHashesNix` reuses the *previous* fixed hashes
when possible. This is based on two assumptions: that `.tar.xz` archives with
the same names remain identical in time (which is the intended behaviour of
CTAN and the various mirrors) and that the build recipe continues to produce
the same output. Should those assumptions not hold, remove the previous fixed
hashes for the relevant package, or for all packages.
### Upgrading the ConTeXt binaries
ConTeXt in TeX Live is packaged as described
[here](https://github.com/gucci-on-fleek/context-packaging). With every update
to the ConTeXt package, the LuaMetaTeX compiler also needs to be updated. For
this, we fetch the source from the releases of the above repo. Make sure to
update this in `texlive.bin.context`, when updating TeX Live.
### Updating the licensing information
The license of each package in texlive is automatically extracted from texlive's
texlive.tlpdb into tlpdb.nix. The combined licenses of the schemes is stored
separately in `default.nix` and must be kept in sync with the licenses of the
actual contents of these schemes. Whether this is the case can be verified with the
`pkgs.tests.texlive.licenses` test. In case of a mismatch, copy the “correct”
license lists reported by the test into `default.nix`.
### Running the testsuite
There are a some other useful tests that haven't been mentioned before. Build them with
```
nix-build ../../../../.. -A tests.texlive --no-out-link
```
### Commit changes
Commit the updated `tlpdb.nix` and `fixed-hashes.nix` to the repository with
a message like
> texlive: 2022-final -> 2023.20230401
Please make sure to follow the [CONTRIBUTING](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md)
guidelines.
## Reviewing the bin containers
Most `tlType == "bin"` containers consist of links to scripts distributed in
`$TEXMFDIST/scripts` with a number of patches applied within `default.nix`.
At each upgrade, please run the tests `tests.texlive.shebangs` to verify that
all shebangs have been patched and in case add the relevant interpreters, and
use `tests.texlive.binaries` to check if basic execution of all binaries works.
Please review manually all binaries in the `broken` and `ignored` lists of
`tests.texlive.binaries` at least once for major TeX Live release.
Since the tests cannot catch all runtime dependencies, you should grep the
`$TEXMFDIST/scripts` folder for common cases, for instance (where `$scripts`
points to the relevant folder of `scheme-full`):
- Calls to `exec $interpreter`
```
grep -IRS 'exec ' "$TEXMFDIST/scripts" | cut -d: -f2 | sort -u | less -S
```
- Calls to Ghostscripts (see `needsGhostscript` in `combine.nix`)
```
grep -IR '\([^a-zA-Z]\|^\)gs\( \|$\|"\)' "$TEXMFDIST"/scripts
grep -IR 'rungs' "$TEXMFDIST"
```
As a general rule, if a runtime dependency as above is essential for the core
functionality of the package, then it should be made available in the bin
containers (by patching `PATH`), or in `texlive.combine` (as we do for
Ghostscript). Non-essential runtime dependencies should be ignored if they
increase the closure substantially.

View File

@@ -0,0 +1,832 @@
{
lib,
stdenv,
fetchurl,
fetchzip,
fetchFromGitHub,
fetchpatch,
buildPackages,
texlive,
zlib,
libiconv,
libpng,
libX11,
freetype,
ttfautohint,
gd,
libXaw,
icu,
ghostscript,
libXpm,
libXmu,
libXext,
perl,
perlPackages,
python3Packages,
pkg-config,
cmake,
ninja,
libpaper,
graphite2,
zziplib,
harfbuzz,
potrace,
gmp,
mpfr,
mupdf-headless,
brotli,
cairo,
pixman,
xorg,
clisp,
biber,
woff2,
xxHash,
makeWrapper,
shortenPerlShebang,
useFixedHashes,
asymptote,
biber-ms,
tlpdb,
luajit,
}@args:
# Useful resource covering build options:
# http://tug.org/texlive/doc/tlbuild.html
let
withSystemLibs = map (libname: "--with-system-${libname}");
year = toString ((import ./tlpdb.nix)."00texlive.config").year;
version = year; # keep names simple for now
# detect and stop redundant rebuilds that may occur when building new fixed hashes
assertFixedHash =
name: src:
if !useFixedHashes || src ? outputHash then
src
else
throw "The TeX Live package '${src.pname}' must have a fixed hash before building '${name}'.";
# list of packages whose binaries are built in core, core-big
# generated manually by inspecting ${core}/bin
corePackages = [
"afm2pl"
"aleph"
"autosp"
"axodraw2"
"bibtex"
"cjkutils"
"ctie"
"cweb"
"detex"
"dtl"
"dvi2tty"
"dvicopy"
"dvidvi"
"dviljk"
"dviout-util"
"dvipdfmx"
"dvipos"
"dvips"
"fontware"
"gregoriotex"
"gsftopk"
"hitex"
"kpathsea"
"lacheck"
"lcdftypetools"
"m-tx"
"makeindex"
"mfware"
"musixtnt"
"omegaware"
"patgen"
"pdftex"
"pdftosrc"
"pmx"
"ps2eps"
"ps2pk"
"psutils"
"ptex"
"seetexk"
"synctex"
"t1utils"
"tex"
"tex4ht"
"texlive-scripts-extra"
"texware"
"tie"
"tpic2pdftex"
"ttfutils"
"uptex"
"velthuis"
"vlna"
"web"
"xml2pmx"
];
coreBigPackages = [
"metafont"
"mflua"
"metapost"
"luatex"
"luahbtex"
"upmendex"
"xetex"
]
++ lib.optional withLuaJIT "luajittex";
binPackages = lib.getAttrs (corePackages ++ coreBigPackages) tlpdb;
common = {
src = fetchurl {
urls = [
"http://ftp.math.utah.edu/pub/tex/historic/systems/texlive/${year}/texlive-${year}0308-source.tar.xz"
"ftp://tug.ctan.org/pub/tex/historic/systems/texlive/${year}/texlive-${year}0308-source.tar.xz"
];
hash = "sha256-//2xo9FDwXekOYoiKaQNaojxgJjl9tz9V2SMnyQXSQ8=";
};
prePatch = ''
for i in texk/kpathsea/mktex*; do
sed -i '/^mydir=/d' "$i"
done
# ST_NLINK_TRICK causes kpathsea to treat folders with no real subfolders
# as leaves, even if they contain symlinks to other folders; must be
# disabled to work correctly with the nix store", see section 5.3.6
# Subdirectory expansion of the kpathsea manual
# http://mirrors.ctan.org/systems/doc/kpathsea/kpathsea.pdf for more
# details
sed -i '/^#define ST_NLINK_TRICK/d' texk/kpathsea/config.h
''
+
# when cross compiling, we must use himktables from PATH
# (i.e. from buildPackages.texlive.bin.core.dev)
lib.optionalString (!stdenv.buildPlatform.canExecute stdenv.hostPlatform) ''
sed -i 's|\./himktables|himktables|' texk/web2c/Makefile.in
'';
configureFlags = [
"--with-banner-add=/nixos.org"
"--disable-missing"
# terminate if a requested program or feature must be
# disabled, e.g., due to missing libraries
"--disable-native-texlive-build" # do not build for the TeX Live binary distribution
"--enable-shared" # "--enable-cxx-runtime-hack" # static runtime
"--enable-tex-synctex"
"--disable-texlive" # do not build the texlive (TeX Live scripts) package
"--disable-linked-scripts" # do not install the linked scripts
"-C" # use configure cache to speed up
]
++ withSystemLibs [
# see "from TL tree" vs. "Using installed" in configure output
"zziplib"
"mpfr"
"gmp"
"pixman"
"potrace"
"gd"
"freetype2"
"libpng"
"libpaper"
"zlib"
]
++ lib.optional (
stdenv.hostPlatform != stdenv.buildPlatform
) "BUILDCC=${buildPackages.stdenv.cc.targetPrefix}cc";
# move binaries to corresponding split outputs, based on content of texlive.tlpdb
binToOutput = lib.listToAttrs (
lib.concatMap (
n:
map (v: {
name = v;
value = builtins.replaceStrings [ "-" ] [ "_" ] n;
}) binPackages.${n}.binfiles or [ ]
) (builtins.attrNames binPackages)
);
moveBins = ''
for bin in "$out/bin"/* ; do
bin="''${bin##*/}"
package="''${binToOutput[$bin]}"
if [[ -n "$package" ]] ; then
if [[ -z "''${!package}" ]] ; then
echo "WARNING: missing output '$package' for binary '$bin', leaving in 'out'"
else
mkdir -p "''${!package}"/bin
mv "$out/bin/$bin" "''${!package}"/bin/
if [[ -e "$out/share/texmf-dist/scripts/$bin" ]] ; then
mkdir -p "''${!package}"/share/texmf-dist/scripts
mv "$out/share/texmf-dist/scripts/$bin" "''${!package}"/share/texmf-dist/scripts/
fi
fi
else
echo "WARNING: no output known for binary '$bin', leaving in 'out'"
fi
done
'';
};
# RISC-V: https://github.com/LuaJIT/LuaJIT/issues/628
withLuaJIT = lib.meta.availableOn stdenv.hostPlatform luajit;
in
rec {
# un-indented
texliveYear = year;
core = stdenv.mkDerivation rec {
pname = "texlive-bin";
inherit version;
__structuredAttrs = true;
inherit (common) binToOutput src prePatch;
outputs = [
"out"
"dev"
"man"
"info"
]
++ (map (builtins.replaceStrings [ "-" ] [ "_" ]) corePackages);
nativeBuildInputs = [
pkg-config
]
++ lib.optionals (!stdenv.buildPlatform.canExecute stdenv.hostPlatform) (
with texlive.bin.core;
[
# configure: error: tangle was not found but is required when cross-compiling.
# dev (himktables) is used when building hitex to generate the additional source file hitables.c
web # tangle
cweb # ctangle
omegaware # otangle
tie # tie see "Building TeX Live" 6.4.2 Cross problems
dev # himktables
]
);
buildInputs = [
# teckit
zziplib
mpfr
gmp
pixman
gd
freetype
libpng
libpaper
zlib
perl
];
hardeningDisable = [ "format" ];
preConfigure = ''
rm -r libs/{cairo,freetype2,gd,gmp,graphite2,harfbuzz,icu,libpaper,libpng} \
libs/{lua53,luajit,mpfr,pixman,pplib,teckit,zlib,zziplib} \
texk/{bibtex-x,chktex,dvipng,dvisvgm,upmendex,xdvik} \
utils/{asymptote,texdoctk,xindy,xpdfopen}
mkdir WorkDir
cd WorkDir
'';
configureScript = "../configure";
depsBuildBuild = [ buildPackages.stdenv.cc ];
configureFlags =
common.configureFlags
++ [ "--without-x" ] # disable xdvik and xpdfopen
++ map (what: "--disable-${what}") [
"chktex"
"dvisvgm"
"dvipng" # ghostscript dependency
"luatex"
"luajittex"
"luahbtex"
"luajithbtex"
"mp"
"pmp"
"upmp"
"mf"
"mflua"
"mfluajit" # cairo would bring in X and more
"xetex"
"bibtexu"
"bibtex8"
"bibtex-x"
"upmendex" # ICU isn't small
];
enableParallelBuilding = true;
doCheck = false; # triptest fails, likely due to missing TEXMF tree
preCheck = "patchShebangs ../texk/web2c";
installTargets = [ "install" ];
# TODO: perhaps improve texmf.cnf search locations
postInstall =
# install himktables in separate output for use in cross compilation
''
mkdir -p $dev/bin
cp texk/web2c/.libs/himktables $dev/bin/himktables
''
+ common.moveBins
# remove redundant texmf-dist (content provided by TeX Live packages)
+ ''
rm -frv "$out"/share/texmf-dist
mkdir -p "${placeholder "psutils"}"/share/texmf-dist/scripts/psutils
cp texk/psutils/{extractres.pl,includeres.pl,psjoin.pl} "${placeholder "psutils"}"/share/texmf-dist/scripts/psutils
''
# remove broken symlinks
+ ''
rm "$out"/bin/{eptex,ptex,uptex}
rm "${placeholder "ptex"}"/bin/{pbibtex,pdvitype,ppltotf,ptftopl}
'';
passthru = { inherit version buildInputs; };
meta = with lib; {
description = "Basic binaries for TeX Live";
homepage = "http://www.tug.org/texlive";
license = lib.licenses.gpl2Plus;
maintainers = with maintainers; [
veprbl
lovek323
raskin
jwiegley
];
platforms = platforms.all;
};
};
inherit (core-big)
metafont
mflua
metapost
luatex
luahbtex
xetex
;
luajittex = core.big.luajittex or null;
core-big = stdenv.mkDerivation {
pname = "texlive-bin-big";
inherit version;
__structuredAttrs = true;
inherit (common) binToOutput src prePatch;
patches = [
# improves reproducibility of fmt files
# see discussion at https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1009196
(fetchpatch {
name = "lua_fixed_hash.patch";
url = "https://bugs.debian.org/cgi-bin/bugreport.cgi?att=1;bug=1009196;filename=lua_fixed_hash.patch;msg=45";
sha256 = "sha256-FTu1eRd3AUU7IRs2/7e7uwHuvZsrzTBPypbcEZkU7y4=";
})
# The original LuaJIT version number used here is 2.1.1736781742.
# The patch number in this is the unix epoch timestamp of the commit used.
# TexLive already truncates the patch number to the last 5 digits (81742
# in this case), however, this number will roll over every 1.1 days (1e5
# seconds), making it non-monotonic.
# Furthermore, the nix-darwin linker requires version numbers to be <=
# 1023.
# We therefore opt to choose a 3-digit sequence from the unix epoch that
# gives a good tradeoff between when it will roll over, and how often it
# will actually change: digits 9-7 (counting from the right, i.e., 736 in
# this case) yields a number that changes every 11.6 days (1e6 seconds,
# it is unlikely texlive will be updated on a shorter interval), and will
# stay stable for 31.7 years (1e9 seconds).
./truncate-luajit-version-number.patch
];
hardeningDisable = [ "format" ];
inherit (core) nativeBuildInputs depsBuildBuild;
buildInputs = core.buildInputs ++ [
core
cairo
harfbuzz
icu
graphite2
libX11
potrace
];
/*
deleting the unused packages speeds up configure by a considerable margin
and ensures we do not rebuild existing libraries by mistake
*/
preConfigure = ''
rm -r libs/{cairo,freetype2,gd,gmp,graphite2,harfbuzz,icu,libpaper,libpng} \
libs/{mpfr,pixman,xpdf,zlib,zziplib} \
texk/{afm2pl,bibtex-x,chktex,cjkutils,detex,dtl,dvi2tty,dvidvi,dviljk,dviout-util} \
texk/{dvipdfm-x,dvipng,dvipos,dvipsk,dvisvgm,gregorio,gsftopk,kpathsea} \
texk/{lcdf-typetools,makeindexk,makejvf,mendexk,musixtnt,ps2pk,psutils,ptexenc} \
texk/{seetexk,tex4htk,texlive,ttf2pk2,ttfdump,xdvik} \
utils/{asymptote,autosp,axodraw2,devnag,lacheck,m-tx,pmx,ps2eps,t1utils,texdoctk} \
utils/{tpic2pdftex,vlna,xindy,xml2pmx,xpdfopen}
mkdir WorkDir
cd WorkDir
''
# force XeTeX to use fontconfig instead of Core Text, so that fonts can be made available via FONTCONFIG_FILE,
# by tricking configure into thinking that the relevant test result is already in the config cache
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
export kpse_cv_have_ApplicationServices=no
'';
configureFlags =
common.configureFlags
++ withSystemLibs [
"kpathsea"
"ptexenc"
"cairo"
"harfbuzz"
"icu"
"graphite2"
]
++
map (prog: "--disable-${prog}") # don't build things we already have
# list from texk/web2c/configure
(
[
"tex"
"ptex"
"eptex"
"uptex"
"euptex"
"aleph"
"hitex"
"pdftex"
"web-progs"
"synctex"
]
++ lib.optionals (!withLuaJIT) [
"luajittex"
"luajithbtex"
"mfluajit"
]
)
# disable all packages, re-enable upmendex, web2c packages
++ [
"--disable-all-pkgs"
"--enable-upmendex"
"--enable-web2c"
]
# kpathsea requires specifying the kpathsea location manually
++ [ "--with-kpathsea-includes=${core.dev}/include" ];
configureScript = "../configure";
enableParallelBuilding = true;
doCheck = false; # fails
outputs = [
"out"
"dev"
"man"
"info"
]
++ (map (builtins.replaceStrings [ "-" ] [ "_" ]) coreBigPackages)
# some outputs of metapost, omegaware are for ptex/uptex
++ [
"ptex"
"uptex"
]
# unavoidable duplicates from core
++ [
"ctie"
"cweb"
"omegaware"
"texlive_scripts_extra"
"tie"
"web"
];
postInstall = common.moveBins;
};
chktex = stdenv.mkDerivation {
pname = "chktex";
inherit (texlive.pkgs.chktex) version;
inherit (common) src;
nativeBuildInputs = [ pkg-config ];
# perl used in shebang of script bin/deweb
buildInputs = [
core # kpathsea
perl
];
preConfigure = "cd texk/chktex";
configureFlags = common.configureFlags ++ [ "--with-system-kpathsea" ];
enableParallelBuilding = true;
};
# The LuaMetaTeX engine (distributed since TeX Live 2023) must be built separately.
# For details on how TeX Live packages ConTeXt, see
# https://github.com/gucci-on-fleek/context-packaging
context =
let
# The latest release of the context-packaging repo before the CTAN version in tlpdb.nix
# https://github.com/gucci-on-fleek/context-packaging
context_packaging_release = "2025-06-12-14-21-B";
in
stdenv.mkDerivation {
pname = "luametatex";
version = "2.11.07";
src = fetchzip {
name = "luametatex.src.zip";
url = "https://github.com/gucci-on-fleek/context-packaging/releases/download/${context_packaging_release}/luametatex.src.zip";
hash = "sha256-9TLTIUSqA3g8QP9EF+tQ4VfLLLQwMrbeXPPy58uFWDo=";
stripRoot = false;
};
enableParallelBuilding = true;
nativeBuildInputs = [
cmake
ninja
];
meta = with lib; {
description = "LUAMETATEX engine is a follow up on LUATEX and is again part of CONTEXT development";
homepage = "https://www.pragma-ade.nl/luametatex-1.htm";
license = licenses.gpl2Plus;
maintainers = with lib.maintainers; [
apfelkuchen6
xworld21
];
};
};
dvisvgm = stdenv.mkDerivation rec {
pname = "dvisvgm";
version = "3.2.2";
src =
assert lib.assertMsg (version == texlive.pkgs.dvisvgm.version)
"dvisvgm: TeX Live version (${texlive.pkgs.dvisvgm.version}) different from source (${version}), please update dvisvgm";
fetchurl {
url = "https://github.com/mgieseki/dvisvgm/releases/download/${version}/dvisvgm-${version}.tar.gz";
hash = "sha256-8GKL6lqjMUXXWwpqbdGPrYibdSc4y8AcGUGPNUc6HQA=";
};
configureFlags = [
"--disable-manpage" # man pages are provided by the doc container
"--with-ttfautohint"
];
# PDF handling requires mutool (from mupdf) since Ghostscript 10.01
postPatch = ''
substituteInPlace src/PDFHandler.cpp \
--replace-fail 'Process("mutool"' "Process(\"$(PATH="$HOST_PATH" command -v mutool)\""
'';
nativeBuildInputs = [ pkg-config ];
buildInputs = [
core
brotli
ghostscript
zlib
freetype
ttfautohint
woff2
potrace
xxHash
mupdf-headless
];
enableParallelBuilding = true;
};
dvipng = stdenv.mkDerivation {
pname = "dvipng";
inherit (texlive.pkgs.dvipng) version;
inherit (common) src;
nativeBuildInputs = [
perl
pkg-config
makeWrapper
];
buildInputs = [
core # kpathsea
zlib
libpng
freetype
gd
ghostscript
];
preConfigure = ''
cd texk/dvipng
patchShebangs doc/texi2pod.pl
'';
configureFlags = common.configureFlags ++ [
"--with-system-kpathsea"
"--with-gs=yes"
"--disable-debug"
];
GS = "${ghostscript}/bin/gs";
enableParallelBuilding = true;
};
pygmentex = python3Packages.buildPythonApplication rec {
pname = "pygmentex";
inherit (src) version;
format = "other";
src = assertFixedHash pname texlive.pkgs.pygmentex.tex;
propagatedBuildInputs = with python3Packages; [
pygments
chardet
];
dontBuild = true;
doCheck = false;
installPhase = ''
runHook preInstall
install -D ./scripts/pygmentex/pygmentex.py "$out"/bin/pygmentex
runHook postInstall
'';
meta = with lib; {
homepage = "https://www.ctan.org/pkg/pygmentex";
description = "Auxiliary tool for typesetting code listings in LaTeX documents using Pygments";
longDescription = ''
PygmenTeX is a Python-based LaTeX package that can be used for
typesetting code listings in a LaTeX document using Pygments.
Pygments is a generic syntax highlighter for general use in all kinds of
software such as forum systems, wikis or other applications that need to
prettify source code.
'';
license = licenses.lppl13c;
maintainers = with maintainers; [ romildo ];
};
};
asymptote = args.asymptote.overrideAttrs (
finalAttrs: prevAttrs: {
version = texlive.pkgs.asymptote.version;
# keep local src and patches even if duplicated in the top level asymptote
# so that top level updates do not break texlive
src = fetchurl {
url = "mirror://sourceforge/asymptote/${finalAttrs.version}/asymptote-${finalAttrs.version}.src.tgz";
hash = "sha256-+T0n2SX9C8Mz0Fb+vkny1x+TWETC+NN67MjfD+6Twys=";
};
texContainer = texlive.pkgs.asymptote.tex;
texdocContainer = texlive.pkgs.asymptote.texdoc;
# build issue with asymptote 2.95 has been fixed
postConfigure = "";
}
);
inherit biber;
inherit biber-ms;
bibtexu = bibtex8;
bibtex8 = stdenv.mkDerivation {
pname = "bibtex-x";
inherit (texlive.pkgs.bibtexu) version;
inherit (common) src;
nativeBuildInputs = [ pkg-config ];
buildInputs = [
core # kpathsea
icu
];
preConfigure = "cd texk/bibtex-x";
configureFlags = common.configureFlags ++ [
"--with-system-kpathsea"
"--with-system-icu"
];
enableParallelBuilding = true;
};
xdvi = stdenv.mkDerivation {
pname = "xdvi";
inherit (texlive.pkgs.xdvi) version;
inherit (common) src;
nativeBuildInputs = [ pkg-config ];
buildInputs = [
core # kpathsea
freetype
ghostscript
]
++ (with xorg; [
libX11
libXaw
libXi
libXpm
libXmu
libXaw
libXext
libXfixes
]);
preConfigure = "cd texk/xdvik";
configureFlags = common.configureFlags ++ [
"--with-system-kpathsea"
"--with-system-libgs"
];
enableParallelBuilding = true;
postInstall = ''
substituteInPlace "$out/bin/xdvi" \
--replace-fail "exec xdvi-xaw" "exec '$out/bin/xdvi-xaw'"
'';
# TODO: it's suspicious that mktexpk generates fonts into ~/.texlive2014
};
xpdfopen = stdenv.mkDerivation {
pname = "xpdfopen";
inherit (texlive.pkgs.xpdfopen) version;
inherit (common) src;
buildInputs = [ libX11 ];
preConfigure = "cd utils/xpdfopen";
enableParallelBuilding = true;
};
} # un-indented
//
lib.optionalAttrs (!clisp.meta.broken) # broken on aarch64 and darwin (#20062)
{
xindy = stdenv.mkDerivation {
pname = "xindy";
inherit (texlive.pkgs.xindy) version;
inherit (common) src;
# If unset, xindy will try to mkdir /homeless-shelter
HOME = ".";
prePatch = "cd utils/xindy";
# hardcode clisp location
postPatch = ''
substituteInPlace xindy-*/user-commands/xindy.in \
--replace-fail "our \$clisp = ( \$is_windows ? 'clisp.exe' : 'clisp' ) ;" \
"our \$clisp = '$(type -P clisp)';" \
--replace-fail 'die "$cmd: Cannot locate xindy modules directory";' \
'$modules_dir = "${texlive.pkgs.xindy.tex}/xindy/modules"; die "$cmd: Cannot locate xindy modules directory" unless -d $modules_dir;'
'';
nativeBuildInputs = [
pkg-config
perl
];
buildInputs = [
clisp
libiconv
perl
];
configureFlags = [
"--with-clisp-runtime=system"
"--disable-xindy-docs"
"--disable-xindy-rules"
];
preInstall = ''mkdir -p "$out/bin" '';
# fixup various file-location errors of: lib/xindy/{xindy.mem,modules/}
postInstall = ''
mkdir -p "$out/lib/xindy"
mv "$out"/{bin/xindy.mem,lib/xindy/}
'';
};
}

View File

@@ -0,0 +1,487 @@
{
# texlive package set
tl,
bin,
lib,
buildEnv,
libfaketime,
makeFontsConf,
makeWrapper,
runCommand,
writeShellScript,
writeText,
toTLPkgSets,
bash,
perl,
# common runtime dependencies
coreutils,
gawk,
gnugrep,
gnused,
ghostscript,
}:
lib.fix (
self:
{
withDocs ? false,
withSources ? false,
requiredTeXPackages ? ps: [ ps.scheme-infraonly ],
### texlive.combine backward compatibility
__extraName ? "combined",
__extraVersion ? "",
# emulate the old texlive.combine (e.g. add man pages to main output)
__combine ? false,
# adjust behavior further if called from the texlive.combine wrapper
__fromCombineWrapper ? false,
# build only the formats of a package (for internal use!)
__formatsOf ? null,
}@args:
let
### buildEnv with custom attributes
buildEnv' =
args:
(
buildEnv { inherit (args) name paths; }
// lib.optionalAttrs (args ? extraOutputsToInstall) { inherit (args) extraOutputsToInstall; }
).overrideAttrs
(
removeAttrs args [
"extraOutputsToInstall"
"name"
"paths"
"pkgs"
]
);
### texlive.combine backward compatibility
# if necessary, convert old style { pkgs = [ ... ]; } packages to attribute sets
isOldPkgList = p: !p.outputSpecified or false && p ? pkgs && builtins.all (p: p ? tlType) p.pkgs;
ensurePkgSets =
ps:
if !__fromCombineWrapper && builtins.any isOldPkgList ps then
let
oldPkgLists = builtins.partition isOldPkgList ps;
in
oldPkgLists.wrong ++ lib.concatMap toTLPkgSets oldPkgLists.right
else
ps;
pkgList = rec {
# resolve dependencies of the packages that affect the runtime
all =
let
packages = ensurePkgSets (requiredTeXPackages tl);
runtime = builtins.partition (
p:
p.outputSpecified or false
-> builtins.elem (p.tlOutputName or p.outputName) [
"out"
"tex"
"tlpkg"
]
) packages;
keySet = p: {
key =
p.pname or p.name
+ lib.optionalString (p.outputSpecified or false) ("-" + p.tlOutputName or p.outputName or "");
inherit p;
tlDeps = if p ? tlDeps then ensurePkgSets p.tlDeps else (p.requiredTeXPackages or (_: [ ]) tl);
};
in
# texlive.combine: the wrapper already resolves all dependencies
if __fromCombineWrapper then
requiredTeXPackages null
else
builtins.catAttrs "p" (
builtins.genericClosure {
startSet = map keySet runtime.right;
operator = p: map keySet p.tlDeps;
}
)
++ runtime.wrong;
# group the specified outputs
specified = builtins.partition (p: p.outputSpecified or false) all;
specifiedOutputs = lib.groupBy (p: p.tlOutputName or p.outputName) specified.right;
otherOutputNames = builtins.catAttrs "key" (
builtins.genericClosure {
startSet = map (key: { inherit key; }) (
lib.concatLists (builtins.catAttrs "outputs" specified.wrong)
);
operator = _: [ ];
}
);
otherOutputs = lib.genAttrs otherOutputNames (n: builtins.catAttrs n specified.wrong);
outputsToInstall = builtins.catAttrs "key" (
builtins.genericClosure {
startSet = map (key: { inherit key; }) (
[ "out" ]
++ lib.optional (otherOutputs ? man) "man"
++ lib.concatLists (builtins.catAttrs "outputsToInstall" (builtins.catAttrs "meta" specified.wrong))
);
operator = _: [ ];
}
);
# split binary and tlpkg from tex, texdoc, texsource
bin =
if __fromCombineWrapper then
builtins.filter (p: p.tlType == "bin") all # texlive.combine: legacy filter
else
otherOutputs.out or [ ] ++ specifiedOutputs.out or [ ];
tlpkg =
if __fromCombineWrapper then
builtins.filter (p: p.tlType == "tlpkg") all # texlive.combine: legacy filter
else
otherOutputs.tlpkg or [ ] ++ specifiedOutputs.tlpkg or [ ];
nonbin =
if __fromCombineWrapper then
builtins.filter (p: p.tlType != "bin" && p.tlType != "tlpkg") all # texlive.combine: legacy filter
else
(
if __combine then # texlive.combine: emulate old input ordering to avoid rebuilds
lib.concatMap (
p:
lib.optional (p ? tex) p.tex
++ lib.optional ((withDocs || p ? man) && p ? texdoc) p.texdoc
++ lib.optional (withSources && p ? texsource) p.texsource
) specified.wrong
else
otherOutputs.tex or [ ]
++ lib.optionals withDocs (otherOutputs.texdoc or [ ])
++ lib.optionals withSources (otherOutputs.texsource or [ ])
)
++ specifiedOutputs.tex or [ ]
++ specifiedOutputs.texdoc or [ ]
++ specifiedOutputs.texsource or [ ];
# outputs that do not become part of the environment
nonEnvOutputs = lib.subtractLists [ "out" "tex" "texdoc" "texsource" "tlpkg" ] otherOutputNames;
# packages that contribute to config files and formats
fontMaps = lib.filter (p: p ? fontMaps && (p.tlOutputName or p.outputName == "tex")) nonbin;
sortedFontMaps = builtins.sort (a: b: a.pname < b.pname) fontMaps;
hyphenPatterns = lib.filter (
p: p ? hyphenPatterns && (p.tlOutputName or p.outputName == "tex")
) nonbin;
sortedHyphenPatterns = builtins.sort (a: b: a.pname < b.pname) hyphenPatterns;
formatPkgs = lib.filter (
p:
p ? formats
&& (p.outputSpecified or false -> p.tlOutputName or p.outputName == "tex")
&& builtins.any (f: f.enabled or true) p.formats
) all;
sortedFormatPkgs =
if __formatsOf != null then [ __formatsOf ] else builtins.sort (a: b: a.pname < b.pname) formatPkgs;
formats = map (
p:
self {
requiredTeXPackages =
ps:
[
ps.scheme-infraonly
p
]
++ hyphenPatterns;
__formatsOf = p;
}
) sortedFormatPkgs;
};
# list generated by inspecting `grep -IR '\([^a-zA-Z]\|^\)gs\( \|$\|"\)' "$TEXMFDIST"/scripts`
# and `grep -IR rungs "$TEXMFDIST"`
# and ignoring luatex, perl, and shell scripts (those must be patched using postFixup)
needsGhostscript = lib.any (
p:
lib.elem p.pname [
"context"
"dvipdfmx"
"latex-papersize"
"lyluatex"
]
) pkgList.bin;
name =
if __combine then
"texlive-${__extraName}-${bin.texliveYear}${__extraVersion}" # texlive.combine: old name name
else
"texlive-${bin.texliveYear}-" + (if __formatsOf != null then "${__formatsOf.pname}-fmt" else "env");
texmfdist = buildEnv' {
name = "${name}-texmfdist";
# remove fake derivations (without 'outPath') to avoid undesired build dependencies
paths = builtins.catAttrs "outPath" pkgList.nonbin;
# mktexlsr
nativeBuildInputs = [ tl."texlive.infra" ];
postBuild = # generate ls-R database
''
mktexlsr "$out"
'';
};
tlpkg = buildEnv {
name = "${name}-tlpkg";
# remove fake derivations (without 'outPath') to avoid undesired build dependencies
paths = builtins.catAttrs "outPath" pkgList.tlpkg;
};
# the 'non-relocated' packages must live in $TEXMFROOT/texmf-dist
# and sometimes look into $TEXMFROOT/tlpkg (notably fmtutil, updmap look for perl modules in both)
texmfroot =
runCommand "${name}-texmfroot"
{
inherit texmfdist tlpkg;
}
''
mkdir -p "$out"
ln -s "$texmfdist" "$out"/texmf-dist
ln -s "$tlpkg" "$out"/tlpkg
'';
# texlive.combine: expose info and man pages in usual /share/{info,man} location
doc = buildEnv {
name = "${name}-doc";
paths = [ (texmfdist.outPath + "/doc") ];
extraPrefix = "/share";
pathsToLink = [
"/info"
"/man"
];
};
meta = {
description =
"TeX Live environment"
+ lib.optionalString withDocs " with documentation"
+ lib.optionalString (withDocs && withSources) " and"
+ lib.optionalString withSources " with sources";
platforms = lib.platforms.all;
longDescription =
"Contains the following packages and their transitive dependencies:\n - "
+ lib.concatMapStringsSep "\n - " (
p:
p.pname + (lib.optionalString (p.outputSpecified or false) " (${p.tlOutputName or p.outputName})")
) (requiredTeXPackages tl);
};
# other outputs
nonEnvOutputs = lib.genAttrs pkgList.nonEnvOutputs (
outName:
buildEnv' {
inherit name;
outputs = [ outName ];
paths = builtins.catAttrs "outPath" (
pkgList.otherOutputs.${outName} or [ ] ++ pkgList.specifiedOutputs.${outName} or [ ]
);
# force the output to be ${outName} or nix-env will not work
nativeBuildInputs = [
(writeShellScript "force-output.sh" ''
export out="''${${outName}-}"
'')
];
inherit meta passthru;
}
);
passthru = {
# This is set primarily to help find-tarballs.nix to do its job
requiredTeXPackages = builtins.filter lib.isDerivation (
pkgList.bin
++ pkgList.nonbin
++ lib.optionals (!__fromCombineWrapper) (
lib.concatMap (
n: (pkgList.otherOutputs.${n} or [ ] ++ pkgList.specifiedOutputs.${n} or [ ])
) pkgList.nonEnvOutputs
)
);
# useful for inclusion in the `fonts.packages` nixos option or for use in devshells
fonts = "${texmfroot}/texmf-dist/fonts";
# support variants attrs, (prev: attrs)
__overrideTeXConfig =
newArgs:
let
appliedArgs = if builtins.isFunction newArgs then newArgs args else newArgs;
in
self (args // { __fromCombineWrapper = false; } // appliedArgs);
withPackages =
reqs:
self (
args
// {
requiredTeXPackages = ps: reqs ps ++ requiredTeXPackages ps;
__fromCombineWrapper = false;
}
);
};
# TeXLive::TLOBJ::fmtutil_cnf_lines
fmtutilLine =
{
name,
engine,
enabled ? true,
patterns ? [ "-" ],
options ? "",
...
}:
lib.optionalString (!enabled) "#! "
+ "${name} ${engine} ${lib.concatStringsSep "," patterns} ${options}";
fmtutilLines =
{ pname, formats, ... }:
[
"#"
"# from ${pname}:"
]
++ map fmtutilLine formats;
# TeXLive::TLOBJ::language_dat_lines
langDatLine =
{
name,
file,
synonyms ? [ ],
...
}:
[ "${name} ${file}" ] ++ map (s: "=" + s) synonyms;
langDatLines =
{ pname, hyphenPatterns, ... }:
[ "% from ${pname}:" ] ++ builtins.concatMap langDatLine hyphenPatterns;
# TeXLive::TLOBJ::language_def_lines
# see TeXLive::TLUtils::parse_AddHyphen_line for default values
langDefLine =
{
name,
file,
lefthyphenmin ? "",
righthyphenmin ? "",
synonyms ? [ ],
...
}:
map (
n:
"\\addlanguage{${n}}{${file}}{}{${if lefthyphenmin == "" then "2" else lefthyphenmin}}{${
if righthyphenmin == "" then "3" else righthyphenmin
}}"
) ([ name ] ++ synonyms);
langDefLines =
{ pname, hyphenPatterns, ... }:
[ "% from ${pname}:" ] ++ builtins.concatMap langDefLine hyphenPatterns;
# TeXLive::TLOBJ::language_lua_lines
# see TeXLive::TLUtils::parse_AddHyphen_line for default values
langLuaLine =
{
name,
file,
lefthyphenmin ? "",
righthyphenmin ? "",
synonyms ? [ ],
...
}@args:
''
''\t['${name}'] = {
''\t''\tloader = '${file}',
''\t''\tlefthyphenmin = ${if lefthyphenmin == "" then "2" else lefthyphenmin},
''\t''\trighthyphenmin = ${if righthyphenmin == "" then "3" else righthyphenmin},
''\t''\tsynonyms = { ${lib.concatStringsSep ", " (map (s: "'${s}'") synonyms)} },
''
+ lib.optionalString (args ? file_patterns) "\t\tpatterns = '${args.file_patterns}',\n"
+ lib.optionalString (args ? file_exceptions) "\t\thyphenation = '${args.file_exceptions}',\n"
+ lib.optionalString (args ? luaspecial) "\t\tspecial = '${args.luaspecial}',\n"
+ "\t},";
langLuaLines =
{ pname, hyphenPatterns, ... }: [ "-- from ${pname}:" ] ++ map langLuaLine hyphenPatterns;
assembleConfigLines = f: packages: builtins.concatStringsSep "\n" (builtins.concatMap f packages);
updmapLines = { pname, fontMaps, ... }: [ "# from ${pname}:" ] ++ fontMaps;
out =
# no indent for git diff purposes
buildEnv' {
inherit name;
# use attrNames, attrValues to ensure the two lists are sorted in the same way
outputs = [
"out"
]
++ lib.optionals (!__combine && __formatsOf == null) (builtins.attrNames nonEnvOutputs);
otherOutputs = lib.optionals (!__combine && __formatsOf == null) (
builtins.attrValues nonEnvOutputs
);
# remove fake derivations (without 'outPath') to avoid undesired build dependencies
paths =
builtins.catAttrs "outPath" pkgList.bin
++ lib.optionals (!__combine && __formatsOf == null) pkgList.formats
++ lib.optional __combine doc;
pathsToLink = [
"/"
"/share/texmf-var/scripts"
"/share/texmf-var/tex/generic/config"
"/share/texmf-var/web2c"
"/share/texmf-config"
"/bin" # ensure these are writeable directories
];
nativeBuildInputs = [
makeWrapper
libfaketime
tl."texlive.infra" # mktexlsr
tl.texlive-scripts # fmtutil, updmap
tl.texlive-scripts-extra # texlinks
perl
];
buildInputs = [
coreutils
gawk
gnugrep
gnused
]
++ lib.optional needsGhostscript ghostscript;
inherit meta passthru __combine;
__formatsOf = __formatsOf.pname or null;
inherit texmfdist texmfroot;
fontconfigFile = makeFontsConf { fontDirectories = [ "${texmfroot}/texmf-dist/fonts" ]; };
fmtutilCnf = assembleConfigLines fmtutilLines pkgList.sortedFormatPkgs;
updmapCfg = assembleConfigLines updmapLines pkgList.sortedFontMaps;
languageDat = assembleConfigLines langDatLines pkgList.sortedHyphenPatterns;
languageDef = assembleConfigLines langDefLines pkgList.sortedHyphenPatterns;
languageLua = assembleConfigLines langLuaLines pkgList.sortedHyphenPatterns;
postactionScripts = builtins.catAttrs "postactionScript" pkgList.tlpkg;
postBuild = ''
. "${./build-tex-env.sh}"
'';
allowSubstitutes = true;
preferLocalBuild = false;
};
in
# outputsToInstall must be set *after* overrideAttrs (used in buildEnv') or it fails the checkMeta tests
if __combine || __formatsOf != null then
out
else
lib.addMetaAttrs { inherit (pkgList) outputsToInstall; } out
)

View File

@@ -0,0 +1,352 @@
# shellcheck shell=bash
# Replicate the post install phase of the upstream TeX Live installer.
#
# This script is based on the install-tl script and the TeXLive::TLUtils perl
# module, down to using the same (prefixed) function names and log messages.
#
# When updating to the next TeX Live release, review install-tl for changes and
# update this script accordingly.
### install-tl
# adjust texmf.cnf and texmfcnf.lua
installtl_do_texmf_cnf () {
# unlike install-tl, we make a copy of the entire texmf.cnf
# and point the binaries at $TEXMFCNF/texmf.cnf via wrappers
mkdir -p "$TEXMFCNF"
if [[ -e $texmfdist/web2c/texmfcnf.lua ]]; then
tlutils_info "writing texmfcnf.lua to $TEXMFCNF/texmfcnf.lua"
sed -e "s,\(TEXMFOS[ ]*=[ ]*\)[^\,]*,\1\"$texmfroot\",g" \
-e "s,\(TEXMFDIST[ ]*=[ ]*\)[^\,]*,\1\"$texmfdist\",g" \
-e "s,\(TEXMFSYSVAR[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFSYSVAR\",g" \
-e "s,\(TEXMFSYSCONFIG[ ]*=[ ]*\)[^\,]*,\1\"$TEXMFSYSCONFIG\",g" \
-e "s,\(TEXMFLOCAL[ ]*=[ ]*\)[^\,]*,\1\"$out/share/texmf-local\",g" \
-e "s,\$SELFAUTOLOC,$out,g" \
-e "s,selfautodir:/,$out/share/,g" \
-e "s,selfautodir:,$out/share/,g" \
-e "s,selfautoparent:/,$out/share/,g" \
-e "s,selfautoparent:,$out/share/,g" \
"$texmfdist/web2c/texmfcnf.lua" > "$TEXMFCNF/texmfcnf.lua"
fi
tlutils_info "writing texmf.cnf to $TEXMFCNF/texmf.cnf"
sed -e "s,\(TEXMFROOT[ ]*=[ ]*\)[^\,]*,\1$texmfroot,g" \
-e "s,\(TEXMFDIST[ ]*=[ ]*\)[^\,]*,\1$texmfdist,g" \
-e "s,\(TEXMFSYSVAR[ ]*=[ ]*\)[^\,]*,\1$TEXMFSYSVAR,g" \
-e "s,\(TEXMFSYSCONFIG[ ]*=[ ]*\)[^\,]*,\1$TEXMFSYSCONFIG,g" \
-e "s,\$SELFAUTOLOC,$out,g" \
-e "s,\$SELFAUTODIR,$out/share,g" \
-e "s,\$SELFAUTOPARENT,$out/share,g" \
-e "s,\$SELFAUTOGRANDPARENT,$out/share,g" \
"$texmfdist/web2c/texmf.cnf" > "$TEXMFCNF/texmf.cnf"
}
# run postaction scripts from texlive.tlpdb
# note that the other postactions (fileassoc, ...) are Windows only
installtl_do_tlpdb_postactions () {
local postaction postInterp
if [[ -n $postactionScripts ]] ; then
tlutils_info "running package-specific postactions"
for postaction in $postactionScripts ; do
# see TeXLive::TLUtils::_installtl_do_postaction_script
case "$postaction" in
*.pl)
postInterp=perl ;;
*.texlua)
postInterp=texlua ;;
*)
postInterp= ;;
esac
tlutils_info "${postInterp:+$postInterp }$postaction install $texmfroot"
FORCE_SOURCE_DATE=1 $postInterp "$texmfroot/$postaction" install "$texmfroot" >>"$TEXMFSYSVAR/postaction-${postaction##*/}.log"
done
tlutils_info "finished with package-specific postactions"
fi
}
installtl_do_path_adjustments () {
# here install-tl would add a system symlink to the man pages
# instead we run other nixpkgs related adjustments
# generate wrappers
tlutils_info "wrapping binaries"
local bash cmd extraPaths link path target wrapCount
bash="$(command -v bash)"
enable -f "${bash%/bin/bash}"/lib/bash/realpath realpath
# common runtime dependencies
for cmd in cat awk sed grep gs ; do
# do not fail if gs is absent
path="$(PATH="$HOST_PATH" command -v "$cmd" || :)"
if [[ -n $path ]] ; then
extraPaths="${extraPaths:+$extraPaths:}${path%/"$cmd"}"
fi
done
declare -i wrapCount=0
for link in "$out"/bin/* ; do
target="$(realpath "$link")"
# skip non-executable files (such as context.lua)
if [[ ! -x $target ]] ; then
continue
fi
if [[ ${target##*/} != "${link##*/}" ]] ; then
# detected alias with different basename, use immediate target of $link to preserve $0
# relevant for mktexfmt, repstopdf, ...
target="$(readlink "$link")"
fi
rm "$link"
makeWrapper "$target" "$link" \
--inherit-argv0 \
--prefix PATH : "$extraPaths:$out/bin" \
--set-default TEXMFCNF "$TEXMFCNF" \
--set-default FONTCONFIG_FILE "$fontconfigFile"
wrapCount=$((wrapCount + 1))
done
tlutils_info "wrapped $wrapCount binaries and scripts"
# generate format symlinks (using fmtutil.cnf)
tlutils_info "generating format symlinks"
texlinks --quiet "$out/bin"
# remove *-sys scripts since /nix/store is readonly
rm "$out"/bin/*-sys
# link TEXMFDIST in $out/share for backward compatibility
ln -s "$texmfdist" "$out"/share/texmf
# generate other outputs
local otherOutput otherOutputName
local otherOutputs="$otherOutputs"
for otherOutputName in $outputs ; do
if [[ $otherOutputName == out ]] ; then
continue
fi
otherOutput="${otherOutputs%% *}"
otherOutputs="${otherOutputs#* }"
ln -s "$otherOutput" "${!otherOutputName}"
done
}
# run all post install parts
installtl_do_postinst_stuff () {
installtl_do_texmf_cnf
# create various config files
# in principle, we could use writeText and share them across different
# environments, but the eval & build overhead is not worth the savings
tlutils_create_fmtutil
# can be skipped if generating formats only
if [[ -z $__formatsOf ]] ; then
tlutils_create_updmap
fi
tlutils_create_language_dat
tlutils_create_language_def
tlutils_create_language_lua
# make new files available
tlutils_info "running mktexlsr $TEXMFSYSVAR $TEXMFSYSCONFIG"
mktexlsr "$TEXMFSYSVAR" "$TEXMFSYSCONFIG"
# can be skipped if generating formats only
if [[ -z $__formatsOf ]] ; then
# update font maps
tlutils_info "generating font maps"
updmap-sys --quiet --force --nohash 2>&1
# configure the paper size
# tlmgr --no-execute-actions paper letter
# install-tl: "rerun mktexlsr for updmap-sys and tlmgr paper updates"
tlutils_info "re-running mktexlsr $TEXMFSYSVAR $TEXMFSYSCONFIG"
mktexlsr "$TEXMFSYSVAR" "$TEXMFSYSCONFIG"
tlutils_update_context_cache
fi
# generate formats
# install-tl would run fmtutil-sys $common_fmtutil_args --no-strict --all
# instead, we want fmtutil to exit with error on failure
if [[ -n $fmtutilCnf && -n $__combine$__formatsOf ]] ; then
tlutils_info "pre-generating all format files, be patient..."
# many formats still ignore SOURCE_DATE_EPOCH even when FORCE_SOURCE_DATE=1
# libfaketime fixes non-determinism related to timestamps ignoring FORCE_SOURCE_DATE
# we cannot fix further randomness caused by luatex; for further details, see
# https://salsa.debian.org/live-team/live-build/-/blob/master/examples/hooks/reproducible/2006-reproducible-texlive-binaries-fmt-files.hook.chroot#L52
# note that calling faketime and fmtutil is fragile (faketime uses LD_PRELOAD, fmtutil calls /bin/sh, causing potential glibc issues on non-NixOS)
# so we patch fmtutil to use faketime, rather than calling faketime fmtutil
substitute "$texmfdist"/scripts/texlive/fmtutil.pl fmtutil \
--replace-fail "my \$cmdline = \"\$eng -ini " "my \$cmdline = \"faketime -f '\@$(date +'%F %T' --date=@"$SOURCE_DATE_EPOCH") x0.001' \$eng -ini "
FORCE_SOURCE_DATE=1 perl fmtutil --quiet --strict --sys --all 2>&1 | grep '^fmtutil' # too verbose
# if generating formats only, delete everything else and exit
if [[ -n $__formatsOf ]] ; then
# see fmtutil.pl::compute_format_destination for file extensions
find "$out" \( -type f -or -type l \) \
-not -path "$TEXMFSYSVAR/*.mem" \
-not -path "$TEXMFSYSVAR/*.base" \
-not -path "$TEXMFSYSVAR/*.fmt" \
-delete
find "$out" -type d -empty -delete
exit
fi
elif [[ -z $__combine ]] ; then
# double check that all formats are present
if fmtutil --quiet --strict --sys --missing --dry-run 2>&1 | grep running ; then
tlutils_info 'formats not found, aborting'
exit 1
fi
fi
installtl_do_path_adjustments
installtl_do_tlpdb_postactions
# remove log files to improve reproducibility
find "$TEXMFSYSVAR" -name '*.log' -delete
}
### TeXLive::TLUtils
tlutils_info () {
printf "texlive${__formatsOf:+($__formatsOf-fmt)}: %s\n" "$*"
}
tlutils_create_fmtutil () {
# fmtutil.cnf created by install-tl already exists readonly in $texmfdist
# so here we need to *disable* the entries that are not in $fmtutilCnf
# and write the output in the writeable $TEXMFSYSVAR
local engine fmt line outFile sedExpr
outFile="$TEXMFSYSVAR"/web2c/fmtutil.cnf
tlutils_info "writing fmtutil.cnf to $outFile"
while IFS= read -r line ; do
# a line is 'fmt engine ...' or '#! fmt engine ...'
# (see fmtutil.pl::read_fmtutil_file)
line="${line#\#! }"
read -r fmt engine _ <<<"$line"
# if a line for the ($fmt,$engine) pair exists, remove it to avoid
# pointless warnings from fmtutil
sedExpr="$sedExpr /^(#! )?$fmt $engine /d;"
done <<<"$fmtutilCnf"
# disable all the remaining formats
sedExpr="$sedExpr /^[^#]/{ s/^/#! /p };"
{
echo "# Generated by nixpkgs"
sed -E -n -e "$sedExpr" "$texmfdist"/web2c/fmtutil.cnf
[[ -z $fmtutilCnf ]] || printf '%s' "$fmtutilCnf"
} >"$outFile"
}
tlutils_create_updmap () {
# updmap.cfg created by install-tl already exists readonly in $texmfdist
# so here we need to *disable* the entries that are not in $updmapCfg
# and write the output in the writeable $TEXMFSYSVAR
local line map outFile sedExpr
outFile="$TEXMFSYSVAR"/web2c/updmap.cfg
tlutils_info "writing updmap.cfg to $outFile"
while IFS= read -r line ; do
# a line is 'type map' or '#! type map'
# (see fmtutil.pl::read_updmap_file)
read -r _ map <<<"$line"
# if a line for $map exists, remove it to avoid
# pointless warnings from updmap
sedExpr="$sedExpr /^(#! )?[^ ]*Map $map$/d;"
done <<<"$updmapCfg"
# disable all the remaining font maps
sedExpr="$sedExpr /^[^ ]*Map/{ s/^/#! /p };"
{
echo "# Generated by nixpkgs"
sed -E -n -e "$sedExpr" "$texmfdist"/web2c/updmap.cfg
[[ -z $updmapCfg ]] || printf '%s' "$updmapCfg"
} >"$outFile"
}
tlutils__create_config_files () {
# simplified arguments
local header="$1"
local dest="$2"
local prefix="$3"
local lines="$4"
local suffix="$5"
if [[ -z "$header" || -e "$header" ]] ; then
tlutils_info "writing ${dest##*/} to $dest"
{
[[ -z $prefix ]] || printf '%s\n' "$prefix"
[[ ! -e $header ]] || cat "$header"
[[ -z $lines ]] || printf '%s\n' "$lines"
[[ -z $suffix ]] || printf '%s\n' "$suffix"
} >"$dest"
fi
}
tlutils_create_language_dat () {
tlutils__create_config_files \
"$texmfdist"/tex/generic/config/language.us \
"$TEXMFSYSVAR"/tex/generic/config/language.dat \
'% Generated by nixpkgs' \
"$languageDat" \
''
}
tlutils_create_language_def () {
tlutils__create_config_files \
"$texmfdist"/tex/generic/config/language.us.def \
"$TEXMFSYSVAR"/tex/generic/config/language.def \
'' \
"$languageDef" \
'%%% No changes may be made beyond this point.
\uselanguage {USenglish} %%% This MUST be the last line of the file.'
}
tlutils_create_language_lua () {
tlutils__create_config_files \
"$texmfdist"/tex/generic/config/language.us.lua \
"$TEXMFSYSVAR"/tex/generic/config/language.dat.lua \
'-- Generated by nixpkgs' \
"$languageLua" \
'}'
}
tlutils_update_context_cache () {
if [[ -x $out/bin/mtxrun ]] ; then
tlutils_info "setting up ConTeXt cache"
# temporarily patch mtxrun.lua to generate uuid's deterministically from SOURCE_DATE_EPOCH
mv "$out"/bin/mtxrun.lua{,.orig}
substitute "$out"/bin/mtxrun.lua.orig "$out"/bin/mtxrun.lua \
--replace-fail 'randomseed(math.initialseed)' "randomseed($SOURCE_DATE_EPOCH)"
# this is very verbose, save the output for debugging purposes
{
mtxrun --generate
context --luatex --generate
[[ ! -x $out/bin/luajittex ]] || context --luajittex --generate
} >"$TEXMFSYSVAR"/context-cache.log
mv "$out"/bin/mtxrun.lua{.orig,}
fi
}
# init variables (export only the ones that are used in the wrappers)
export PATH="$out/bin:$PATH"
TEXMFSYSCONFIG="$out/share/texmf-config"
TEXMFSYSVAR="$out/share/texmf-var"
export TEXMFCNF="$TEXMFSYSVAR/web2c"
installtl_do_postinst_stuff

View File

@@ -0,0 +1,297 @@
{
lib,
fetchurl,
runCommand,
writeShellScript,
# script interpreters
bash,
jdk,
perl,
python3,
ruby,
snobol4,
tk,
# TeX Live prerequisites
texliveBinaries,
}:
/*
Convert an attribute set extracted from tlpdb.nix (with the deps attribute
already processed) to a fake multi-output derivation with possible outputs
[ "tex" "texdoc" "texsource" "tlpkg" "out" "man" "info" ]
The multi-output is emulated as follows:
- the main derivation is a multi-output derivation that builds links to the
containers (tex, texdoc, ...)
- the output attributes are replaced with the actual containers with the
outputSpecified attribute set to true
In this way, when texlive.withPackages picks an output such as drv.tex, it
receives the actual container, avoiding superfluous dependencies on the other
containers (for instance doc containers).
*/
# TODO stabilise a generic interface decoupled from the finer details of the
# translation from texlive.tlpdb to tlpdb.nix
{
pname,
revision,
version ? toString revision,
extraRevision ? "",
extraVersion ? "",
sha512 ? { },
mirrors,
fixedHashes ? { },
postUnpack ? "",
postFixup ? "",
stripPrefix ? 1,
license ? [ ],
hasHyphens ? false,
hasInfo ? false,
hasManpages ? false,
hasRunfiles ? (sha512 ? run),
hasTlpkg ? false,
hasCatalogue ? true,
catalogue ? pname,
extraNativeBuildInputs ? [ ],
...
}@args:
let
# common metadata
name = "${pname}-${version}${extraVersion}";
meta = {
license = map (x: lib.licenses.${x}) license;
# TeX Live packages should not be installed directly into the user profile
outputsToInstall = [ ];
longDescription = ''
This package cannot be installed or used directly. Please use `texlive.withPackages (ps: [ ps.${lib.strings.escapeNixIdentifier pname} ])`.
'';
# discourage nix-env from matching this package
priority = 10;
platforms = lib.platforms.all;
# These create a large number of jobs, which puts load on Hydra
# without any appreciable benefit (as the combined packages already
# cause them all to be built and cached anyway).
hydraPlatforms = [ ];
}
// lib.optionalAttrs (args ? shortdesc) {
description = args.shortdesc;
}
// lib.optionalAttrs hasCatalogue {
homepage = "https://ctan.org/pkg/${catalogue}";
};
hasBinfiles = args ? binfiles && args.binfiles != [ ];
hasDocfiles = sha512 ? doc;
hasSource = sha512 ? source;
# containers that will be built by Hydra
outputs =
lib.optional hasBinfiles "out"
++ lib.optional hasRunfiles "tex"
++ lib.optional hasDocfiles "texdoc"
++
# omit building sources, since as far as we know, installing them is not common
# the sources will still be available under drv.texsource
# lib.optional hasSource "texsource" ++
lib.optional hasTlpkg "tlpkg"
++ lib.optional hasManpages "man"
++ lib.optional hasInfo "info";
outputDrvs = lib.getAttrs outputs containers;
passthru = {
# metadata
inherit pname;
revision = toString revision + extraRevision;
version = version + extraVersion;
# containers behave like specified outputs
outputSpecified = true;
}
// lib.optionalAttrs (args ? deps) { tlDeps = args.deps; }
// lib.optionalAttrs (args ? fontMaps) { inherit (args) fontMaps; }
// lib.optionalAttrs (args ? formats) { inherit (args) formats; }
// lib.optionalAttrs (args ? hyphenPatterns) { inherit (args) hyphenPatterns; }
// lib.optionalAttrs (args ? postactionScript) { inherit (args) postactionScript; }
// lib.optionalAttrs hasSource { inherit (containers) texsource; }
// lib.optionalAttrs (!hasRunfiles) { tex = fakeTeX; };
# build run, doc, source, tlpkg containers
mkContainer =
tlType: tlOutputName: sha512:
let
fixedHash = fixedHashes.${tlType} or null; # be graceful about missing hashes
# the basename used by upstream (without ".tar.xz" suffix)
# tlpkg is not a true container but a subfolder of the run container
urlName = pname + (lib.optionalString (tlType != "run" && tlType != "tlpkg") ".${tlType}");
urls = map (up: "${up}/archive/${urlName}.r${toString revision}.tar.xz") mirrors;
container =
runCommand "${name}-${tlOutputName}"
(
{
src = fetchurl { inherit urls sha512; };
inherit passthru;
# save outputName, since fixed output derivations cannot change nor override outputName
inherit meta stripPrefix tlOutputName;
}
// lib.optionalAttrs (fixedHash != null) {
outputHash = fixedHash;
outputHashAlgo = "sha256";
outputHashMode = "recursive";
}
)
(
''
mkdir "$out"
if [[ "$tlOutputName" == "tlpkg" ]]; then
tar -xf "$src" \
--strip-components=1 \
-C "$out" --anchored --exclude=tlpkg/tlpobj --keep-old-files \
tlpkg
else
tar -xf "$src" \
--strip-components="$stripPrefix" \
-C "$out" --anchored --exclude=tlpkg --keep-old-files
fi
''
+ postUnpack
);
in
# remove drv.out to avoid confusing texlive.withPackages
removeAttrs container [ "out" ] // outputDrvs;
# find interpreters for the script extensions found in tlpdb
extToInput = {
jar = jdk;
lua = texliveBinaries.luatex;
py = python3;
rb = ruby;
sno = snobol4;
tcl = tk;
texlua = texliveBinaries.luatex;
tlu = texliveBinaries.luatex;
};
# fake derivation for resolving dependencies in the absence of a "tex" containers
fakeTeX =
passthru
// {
inherit meta;
tlOutputName = "tex";
inherit build;
}
// outputDrvs;
containers = rec {
tex = mkContainer "run" "tex" sha512.run;
texdoc = mkContainer "doc" "texdoc" sha512.doc;
texsource = mkContainer "source" "texsource" sha512.source;
tlpkg = mkContainer "tlpkg" "tlpkg" sha512.run;
# bin container
out =
runCommand "${name}"
{
inherit meta;
passthru = passthru // {
tlOutputName = "out";
};
# shebang interpreters
buildInputs =
let
outName = builtins.replaceStrings [ "-" ] [ "_" ] pname;
in
[
texliveBinaries.core.${outName} or null
texliveBinaries.${pname} or null
texliveBinaries.core-big.${outName} or null
]
++ (args.extraBuildInputs or [ ])
++ [
bash
perl
]
++ (lib.attrVals (args.scriptExts or [ ]) extToInput);
nativeBuildInputs = extraNativeBuildInputs;
# absolute scripts folder
scriptsFolder = lib.optionals (hasRunfiles && tex ? outPath) (
map (f: tex.outPath + "/scripts/" + f) (lib.toList args.scriptsFolder or pname)
);
# binaries info
inherit (args) binfiles;
binlinks = builtins.attrNames (args.binlinks or { });
bintargets = builtins.attrValues (args.binlinks or { });
# build scripts
patchScripts = ./patch-scripts.sed;
makeBinContainers = ./make-bin-containers.sh;
}
''
. "$makeBinContainers"
${args.postFixup or ""}
''
// outputDrvs;
# build man, info containers
man =
removeAttrs (runCommand "${name}-man"
{
inherit meta texdoc;
passthru = passthru // {
tlOutputName = "man";
};
}
''
mkdir -p "$out"/share
ln -s {"$texdoc"/doc,"$out"/share}/man
''
) [ "out" ]
// outputDrvs;
info =
removeAttrs (runCommand "${name}-info"
{
inherit meta texdoc;
passthru = passthru // {
tlOutputName = "info";
};
}
''
mkdir -p "$out"/share
ln -s {"$texdoc"/doc,"$out"/share}/info
''
) [ "out" ]
// outputDrvs;
};
# multioutput derivation to be exported under texlivePackages
# to make Hydra build all containers
build =
runCommand name
{
__structuredAttrs = true;
inherit meta outputDrvs;
outputs = if outputs != [ ] then outputs else [ "out" ];
passthru = removeAttrs passthru [ "outputSpecified" ] // {
inherit build;
};
# force output name in case "out" is missing
preHook = lib.optionalString (!hasBinfiles && outputs != [ ]) ''
export out="''${${builtins.head outputs}-}"
'';
}
# each output is just a symlink to the corresponding container
# if the container is missing (that is, outputs == [ ]), create a file, to prevent passing the package to .withPackages
''
for outputName in ''${!outputs[@]} ; do
if [[ -n ''${outputDrvs[$outputName]} ]] ; then
ln -s "''${outputDrvs[$outputName]}" "''${outputs[$outputName]}"
else
touch "''${outputs[$outputName]}"
fi
done
'';
in
if outputs == [ ] then removeAttrs fakeTeX [ "outputSpecified" ] else build // outputDrvs

View File

@@ -0,0 +1,78 @@
# legacy texlive.combine wrapper
{
lib,
toTLPkgList,
toTLPkgSets,
buildTeXEnv,
}:
args@{
pkgFilter ? (
pkg: pkg.tlType == "run" || pkg.tlType == "bin" || pkg.pname == "core" || pkg.hasManpages or false
),
extraName ? "combined",
extraVersion ? "",
...
}:
let
pkgSet = removeAttrs args [
"pkgFilter"
"extraName"
"extraVersion"
];
# combine a set of TL packages into a single TL meta-package
combinePkgs =
pkgList:
lib.catAttrs "pkg" (
let
# a TeX package used to be an attribute set { pkgs = [ ... ]; ... } where pkgs is a list of derivations
# the derivations make up the TeX package and optionally (for backward compatibility) its dependencies
tlPkgToSets =
drv:
map (
{
tlType,
version ? "",
outputName ? "",
...
}@pkg:
{
# outputName required to distinguish among bin.core-big outputs
key = "${pkg.pname or pkg.name}.${tlType}-${version}-${outputName}";
inherit pkg;
}
) (drv.pkgs or (toTLPkgList drv));
pkgListToSets = lib.concatMap tlPkgToSets;
in
builtins.genericClosure {
startSet = pkgListToSets pkgList;
operator = { pkg, ... }: pkgListToSets (pkg.tlDeps or [ ]);
}
);
combined = combinePkgs (lib.attrValues pkgSet);
# convert to specified outputs
tlTypeToOut = {
run = "tex";
doc = "texdoc";
source = "texsource";
bin = "out";
tlpkg = "tlpkg";
};
toSpecified =
{ tlType, ... }@drv:
drv
// {
outputSpecified = true;
tlOutputName = tlTypeToOut.${tlType};
};
all = lib.filter pkgFilter combined ++ lib.filter (pkg: pkg.tlType == "tlpkg") combined;
converted = map toSpecified all;
in
buildTeXEnv {
__extraName = extraName;
__extraVersion = extraVersion;
requiredTeXPackages = _: converted;
__combine = true;
__fromCombineWrapper = true;
}

View File

@@ -0,0 +1,632 @@
/*
TeX Live user docs
- source: ../../../../../doc/languages-frameworks/texlive.xml
- current html: https://nixos.org/nixpkgs/manual/#sec-language-texlive
*/
{
lib,
stdenv,
fetchpatch,
fetchurl,
runCommand,
writeShellScript,
writeText,
buildEnv,
callPackage,
ghostscript_headless,
harfbuzz,
makeWrapper,
installShellFiles,
python3,
ruby,
perl,
tk,
jdk,
bash,
snobol4,
coreutils,
findutils,
gawk,
getopt,
gnugrep,
gnumake,
gnupg,
gnused,
gzip,
html-tidy,
ncurses,
zip,
libfaketime,
asymptote,
biber-ms,
makeFontsConf,
useFixedHashes ? true,
extraMirrors ? [ ],
recurseIntoAttrs,
nixfmt,
luajit,
}:
let
# various binaries (compiled)
bin = callPackage ./bin.nix {
ghostscript = ghostscript_headless;
harfbuzz = harfbuzz.override {
withIcu = true;
withGraphite2 = true;
};
inherit useFixedHashes;
tlpdb = overriddenTlpdb;
};
tlpdb = import ./tlpdb.nix;
tlpdbVersion = tlpdb."00texlive.config";
# the set of TeX Live packages, collections, and schemes; using upstream naming
overriddenTlpdb =
let
overrides = import ./tlpdb-overrides.nix {
inherit
stdenv
lib
fetchpatch
bin
tlpdb
tlpdbxz
tl
installShellFiles
coreutils
findutils
gawk
getopt
ghostscript_headless
gnugrep
gnumake
gnupg
gnused
gzip
html-tidy
ncurses
perl
python3
ruby
zip
luajit
;
};
in
overrides tlpdb;
version = {
# day of the snapshot being taken
year = "2025";
month = "07";
day = "03";
# TeX Live version
texliveYear = 2025;
# final (historic) release or snapshot
final = false;
};
# The tarballs on CTAN mirrors for the current release are constantly
# receiving updates, so we can't use those directly. Stable snapshots
# need to be used instead. Ideally, for the release branches of NixOS we
# should be switching to the tlnet-final versions
# (https://tug.org/historic/).
mirrors =
extraMirrors
++ (
if version.final then
[
# tlnet-final snapshot; used when texlive.tlpdb is frozen
# the TeX Live yearly freeze typically happens in mid-March
"http://ftp.math.utah.edu/pub/tex/historic/systems/texlive/${toString version.texliveYear}/tlnet-final"
"ftp://tug.org/texlive/historic/${toString version.texliveYear}/tlnet-final"
]
else
[
# CTAN mirrors
"https://mirror.ctan.org/systems/texlive/tlnet"
# daily snapshots hosted by one of the texlive release managers;
# used for packages that in the meanwhile have been updated or removed from CTAN
# and for packages that have not reached yet the historic mirrors
# please note that this server is not meant for large scale deployment
# https://tug.org/pipermail/tex-live/2019-November/044456.html
# https://texlive.info/ MUST appear last (see tlpdbxz)
"https://texlive.info/tlnet-archive/${version.year}/${version.month}/${version.day}/tlnet"
]
);
tlpdbxz = fetchurl {
urls =
map (up: "${up}/tlpkg/texlive.tlpdb.xz")
# use last mirror for daily snapshots as texlive.tlpdb.xz changes every day
# TODO make this less hacky
(if version.final then mirrors else [ (lib.last mirrors) ]);
hash = "sha256-hTWTs5meP6X7+bBGEHP9pDv8eJTfvBZFKX0WeK8+aZg=";
};
tlpdbNix =
runCommand "tlpdb.nix"
{
inherit tlpdbxz;
tl2nix = ./tl2nix.sed;
}
''
xzcat "$tlpdbxz" | sed -rn -f "$tl2nix" | uniq | ${lib.getExe nixfmt} > "$out"
'';
# map: name -> fixed-output hash
fixedHashes = lib.optionalAttrs useFixedHashes (import ./fixed-hashes.nix);
buildTeXLivePackage = import ./build-texlive-package.nix {
inherit
lib
fetchurl
runCommand
writeShellScript
bash
jdk
perl
python3
ruby
snobol4
tk
;
texliveBinaries = bin;
};
tl = lib.mapAttrs (
pname:
{
revision,
extraRevision ? "",
...
}@args:
buildTeXLivePackage (
args
# NOTE: the fixed naming scheme must match generate-fixed-hashes.nix
// {
inherit mirrors pname;
fixedHashes = fixedHashes."${pname}-${toString revision}${extraRevision}" or { };
}
// lib.optionalAttrs (args ? deps) { deps = map (n: tl.${n}) (args.deps or [ ]); }
)
) overriddenTlpdb;
# function for creating a working environment
buildTeXEnv = import ./build-tex-env.nix {
inherit bin tl;
ghostscript = ghostscript_headless;
inherit
lib
buildEnv
libfaketime
makeFontsConf
makeWrapper
runCommand
writeShellScript
writeText
toTLPkgSets
bash
perl
coreutils
gawk
gnugrep
gnused
;
};
### texlive.combine compatibility layer:
# convert TeX packages to { pkgs = [ ... ]; } lists
# respecting specified outputs
toTLPkgList =
drv:
if drv.outputSpecified or false then
let
tlType = drv.tlType or tlOutToType.${drv.tlOutputName or drv.outputName} or null;
in
lib.optional (tlType != null) (drv // { inherit tlType; })
else
[ (drv.tex // { tlType = "run"; }) ]
++ lib.optional (drv ? texdoc) (
drv.texdoc // { tlType = "doc"; } // lib.optionalAttrs (drv ? man) { hasManpages = true; }
)
++ lib.optional (drv ? texsource) (drv.texsource // { tlType = "source"; })
++ lib.optional (drv ? tlpkg) (drv.tlpkg // { tlType = "tlpkg"; })
++ lib.optional (drv ? out) (drv.out // { tlType = "bin"; });
tlOutToType = {
out = "bin";
tex = "run";
texsource = "source";
texdoc = "doc";
tlpkg = "tlpkg";
};
# convert { pkgs = [ ... ]; } lists to TeX packages
# possibly more than one, if pkgs is also used to specify dependencies
tlTypeToOut = {
run = "tex";
doc = "texdoc";
source = "texsource";
bin = "out";
tlpkg = "tlpkg";
};
toSpecifiedNV = p: rec {
name = value.tlOutputName;
value = removeAttrs p [ "pkgs" ] // {
outputSpecified = true;
tlOutputName = tlTypeToOut.${p.tlType};
};
};
toTLPkgSet =
pname: drvs:
let
set = lib.listToAttrs (map toSpecifiedNV drvs);
mainDrv = set.out or set.tex or set.tlpkg or set.texdoc or set.texsource;
in
removeAttrs mainDrv [ "outputSpecified" ];
toTLPkgSets = { pkgs, ... }: lib.mapAttrsToList toTLPkgSet (lib.groupBy (p: p.pname) pkgs);
# export TeX packages as { pkgs = [ ... ]; } in the top attribute set
allPkgLists = lib.mapAttrs (n: drv: { pkgs = toTLPkgList drv; }) tl;
# function for creating a working environment from a set of TL packages
# now a legacy wrapper around buildTeXEnv
combine = import ./combine-wrapper.nix {
inherit
buildTeXEnv
lib
toTLPkgList
toTLPkgSets
;
};
assertions =
lib.assertMsg (
tlpdbVersion.year == version.texliveYear
) "TeX Live year in texlive does not match tlpdb.nix, refusing to evaluate"
&& lib.assertMsg (
tlpdbVersion.frozen == version.final
) "TeX Live final status in texlive does not match tlpdb.nix, refusing to evaluate";
# Pre-defined environment packages for TeX Live schemes,
# to make nix-env usage more comfortable and build selected on Hydra.
# these license lists should be the sorted union of the licenses of the packages the schemes contain.
# The correctness of this collation is tested by tests.texlive.licenses
licenses = with lib.licenses; {
scheme-basic = [
cc-by-sa-40
free
gfl
gpl1Only
gpl2Only
gpl2Plus
knuth
lgpl21
lppl1
lppl13c
mit
ofl
publicDomain
];
scheme-bookpub = [
artistic2
asl20
bsd3
cc-by-sa-40
fdl13Only
free
gfl
gpl1Only
gpl2Only
gpl2Plus
knuth
lgpl21
lppl1
lppl12
lppl13c
mit
ofl
publicDomain
];
scheme-context = [
bsd2
bsd3
cc-by-sa-40
eupl12
fdl13Only
free
gfl
gfsl
gpl1Only
gpl2Only
gpl2Plus
gpl3Only
gpl3Plus
knuth
lgpl2
lgpl21
lppl1
lppl13c
mit
ofl
publicDomain
x11
];
scheme-full = [
artistic1-cl8
artistic2
asl20
bsd2
bsd3
bsdOriginal
cc-by-10
cc-by-20
cc-by-30
cc-by-40
cc-by-sa-10
cc-by-sa-20
cc-by-sa-30
cc-by-sa-40
cc0
eupl12
fdl13Only
free
gfl
gfsl
gpl1Only
gpl2Only
gpl2Plus
gpl3Only
gpl3Plus
isc
knuth
lgpl2
lgpl21
lgpl3
lppl1
lppl12
lppl13a
lppl13c
mit
ofl
publicDomain
x11
];
scheme-gust = [
artistic1-cl8
asl20
bsd2
bsd3
cc-by-40
cc-by-sa-40
cc0
eupl12
fdl13Only
free
gfl
gfsl
gpl1Only
gpl2Only
gpl2Plus
gpl3Only
gpl3Plus
knuth
lgpl2
lgpl21
lppl1
lppl12
lppl13c
mit
ofl
publicDomain
x11
];
scheme-infraonly = [
gpl2Plus
lgpl21
];
scheme-medium = [
artistic1-cl8
asl20
bsd2
bsd3
cc-by-40
cc-by-sa-20
cc-by-sa-30
cc-by-sa-40
cc0
eupl12
fdl13Only
free
gfl
gpl1Only
gpl2Only
gpl2Plus
gpl3Only
gpl3Plus
isc
knuth
lgpl2
lgpl21
lgpl3
lppl1
lppl12
lppl13a
lppl13c
mit
ofl
publicDomain
x11
];
scheme-minimal = [
cc-by-sa-40
free
gpl1Only
gpl2Plus
knuth
lgpl21
lppl1
lppl13c
mit
ofl
publicDomain
];
scheme-small = [
asl20
cc-by-40
cc-by-sa-40
cc0
eupl12
fdl13Only
free
gfl
gpl1Only
gpl2Only
gpl2Plus
gpl3Only
gpl3Plus
knuth
lgpl2
lgpl21
lppl1
lppl12
lppl13c
mit
ofl
publicDomain
x11
];
scheme-tetex = [
artistic1-cl8
asl20
bsd2
bsd3
cc-by-30
cc-by-40
cc-by-sa-10
cc-by-sa-20
cc-by-sa-30
cc-by-sa-40
cc0
eupl12
fdl13Only
free
gfl
gpl1Only
gpl2Only
gpl2Plus
gpl3Only
gpl3Plus
isc
knuth
lgpl2
lgpl21
lgpl3
lppl1
lppl12
lppl13a
lppl13c
mit
ofl
publicDomain
x11
];
};
meta = {
description = "TeX Live environment";
platforms = lib.platforms.all;
maintainers = with lib.maintainers; [ veprbl ];
license = licenses.scheme-infraonly;
};
combined = recurseIntoAttrs (
lib.genAttrs
[
"scheme-basic"
"scheme-bookpub"
"scheme-context"
"scheme-full"
"scheme-gust"
"scheme-infraonly"
"scheme-medium"
"scheme-minimal"
"scheme-small"
"scheme-tetex"
]
(
pname:
(buildTeXEnv {
__extraName = "combined" + lib.removePrefix "scheme" pname;
__extraVersion =
if version.final then "-final" else ".${version.year}${version.month}${version.day}";
requiredTeXPackages = ps: [ ps.${pname} ];
# to maintain full backward compatibility, enable texlive.combine behavior
__combine = true;
}).overrideAttrs
{
meta = meta // {
description = "TeX Live environment for ${pname}";
license = licenses.${pname};
};
}
)
);
schemes = lib.listToAttrs (
map
(s: {
name = "texlive" + s;
value = lib.addMetaAttrs { license = licenses.${"scheme-" + (lib.toLower s)}; } (buildTeXEnv {
requiredTeXPackages = ps: [ ps.${"scheme-" + (lib.toLower s)} ];
});
})
[
"Basic"
"BookPub"
"ConTeXt"
"Full"
"GUST"
"InfraOnly"
"Medium"
"Minimal"
"Small"
"TeTeX"
]
);
in
allPkgLists
// {
pkgs = tl;
tlpdb = {
# nested in an attribute set to prevent them from appearing in search
nix = tlpdbNix;
xz = tlpdbxz;
};
bin =
assert assertions;
bin
// {
# for backward compatibility
latexindent = tl.latexindent;
};
combine =
assert assertions;
combine;
combined =
assert assertions;
combined;
inherit schemes;
# convenience alias
withPackages = (buildTeXEnv { }).withPackages;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,70 @@
{
pkgs ? (import ../../../../.. { }),
}:
let
inherit (pkgs)
runCommand
writeText
texlive
nix
;
inherit (pkgs.lib)
attrValues
concatMap
concatMapStrings
isDerivation
filter
optional
optionalString
sort
strings
;
getFods =
drv:
optional (isDerivation drv.tex) (drv.tex // { tlType = "run"; })
++ optional (drv ? texdoc) (drv.texdoc // { tlType = "doc"; })
++ optional (drv ? texsource) (drv.texsource // { tlType = "source"; })
++ optional (drv ? tlpkg) (drv.tlpkg // { tlType = "tlpkg"; });
sorted = sort (a: b: a.pname < b.pname) (attrValues texlive.pkgs);
fods = concatMap getFods sorted;
computeHash =
fod:
runCommand "${fod.pname}-${fod.tlType}-fixed-hash" {
buildInputs = [ nix ];
inherit fod;
} ''echo -n "$(nix-hash --base32 --type sha256 "$fod")" >"$out"'';
hash = fod: fod.outputHash or (builtins.readFile (computeHash fod));
hashes = fods: concatMapStrings ({ tlType, ... }@p: ''${tlType}="${hash p}";'') fods;
hashLine =
{
pname,
revision,
extraRevision ? "",
...
}@drv:
let
fods = getFods drv;
# NOTE: the fixed naming scheme must match default.nix
fixedName = "${pname}-${toString revision}${extraRevision}";
in
optionalString (fods != [ ]) ''
${strings.escapeNixIdentifier fixedName}={${hashes fods}};
'';
in
{
# fixedHashesNix uses 'import from derivation' which does not parallelize well
# you should build newHashes first, before evaluating (and building) fixedHashesNix
newHashes = map computeHash (filter (fod: !fod ? outputHash) fods);
fixedHashesNix = writeText "fixed-hashes.nix" ''
{
${concatMapStrings hashLine sorted}}
'';
}

View File

@@ -0,0 +1,60 @@
# load realpath
loadables="$(command -v bash)"
loadables="${loadables%/bin/bash}/lib/bash"
enable -f "$loadables/realpath" realpath
mkdir -p "$out/bin"
# find interpreters
export interpPerl="$(PATH="$HOST_PATH" command -v perl)"
export interpJava="$(PATH="$HOST_PATH" command -v java || :)"
export interpWish="$(PATH="$HOST_PATH" command -v wish || :)"
# prepare sed script
substituteAll "$patchScripts" patch-scripts.sed
for binname in $binfiles ; do
# binlinks to be created last, after the other binaries are in place
if [[ " $binlinks " == *" $binname "* ]] ; then
continue
fi
output="$out/bin/$binname"
# look for existing binary from bin.*
target="$(PATH="$HOST_PATH" command -v "$binname" || :)"
if [[ -n "$target" && -x "$target" ]] ; then
ln -s "$(realpath "$target")" "$output"
continue
fi
# look for scripts
# the explicit list of extensions avoid non-scripts such as $binname.cmd, $binname.jar, $binname.pm
# the order is relevant: $binname.sh is preferred to other $binname.*
for folder in $scriptsFolder ; do
for script in "$folder/$binname"{,.sh,.lua,.pl,.py,.rb,.sno,.tcl,.texlua,.tlu}; do
if [[ -f "$script" ]] ; then
sed -f patch-scripts.sed \
-e 's/^scriptname=`basename "\$0"`$/'"scriptname='$(basename "$binname")'/" \
-e 's/^scriptname=`basename "\$0" .sh`$'"/scriptname='$(basename "$binname" .sh)'/" \
"$script" > "$output"
chmod +x "$output"
continue 3
fi
done
done
echo "error: could not find source for 'bin/$binname'" >&2
exit 1
done
# patch shebangs
patchShebangs "$out/bin"
# generate links
# we canonicalise the source to avoid symlink chains, and to check that it exists
cd "$out"/bin
for alias in $binlinks ; do
target="${bintargets%% *}"
bintargets="${bintargets#* }"
ln -s "$(realpath "$target")" "$out/bin/$alias"
done

View File

@@ -0,0 +1,57 @@
1{
/python/{
N;
# add script folder to path, unless we interfere with a docstring
/\nr"""/b skip-python-path-patch
s!\n!\nimport sys; sys.path.insert(0,'@scriptsFolder@')\n!
:skip-python-path-patch
}
/^#!.*perl/{
# add script folder to @INC
s!$! -I@scriptsFolder@!
}
/^eval/{
# most likely the weird perl shebang
N
/^eval '(exit \$?0)' && eval 'exec perl -S \$0 \${1+"\$@"}' && eval 'exec perl -S \$0 \$argv:q'\n *if 0;$/{
x; s/.*/patching weird perl shebang/; w /dev/stderr
x; s|^.*$|#!@interpPerl@ -I@scriptsFolder@|
}
}
}
# patch 'exec interpreter'
/exec java /{
x; s/.*/patching exec java/; w /dev/stderr
x; s|exec java |exec '@interpJava@' |g
/exec ''/{
x; s/^.*$/error: java missing from PATH/; w /dev/stderr
q 1
}
}
/exec perl /{
x; s/.*/patching exec perl/; w /dev/stderr
x; s|exec perl |exec @interpPerl@ -I@scriptsFolder@ |g
/exec ''/{
x; s/^.*$/error: perl missing from PATH/; w /dev/stderr
q 1
}
}
/exec wish /{
x; s/.*/patching exec wish/; w /dev/stderr
x; s|exec wish |exec '@interpWish@' |g
/exec ''/{
x; s/^.*$/error: wish missing from PATH/; w /dev/stderr
q 1
}
}
# make jar wrappers work without kpsewhich
s!^jarpath=`kpsewhich --progname=[^ ]* --format=texmfscripts \([^ ]*\)`$!jarpath=@scriptsFolder@/\1!g
# replace CYGWIN grep test with bash builtin
s!echo "$kernel" | grep CYGWIN >/dev/null;![[ "$kernel" == *CYGWIN* ]]!g

View File

@@ -0,0 +1,9 @@
@@ -157,7 +157,7 @@
verbose_echo "skipped ConTeXtish symlink $src -> $dest (special case)"
;;
*)
- test ! -f "$src" &&
+ test "x$src" != "x`(ls -ld $src | awk '{print $NF}') 2>/dev/null`" &&
rm -f "$src"
if test -f "$src"; then

View File

@@ -0,0 +1,298 @@
# wrap whole file into an attrset
1i{ # no indentation
$a}
# extract repository metadata
/^name 00texlive\.config$/,/^$/{
s/^name (.*)$/"\1" = {/p
/^$/,1i};
s!^depend frozen/0$! frozen = false;!p
s!^depend frozen/1$! frozen = true;!p
s!^depend release/(.*)$! year = \1;!p
s!^depend revision/(.*)$! revision = \1;!p
}
# form an attrmap per package
# ignore packages whose name contains "." (such as binaries) except for texlive.infra
/^name ([^.]+|texlive\.infra)$/,/^$/{
# quote invalid names
s/^name ([0-9].*|texlive\.infra)$/"\1" = {/p
s/^name (.*)$/\1 = {/p
# extract revision
s/^revision ([0-9]*)$/ revision = \1;/p
# extract short description
/^shortdesc (.+)$/{
# escape special characters ", \, ${
s/\\/\\\\/g # escape backslashes
s/\$\{/\\${/g # escape '${'
s/"/\\"/g # escape quotes
s/^shortdesc (.+)/ shortdesc = "\1";/p
}
# extract hashes of *.tar.xz
/^containerchecksum (.*)/{
# save in holdspace, print later if hasRunfiles || hasTlpkg
s/^containerchecksum (.*)/ sha512.run = "\1";/
H
}
s/^doccontainerchecksum (.*)/ sha512.doc = "\1";/p
s/^srccontainerchecksum (.*)/ sha512.source = "\1";/p
# number of path components to strip, defaulting to 1 ("texmf-dist/")
/^relocated 1/i\ stripPrefix = 0;
/^catalogue(-| )/{
:next-cat
s/^catalogue (.*)/ catalogue = "\1";/p
# extract version and clean unwanted chars from it
/^catalogue-version/y/ \/~/_--/
/^catalogue-version/s/[\#,:\(\)]//g
s/^catalogue-version_(.*)/ version = "\1";/p
# extract license
/^catalogue-license/{
# wrap licenses in quotes
s/ ([^ ]+)/ "\1"/g
# adjust naming as in nixpkgs, the full texts of the licenses are available at https://www.ctan.org/license/${licenseName}
s/"(cc-by(-sa)?-[1-4])"/"\10"/g
s/"apache2"/"asl20"/g
s/"artistic"/"artistic1-cl8"/g
s/"bsd"/"bsd3"/g # license text does not match exactly, but is pretty close
s/"bsd4"/"bsdOriginal"/g
s/"collection"/"free"/g # used for collections of individual packages with distinct licenses. As TeXlive only contains free software, we can use "free" as a catchall
s/"eupl"/"eupl12"/g
s/"fdl"/"fdl13Only"/g
s/"gpl"/"gpl1Only"/g
s/"gpl([1-3])"/"gpl\1Only"/g
s/"gpl2\+"/"gpl2Plus"/g
s/"gpl3\+"/"gpl3Plus"/g
s/"lgpl"/"lgpl2"/g
s/"lgpl2\.1"/"lgpl21"/g
s/"lppl"/"lppl13c"/g # not used consistently, sometimes "lppl" refers to an older version of the license
s/"lppl1\.2"/"lppl12"/g
s/"lppl1\.3"/"lppl13c"/g # If a work refers to LPPL 1.3 as its license, this is interpreted as the latest version of the 1.3 license (https://www.latex-project.org/lppl/)
s/"lppl1\.3a"/"lppl13a"/g
s/"lppl1\.3c"/"lppl13c"/g
s/"other-free"/"free"/g
s/"other-nonfree"/"unfree"/g
s/"opl"/"opubl"/g
s/"pd"/"publicDomain"/g
s/^catalogue-license (.*)/ license = [ \1 ];/p
}
s/^.*$//
N
s/^\ncatalogue(-| )/catalogue\1/
t next-cat
# flag existence of catalogue info in hold space
x ; s/$/\n hasCatalogue = true;/ ; x
# restart cycle
D
}
# extract deps
/^depend ([^.]+|texlive\.infra)$/{
# open a list
i\ deps = [
# loop through following depend lines
:next-dep
s/^\n?depend ([^.]+|texlive\.infra)$/ "\1"/p # print dep
s/^.*$// # clear pattern space
N; /^\ndepend /b next-dep
# close the list
i\ ];
D # restart cycle from the current line
}
# extract font maps
/^execute add.*Map /{
# open a list
i\ fontMaps = [
# loop through following map lines
:next-map
s/^\n?execute add(.*Map .*)$/ "\1"/p # print map
s/^.*$// # clear pattern space
N; /^\nexecute add.*Map /b next-map
# close the string
i\ ];
D # restart cycle from the current line
}
# detect presence of notable files
/^docfiles /{
s/^.*$// # ignore the first line
# read all files
:next-doc
N
s/\n / / # remove newline
t next-doc # loop if the previous lines matched
/ (texmf-dist|RELOC)\/doc\/man\//i\ hasManpages = true;
/ (texmf-dist|RELOC)\/doc\/info\//i\ hasInfo = true;
D # restart cycle
}
/^runfiles /{
s/^.*$// # ignore the first line
# read all files
:next-file
N
s/\n / / # remove newline
t next-file # loop if previous line matched
s/\n/ \n/ # add space before last newline for accurate matching below
/ (RELOC|texmf-dist)\//{
# flag existence of runtime files in hold space
x ; s/$/\n hasRunfiles = true;/ ; x
}
/ tlpkg\//{
# flag existence of tlpkg files in hold space
x ; s/$/\n hasTlpkg = true;/ ; x
}
# extract script extensions
/ texmf-dist\/scripts\/.*\.(jar|lua|py|rb|sno|tcl|texlua|tlu) /{
i\ scriptExts = [
/ texmf-dist\/scripts\/.*\.jar /i\ "jar"
/ texmf-dist\/scripts\/.*\.lua /i\ "lua"
/ texmf-dist\/scripts\/.*\.py /i\ "py"
/ texmf-dist\/scripts\/.*\.rb /i\ "rb"
/ texmf-dist\/scripts\/.*\.sno /i\ "sno"
/ texmf-dist\/scripts\/.*\.tcl /i\ "tcl"
/ texmf-dist\/scripts\/.*\.texlua /i\ "texlua"
/ texmf-dist\/scripts\/.*\.tlu /i\ "tlu"
i\ ];
}
D # restart cycle from the current line
}
# extract postaction scripts (right now, at most one per package, so a string suffices)
s/^postaction script file=(.*)$/ postactionScript = "\1";/p
# extract hyphenation patterns
/^execute\sAddHyphen\s/{
# open a list
i\ hyphenPatterns = [
# create one attribute set per hyphenation pattern
# plain keys: name, lefthyphenmin, righthyphenmin, file, file_patterns, file_exceptions, comment
# optionally double quoted key: luaspecial, comment
# comma-separated lists: databases, synonyms
:next-hyphen
s/(^|\n)execute\sAddHyphen/ {/
s/\s+luaspecial="([^"]+)"/\n luaspecial = "\1";/
s/\s+(name|lefthyphenmin|righthyphenmin|file|file_patterns|file_exceptions|luaspecial|comment)=([^ \t\n]*)/\n \1 = "\2";/g
s/\s+(databases|synonyms)=([^ \t\n]+)/\n \1 = [ "\2" ];/g
s/$/\n }/
:split-hyphens
s/"([^,]+),([^"]+)" ]/"\1" "\2" ]/;
t split-hyphens # repeat until there are no commas
p
s/^.*$// # clear pattern space
N
/^\nexecute\sAddHyphen\s/b next-hyphen
# close the list
i\ ];
D # restart cycle from the current line
}
# extract format details
/^execute\sAddFormat\s/{
# open a list
i\ formats = [
# create one attribute set per format
# note that format names are not unique
# plain keys: name, engine, patterns
# optionally double quoted key: options
# boolean key: mode (enabled/disabled)
# comma-separated lists: fmttriggers, patterns
:next-fmt
s/(^|\n)execute\sAddFormat/ {/
s/\s+options="([^"]+)"/\n options = "\1";/
s/\s+(name|engine|options)=([^ \t\n]+)/\n \1 = "\2";/g
s/\s+mode=enabled//
s/\s+mode=disabled/\n enabled = false;/
s/\s+(fmttriggers|patterns)=([^ \t\n]+)/\n \1 = [ "\2" ];/g
s/$/\n }/
:split-triggers
s/"([^,]+),([^"]+)" ]/"\1" "\2" ]/;
t split-triggers # repeat until there are no commas
p
s/^.*$// # clear pattern space
N
/^\nexecute\sAddFormat\s/b next-fmt
# close the list
i\ ];
D # restart cycle from the current line
}
# close attrmap
/^$/{
# process content of hold space
x
# change hasCatalogue default from false to true
/(^|\n) hasCatalogue = true;(\n|$)/!{
s/$/\n hasCatalogue = false;/M
}
s/^ hasCatalogue = true;$//Mg
# change hasRunfiles default from false to (sha512 ? run)
/(^|\n) hasRunfiles = true;(\n|$)/!{
# if no runfiles nor tlpkg, omit sha512.run altogether
/^ hasTlpkg = true;$/M{
s/$/\n hasRunfiles = false;/M
}
/^ hasTlpkg = true;$/M!{
s/^ sha512.run = "[^"]*";$//M
}
}
s/^ hasRunfiles = true;$//Mg
# clear empty lines
s/(^\n*|\n*$)//g
s/\n\n+/\n/g
# print hold space if not empty
/./Mp
# erase hold space
s/.*//
x
i};
}
}
# add list of binaries from one of the architecture-specific packages
/^name ([^.]+|texlive\.infra)\.x86_64-linux$/,/^$/{
s/^name ([0-9].*|texlive\.infra)\.x86_64-linux$/"\1".binfiles = [/p
s/^name (.*)\.x86_64-linux$/\1.binfiles = [/p
s!^ bin/x86_64-linux/(.+)$! "\1"!p
/^$/i];
}

View File

@@ -0,0 +1,623 @@
{
stdenv,
fetchpatch,
lib,
tlpdb,
bin,
tlpdbxz,
tl,
installShellFiles,
coreutils,
findutils,
gawk,
getopt,
ghostscript_headless,
gnugrep,
gnumake,
gnupg,
gnused,
gzip,
html-tidy,
ncurses,
perl,
python3,
ruby,
zip,
luajit,
}:
oldTlpdb:
let
tlpdbVersion = tlpdb."00texlive.config";
# most format -> engine links are generated by texlinks according to fmtutil.cnf at combine time
# so we remove them from binfiles, and add back the ones texlinks purposefully ignore (e.g. mptopdf)
removeFormatLinks = lib.mapAttrs (
_: attrs:
if
(attrs ? formats && attrs ? binfiles)
# TLPDB reports erroneously that various metafont binaries like "mf" are format links to engines
# like "mf-nowin"; core-big provides both binaries and links so we simply skip them here
then
let
formatLinks = lib.catAttrs "name" (
lib.filter (f: f.name != f.engine && !lib.hasSuffix "-nowin" f.engine) attrs.formats
);
binNotFormats = lib.subtractLists formatLinks attrs.binfiles;
in
if binNotFormats != [ ] then
attrs // { binfiles = binNotFormats; }
else
removeAttrs attrs [ "binfiles" ]
else
attrs
);
orig = removeFormatLinks (removeAttrs oldTlpdb [ "00texlive.config" ]);
in
lib.recursiveUpdate orig rec {
#### overrides of texlive.tlpdb
#### nonstandard script folders
cyrillic-bin.scriptsFolder = "texlive-extra";
fontinst.scriptsFolder = "texlive-extra";
mptopdf.scriptsFolder = "context/perl";
pdftex.scriptsFolder = "simpdftex";
texlive-scripts.scriptsFolder = "texlive";
texlive-scripts-extra.scriptsFolder = "texlive-extra";
xetex.scriptsFolder = "texlive-extra";
#### interpreters not detected by looking at the script extensions
ctanbib.extraBuildInputs = [ bin.luatex ];
de-macro.extraBuildInputs = [ python3 ];
match_parens.extraBuildInputs = [ ruby ];
optexcount.extraBuildInputs = [ python3 ];
pdfbook2.extraBuildInputs = [ python3 ];
texlogsieve.extraBuildInputs = [ bin.luatex ];
#### perl packages
bundledoc.extraBuildInputs = [
(perl.withPackages (
ps: with ps; [
StringShellQuote
]
))
];
crossrefware.extraBuildInputs = [
(perl.withPackages (
ps: with ps; [
LWP
URI
]
))
];
ctan-o-mat.extraBuildInputs = [
(perl.withPackages (
ps: with ps; [
LWP
LWPProtocolHttps
]
))
];
ctanify.extraBuildInputs = [ (perl.withPackages (ps: with ps; [ FileCopyRecursive ])) ];
ctanupload.extraBuildInputs = [
(perl.withPackages (
ps: with ps; [
HTMLFormatter
WWWMechanize
]
))
];
exceltex.extraBuildInputs = [ (perl.withPackages (ps: with ps; [ SpreadsheetParseExcel ])) ];
latex-git-log.extraBuildInputs = [ (perl.withPackages (ps: with ps; [ IPCSystemSimple ])) ];
latexindent.extraBuildInputs = [
(perl.withPackages (
ps: with ps; [
FileHomeDir
LogDispatch
LogLog4perl
UnicodeLineBreak
YAMLTiny
]
))
];
pax.extraBuildInputs = [ (perl.withPackages (ps: with ps; [ FileWhich ])) ];
pdflatexpicscale.extraBuildInputs = [
(perl.withPackages (
ps: with ps; [
GD
ImageExifTool
]
))
];
ptex-fontmaps.extraBuildInputs = [ (perl.withPackages (ps: with ps; [ Tk ])) ];
purifyeps.extraBuildInputs = [ (perl.withPackages (ps: with ps; [ FileWhich ])) ];
sqltex.extraBuildInputs = [ (perl.withPackages (ps: with ps; [ DBI ])) ];
svn-multi.extraBuildInputs = [ (perl.withPackages (ps: with ps; [ TimeDate ])) ];
texdoctk.extraBuildInputs = [ (perl.withPackages (ps: with ps; [ Tk ])) ];
typog.extraBuildInputs = [ (perl.withPackages (ps: with ps; [ IPCSystemSimple ])) ];
ulqda.extraBuildInputs = [ (perl.withPackages (ps: with ps; [ DigestSHA1 ])) ];
#### python packages
pythontex.extraBuildInputs = [ (python3.withPackages (ps: with ps; [ pygments ])) ];
#### other runtime PATH dependencies
a2ping.extraBuildInputs = [ ghostscript_headless ];
bibexport.extraBuildInputs = [ gnugrep ];
checklistings.extraBuildInputs = [ coreutils ];
cjk-gs-integrate.extraBuildInputs = [ ghostscript_headless ];
cyrillic-bin.extraBuildInputs = [
coreutils
gnused
];
dtxgen.extraBuildInputs = [
coreutils
getopt
gnumake
zip
];
dviljk.extraBuildInputs = [ coreutils ];
epspdf.extraBuildInputs = [ ghostscript_headless ];
epstopdf.extraBuildInputs = [ ghostscript_headless ];
fragmaster.extraBuildInputs = [ ghostscript_headless ];
installfont.extraBuildInputs = [
coreutils
getopt
gnused
];
latexfileversion.extraBuildInputs = [
coreutils
gnugrep
gnused
];
listings-ext.extraBuildInputs = [
coreutils
getopt
];
ltxfileinfo.extraBuildInputs = [
coreutils
getopt
gnused
];
ltximg.extraBuildInputs = [ ghostscript_headless ];
luaotfload.extraBuildInputs = [ ncurses ];
makeindex.extraBuildInputs = [
coreutils
gnused
];
pagelayout.extraBuildInputs = [
gnused
ncurses
];
pdfcrop.extraBuildInputs = [ ghostscript_headless ];
pdftex.extraBuildInputs = [
coreutils
ghostscript_headless
gnused
];
pdftex-quiet.extraBuildInputs = [ coreutils ];
pdfxup.extraBuildInputs = [
coreutils
ghostscript_headless
];
pkfix-helper.extraBuildInputs = [ ghostscript_headless ];
ps2eps.extraBuildInputs = [ ghostscript_headless ];
pst2pdf.extraBuildInputs = [ ghostscript_headless ];
tex4ebook.extraBuildInputs = [ html-tidy ];
texlive-scripts.extraBuildInputs = [ gnused ];
texlive-scripts-extra.extraBuildInputs = [
coreutils
findutils
ghostscript_headless
gnused
];
thumbpdf.extraBuildInputs = [ ghostscript_headless ];
tpic2pdftex.extraBuildInputs = [ gawk ];
wordcount.extraBuildInputs = [
coreutils
gnugrep
];
xdvi.extraBuildInputs = [
coreutils
gnugrep
];
xindy.extraBuildInputs = [ gzip ];
#### adjustments to binaries
# TODO patch the scripts from bin.* directly in bin.* instead of here
# mptopdf is a format link, but not generated by texlinks
# so we add it back to binfiles to generate it from mkPkgBin
mptopdf.binfiles = (orig.mptopdf.binfiles or [ ]) ++ [ "mptopdf" ];
# remove man
texlive-scripts.binfiles = lib.remove "man" orig.texlive-scripts.binfiles;
# xindy is broken on some platforms unfortunately
xindy.binfiles =
if bin ? xindy then lib.subtractLists [ "xindy.mem" "xindy.run" ] orig.xindy.binfiles else [ ];
#### additional symlinks
cluttex.binlinks = {
cllualatex = "cluttex";
clxelatex = "cluttex";
};
context.binlinks = {
context = "luametatex";
"context.lua" = tl.context.tex + "/scripts/context/lua/context.lua";
mtxrun = "luametatex";
"mtxrun.lua" = tl.context.tex + "/scripts/context/lua/mtxrun.lua";
};
context-legacy.binlinks = {
texexec = tl.context-legacy.tex + "/scripts/context/ruby/texexec.rb";
texmfstart = tl.context-legacy.tex + "/scripts/context/ruby/texmfstart.rb";
};
dvipdfmx.binlinks = {
# even though 'ebb' was removed from the Makefile, this symlink is still
# part of the binary container of dvipdfmx
ebb = "xdvipdfmx";
};
epstopdf.binlinks.repstopdf = "epstopdf";
pdfcrop.binlinks.rpdfcrop = "pdfcrop";
# TODO: handle symlinks in bin.core
ptex.binlinks = {
pbibtex = tl.uptex.out + "/bin/upbibtex";
pdvitype = tl.uptex.out + "/bin/updvitype";
ppltotf = tl.uptex.out + "/bin/uppltotf";
ptftopl = tl.uptex.out + "/bin/uptftopl";
};
texdef.binlinks = {
latexdef = "texdef";
};
texlive-scripts.binlinks = {
mktexfmt = "fmtutil";
texhash = tl."texlive.infra".out + "/bin/mktexlsr";
};
texlive-scripts-extra.binlinks = {
allec = "allcm";
kpsepath = "kpsetool";
kpsexpand = "kpsetool";
};
#### add PATH dependencies without wrappers
# TODO deduplicate this code
a2ping.postFixup = ''
sed -i '6i$ENV{PATH}='"'"'${lib.makeBinPath a2ping.extraBuildInputs}'"'"' . ($ENV{PATH} ? ":$ENV{PATH}" : '"'''"');' "$out"/bin/a2ping
'';
bibexport.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath bibexport.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/bibexport
'';
checklistings.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath checklistings.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/checklistings
'';
cjk-gs-integrate.postFixup = ''
sed -i '2i$ENV{PATH}='"'"'${lib.makeBinPath cjk-gs-integrate.extraBuildInputs}'"'"' . ($ENV{PATH} ? ":$ENV{PATH}" : '"'''"');' "$out"/bin/cjk-gs-integrate
'';
cyrillic-bin.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath cyrillic-bin.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/rumakeindex
'';
dtxgen.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath dtxgen.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/dtxgen
'';
dviljk.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath dviljk.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/dvihp
'';
epstopdf.postFixup = ''
sed -i '2i$ENV{PATH}='"'"'${lib.makeBinPath epstopdf.extraBuildInputs}'"'"' . ($ENV{PATH} ? ":$ENV{PATH}" : '"'''"');' "$out"/bin/epstopdf
'';
fragmaster.postFixup = ''
sed -i '2i$ENV{PATH}='"'"'${lib.makeBinPath fragmaster.extraBuildInputs}'"'"' . ($ENV{PATH} ? ":$ENV{PATH}" : '"'''"');' "$out"/bin/fragmaster
'';
installfont.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath installfont.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/installfont-tl
'';
latexfileversion.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath latexfileversion.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/latexfileversion
'';
listings-ext.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath listings-ext.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/listings-ext.sh
'';
ltxfileinfo.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath ltxfileinfo.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/ltxfileinfo
'';
ltximg.postFixup = ''
sed -i '2i$ENV{PATH}='"'"'${lib.makeBinPath ltximg.extraBuildInputs}'"'"' . ($ENV{PATH} ? ":$ENV{PATH}" : '"'''"');' "$out"/bin/ltximg
'';
luaotfload.postFixup = ''
sed -i '2ios.setenv("PATH","${lib.makeBinPath luaotfload.extraBuildInputs}" .. (os.getenv("PATH") and ":" .. os.getenv("PATH") or ""))' "$out"/bin/luaotfload-tool
'';
makeindex.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath makeindex.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/mkindex
'';
pagelayout.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath [ gnused ]}''${PATH:+:$PATH}"' "$out"/bin/pagelayoutapi
sed -i '2iPATH="${lib.makeBinPath [ ncurses ]}''${PATH:+:$PATH}"' "$out"/bin/textestvis
'';
pdfcrop.postFixup = ''
sed -i '2i$ENV{PATH}='"'"'${lib.makeBinPath pdfcrop.extraBuildInputs}'"'"' . ($ENV{PATH} ? ":$ENV{PATH}" : '"'''"');' "$out"/bin/pdfcrop
'';
pdftex.postFixup = ''
sed -i -e '2iPATH="${
lib.makeBinPath [
coreutils
gnused
]
}''${PATH:+:$PATH}"' \
-e 's!^distillerpath="/usr/local/bin"$!distillerpath="${
lib.makeBinPath [ ghostscript_headless ]
}"!' \
"$out"/bin/simpdftex
'';
pdftex-quiet.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath pdftex-quiet.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/pdftex-quiet
'';
pdfxup.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath pdfxup.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/pdfxup
'';
pkfix-helper.postFixup = ''
sed -i '2i$ENV{PATH}='"'"'${lib.makeBinPath pkfix-helper.extraBuildInputs}'"'"' . ($ENV{PATH} ? ":$ENV{PATH}" : '"'''"');' "$out"/bin/pkfix-helper
'';
ps2eps.postFixup = ''
sed -i '2i$ENV{PATH}='"'"'${lib.makeBinPath ps2eps.extraBuildInputs}'"'"' . ($ENV{PATH} ? ":$ENV{PATH}" : '"'''"');' "$out"/bin/ps2eps
'';
pst2pdf.postFixup = ''
sed -i '2i$ENV{PATH}='"'"'${lib.makeBinPath pst2pdf.extraBuildInputs}'"'"' . ($ENV{PATH} ? ":$ENV{PATH}" : '"'''"');' "$out"/bin/pst2pdf
'';
tex4ebook.postFixup = ''
sed -i '2ios.setenv("PATH","${lib.makeBinPath tex4ebook.extraBuildInputs}" .. (os.getenv("PATH") and ":" .. os.getenv("PATH") or ""))' "$out"/bin/tex4ebook
'';
texlive-scripts.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath texlive-scripts.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/{fmtutil-user,mktexmf,mktexpk,mktextfm,updmap-user}
'';
thumbpdf.postFixup = ''
sed -i '2i$ENV{PATH}='"'"'${lib.makeBinPath thumbpdf.extraBuildInputs}'"'"' . ($ENV{PATH} ? ":$ENV{PATH}" : '"'''"');' "$out"/bin/thumbpdf
'';
tpic2pdftex.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath tpic2pdftex.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/tpic2pdftex
'';
wordcount.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath wordcount.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/wordcount
'';
# TODO patch in bin.xdvi
xdvi.postFixup = ''
sed -i '2iPATH="${lib.makeBinPath xdvi.extraBuildInputs}''${PATH:+:$PATH}"' "$out"/bin/xdvi
'';
xindy.postFixup = ''
sed -i '2i$ENV{PATH}='"'"'${lib.makeBinPath xindy.extraBuildInputs}'"'"' . ($ENV{PATH} ? ":$ENV{PATH}" : '"'''"');' "$out"/bin/{texindy,xindy}
'';
#### other script fixes
# misc tab and python3 fixes
ebong.postFixup = ''
sed -Ei 's/import sre/import re/; s/file\(/open(/g; s/\t/ /g; s/print +(.*)$/print(\1)/g' "$out"/bin/ebong
'';
# find files in script directory, not binary directory
# add runtime dependencies to PATH
epspdf.postFixup = ''
sed -i '2ios.setenv("PATH","${lib.makeBinPath epspdf.extraBuildInputs}" .. (os.getenv("PATH") and ":" .. os.getenv("PATH") or ""))' "$out"/bin/epspdf
substituteInPlace "$out"/bin/epspdftk --replace-fail '[info script]' "\"$scriptsFolder/epspdftk.tcl\""
'';
# use correct path to xdvipdfmx
extractbb.extraBuildInputs = [ bin.core.dvipdfmx ];
extractbb.postUnpack = ''
if [[ -f "$out"/scripts/extractbb/extractbb-wrapper.lua ]] ; then
sed -i 's!local target_path = interpreter_dir .. "/" .. TARGET_PATH_NAME .. target_ext!local target_path = os.getenv("NIX_TEXLIVE_XDVIPDFMX")!' "$out"/scripts/extractbb/extractbb-wrapper.lua
fi
'';
extractbb.postFixup = ''
sed -i "2ios.setenv('NIX_TEXLIVE_XDVIPDFMX','$(PATH="$HOST_PATH" command -v xdvipdfmx)')" "$out"/bin/extractbb
'';
# find files in script directory, not in binary directory
latexindent.postFixup = ''
substituteInPlace "$out"/bin/latexindent --replace-fail 'use FindBin;' "BEGIN { \$0 = '$scriptsFolder' . '/latexindent.pl'; }; use FindBin;"
'';
# find files in script directory, not in binary directory
minted.postFixup = ''
substituteInPlace "$out"/bin/latexminted --replace-fail "__file__" "\"$scriptsFolder/latexminted.py\""
'';
# find files in source container, fix incompatibilities with snobol4
texaccents.postFixup = ''
sed -i '1s!$! -I${tl.texaccents.texsource}/source/support/texaccents!' "$out"/bin/*
'';
texaccents.postUnpack = ''
if [[ -f "$out"/source/support/texaccents/grepl.inc ]] ; then
sed -i 's!^-include "repl.inc"!-include "repl.sno"!' "$out"/source/support/texaccents/grepl.inc
elif [[ -f "$out"/scripts/texaccents/texaccents.sno ]] ; then
sed -i -e 's!^-include "host.inc"!-include "host.sno"!' \
-e 's/host(2,2)/host(2,host(3))/g' \
-e 's/host(2,3)/host(2,host(3) + 1)/g' \
"$out"/scripts/texaccents/texaccents.sno
fi
'';
# flag lua dependency
texblend.scriptExts = [ "lua" ];
# Patch texlinks.sh back to 2015 version;
# otherwise some bin/ links break, e.g. xe(la)tex.
# add runtime dependencies to PATH
texlive-scripts-extra.postFixup = ''
patch -R "$out"/bin/texlinks < '${./texlinks.diff}'
sed -i '2iPATH="${lib.makeBinPath [ coreutils ]}''${PATH:+:$PATH}"' "$out"/bin/{allcm,dvired,mkocp,ps2frag}
sed -i '2iPATH="${
lib.makeBinPath [
coreutils
findutils
]
}''${PATH:+:$PATH}"' "$out"/bin/allneeded
sed -i '2iPATH="${
lib.makeBinPath [
coreutils
ghostscript_headless
]
}''${PATH:+:$PATH}"' "$out"/bin/dvi2fax
sed -i '2iPATH="${lib.makeBinPath [ gnused ]}''${PATH:+:$PATH}"' "$out"/bin/{kpsetool,texconfig,texconfig-sys}
sed -i '2iPATH="${
lib.makeBinPath [
coreutils
gnused
]
}''${PATH:+:$PATH}"' "$out"/bin/texconfig-dialog
'';
# patch interpreter
texosquery.postFixup = ''
substituteInPlace "$out"/bin/* --replace-fail java "$interpJava"
'';
# hardcode revision numbers (since texlive.infra, tlshell are not in either system or user texlive.tlpdb)
tlshell.postFixup = ''
substituteInPlace "$out"/bin/tlshell \
--replace-fail '[dict get $::pkgs texlive.infra localrev]' '${
toString orig."texlive.infra".revision
}' \
--replace-fail '[dict get $::pkgs tlshell localrev]' '${toString orig.tlshell.revision}'
'';
#### dependency changes
# Since 2025 OpTeX is based on luahbtex
optex.deps = (orig.optex.deps or [ ]) ++ [ "luahbtex" ];
# Since the packaging change for ConTeXt, context-legacy is missing the xetex dependency
context-legacy.deps = (orig.context-legacy.deps or [ ]) ++ [ "xetex" ];
# it seems to need it to transform fonts
xdvi.deps = (orig.xdvi.deps or [ ]) ++ [ "metafont" ];
mltex.deps = (orig.mltex.deps or [ ]) ++ [ "pdftex" ];
# remove dependency-heavy packages from the basic collections
collection-basic.deps = lib.subtractLists [ "metafont" "xdvi" ] orig.collection-basic.deps;
# add them elsewhere so that collections cover all packages
collection-metapost.deps = orig.collection-metapost.deps ++ [ "metafont" ];
collection-plaingeneric.deps = orig.collection-plaingeneric.deps ++ [ "xdvi" ];
#### misc
# FIXME: remove when https://github.com/borisveytsman/crossrefware/pull/17 is merged and included on CTAN
# Typo introduced in https://github.com/borisveytsman/crossrefware/commit/1e67e9773b3d3be983be156e2200478bc263dd93
crossrefware.postUnpack = ''
if [[ -f "$out"/scripts/crossrefware/ltx2crossrefxml.pl ]] ; then
sed -i 's/use IO::file;/use IO::File;/' "$out"/scripts/crossrefware/ltx2crossrefxml.pl
fi
'';
# RISC-V: https://github.com/LuaJIT/LuaJIT/issues/628
luajittex.binfiles = lib.optionals (lib.meta.availableOn stdenv.hostPlatform luajit) orig.luajittex.binfiles;
texdoc = {
extraRevision = "-tlpdb${toString tlpdbVersion.revision}";
extraVersion = "-tlpdb-${toString tlpdbVersion.revision}";
extraNativeBuildInputs = [ installShellFiles ];
# build Data.tlpdb.lua (part of the 'tlType == "run"' package)
postUnpack = ''
if [[ -f "$out"/scripts/texdoc/texdoc.tlu ]]; then
unxz --stdout "${tlpdbxz}" > texlive.tlpdb
# create dummy doc file to ensure that texdoc does not return an error
mkdir -p support/texdoc
touch support/texdoc/NEWS
TEXMFCNF="${tl.kpathsea.tex}/web2c" TEXMF="$out" TEXDOCS=. TEXMFVAR=. \
"${bin.luatex}"/bin/texlua "$out"/scripts/texdoc/texdoc.tlu \
-c texlive_tlpdb=texlive.tlpdb -lM texdoc
cp texdoc/cache-tlpdb.lua "$out"/scripts/texdoc/Data.tlpdb.lua
fi
'';
# install zsh completion
postFixup = ''
TEXMFCNF="${tl.kpathsea.tex}"/web2c TEXMF="$scriptsFolder/../.." \
texlua "$out"/bin/texdoc --print-completion zsh > "$TMPDIR"/_texdoc
installShellCompletion --zsh "$TMPDIR"/_texdoc
'';
};
"texlive.infra" = {
extraRevision = ".tlpdb${toString tlpdbVersion.revision}";
extraVersion = "-tlpdb-${toString tlpdbVersion.revision}";
# add license of tlmgr and TeXLive::* perl packages and of bin.core
license = [
"gpl2Plus"
]
++ lib.toList bin.core.meta.license.shortName
++ orig."texlive.infra".license or [ ];
scriptsFolder = "texlive";
extraBuildInputs = [
coreutils
gnused
gnupg
tl.kpathsea
(perl.withPackages (ps: with ps; [ Tk ]))
];
# make tlmgr believe it can use kpsewhich to evaluate TEXMFROOT
postFixup = ''
substituteInPlace "$out"/bin/tlmgr \
--replace-fail 'if (-r "$bindir/$kpsewhichname")' 'if (1)'
sed -i '2i$ENV{PATH}='"'"'${lib.makeBinPath [ gnupg ]}'"'"' . ($ENV{PATH} ? ":$ENV{PATH}" : '"'''"');' "$out"/bin/tlmgr
sed -i '2iPATH="${
lib.makeBinPath [
coreutils
gnused
tl.kpathsea
]
}''${PATH:+:$PATH}"' "$out"/bin/mktexlsr
'';
# add minimal texlive.tlpdb
postUnpack = ''
if [[ -d "$out"/TeXLive ]] ; then
xzcat "${tlpdbxz}" | sed -n -e '/^name \(00texlive.config\|00texlive.installation\)$/,/^$/p' > "$out"/texlive.tlpdb
fi
'';
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,209 @@
From 2da802031f7b7f2c9f5327b5155af9aec0d02686 Mon Sep 17 00:00:00 2001
From: Christoph Jabs <contact@christophjabs.info>
Date: Tue, 1 Jul 2025 13:05:54 +0300
Subject: [PATCH] truncate luajit version number
---
libs/luajit/configure | 24 ++++++++++++------------
libs/luajit/native/configure | 20 ++++++++++----------
libs/luajit/version.ac | 2 +-
3 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/libs/luajit/configure b/libs/luajit/configure
index c1bc09c039..2ba3598fb8 100755
--- a/libs/luajit/configure
+++ b/libs/luajit/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.72 for luajit for TeX Live 2.1.81742.
+# Generated by GNU Autoconf 2.72 for luajit for TeX Live 2.1.736.
#
# Report bugs to <tex-k@tug.org>.
#
@@ -614,8 +614,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='luajit for TeX Live'
PACKAGE_TARNAME='luajit-for-tex-live'
-PACKAGE_VERSION='2.1.81742'
-PACKAGE_STRING='luajit for TeX Live 2.1.81742'
+PACKAGE_VERSION='2.1.736'
+PACKAGE_STRING='luajit for TeX Live 2.1.736'
PACKAGE_BUGREPORT='tex-k@tug.org'
PACKAGE_URL=''
@@ -1385,7 +1385,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-'configure' configures luajit for TeX Live 2.1.81742 to adapt to many kinds of systems.
+'configure' configures luajit for TeX Live 2.1.736 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1457,7 +1457,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of luajit for TeX Live 2.1.81742:";;
+ short | recursive ) echo "Configuration of luajit for TeX Live 2.1.736:";;
esac
cat <<\_ACEOF
@@ -1578,7 +1578,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-luajit for TeX Live configure 2.1.81742
+luajit for TeX Live configure 2.1.736
generated by GNU Autoconf 2.72
Copyright (C) 2023 Free Software Foundation, Inc.
@@ -2134,7 +2134,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by luajit for TeX Live $as_me 2.1.81742, which was
+It was created by luajit for TeX Live $as_me 2.1.736, which was
generated by GNU Autoconf 2.72. Invocation command line was
$ $0$ac_configure_args_raw
@@ -5102,7 +5102,7 @@ fi
# Define the identity of the package.
PACKAGE='luajit-for-tex-live'
- VERSION='2.1.81742'
+ VERSION='2.1.736'
printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -6703,10 +6703,10 @@ printf "%s\n" "no, using $LN_S" >&6; }
fi
-LUAJITVERSION=2.1.81742
+LUAJITVERSION=2.1.736
-LUAJIT_LT_VERSINFO=3:81742:1
+LUAJIT_LT_VERSINFO=3:736:1
case `pwd` in
@@ -17377,7 +17377,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by luajit for TeX Live $as_me 2.1.81742, which was
+This file was extended by luajit for TeX Live $as_me 2.1.736, which was
generated by GNU Autoconf 2.72. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -17445,7 +17445,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
-luajit for TeX Live config.status 2.1.81742
+luajit for TeX Live config.status 2.1.736
configured by $0, generated by GNU Autoconf 2.72,
with options \\"\$ac_cs_config\\"
diff --git a/libs/luajit/native/configure b/libs/luajit/native/configure
index 23c4d29bf0..8f9c93f8ff 100755
--- a/libs/luajit/native/configure
+++ b/libs/luajit/native/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.72 for luajit native 2.1.81742.
+# Generated by GNU Autoconf 2.72 for luajit native 2.1.736.
#
# Report bugs to <tex-k@tug.org>.
#
@@ -604,8 +604,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='luajit native'
PACKAGE_TARNAME='luajit-native'
-PACKAGE_VERSION='2.1.81742'
-PACKAGE_STRING='luajit native 2.1.81742'
+PACKAGE_VERSION='2.1.736'
+PACKAGE_STRING='luajit native 2.1.736'
PACKAGE_BUGREPORT='tex-k@tug.org'
PACKAGE_URL=''
@@ -1316,7 +1316,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-'configure' configures luajit native 2.1.81742 to adapt to many kinds of systems.
+'configure' configures luajit native 2.1.736 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1387,7 +1387,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of luajit native 2.1.81742:";;
+ short | recursive ) echo "Configuration of luajit native 2.1.736:";;
esac
cat <<\_ACEOF
@@ -1484,7 +1484,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-luajit native configure 2.1.81742
+luajit native configure 2.1.736
generated by GNU Autoconf 2.72
Copyright (C) 2023 Free Software Foundation, Inc.
@@ -1883,7 +1883,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by luajit native $as_me 2.1.81742, which was
+It was created by luajit native $as_me 2.1.736, which was
generated by GNU Autoconf 2.72. Invocation command line was
$ $0$ac_configure_args_raw
@@ -4851,7 +4851,7 @@ fi
# Define the identity of the package.
PACKAGE='luajit-native'
- VERSION='2.1.81742'
+ VERSION='2.1.736'
printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -6905,7 +6905,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by luajit native $as_me 2.1.81742, which was
+This file was extended by luajit native $as_me 2.1.736, which was
generated by GNU Autoconf 2.72. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -6973,7 +6973,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
-luajit native config.status 2.1.81742
+luajit native config.status 2.1.736
configured by $0, generated by GNU Autoconf 2.72,
with options \\"\$ac_cs_config\\"
diff --git a/libs/luajit/version.ac b/libs/luajit/version.ac
index 4aac6497c1..534f508733 100644
--- a/libs/luajit/version.ac
+++ b/libs/luajit/version.ac
@@ -11,4 +11,4 @@ dnl m4-include this file to define the current luajit version
dnl m4_define([luajit_version], [2.1.1736781742])
dnl libtool: error: REVISION '1736781742' must be a nonnegative integer
dnl libtool: error: '3:1736781742:1' is not valid version information
-m4_define([luajit_version], [2.1.81742])
+m4_define([luajit_version], [2.1.736])
--
2.49.0

View File

@@ -0,0 +1,55 @@
{
lib,
mkDerivation,
fetchFromGitHub,
qmake,
qttools,
qtbase,
poppler,
flex,
bison,
}:
mkDerivation {
pname = "tikzit";
version = "2.1.6";
src = fetchFromGitHub {
owner = "tikzit";
repo = "tikzit";
rev = "v2.1.6";
sha256 = "0ba99pgv54pj1xvhrwn9db2w0v4h07vsjajcnhpa2smy88ypg32h";
};
nativeBuildInputs = [
qmake
qttools
flex
bison
];
buildInputs = [
qtbase
poppler
];
# src/data/tikzlexer.l:29:10: fatal error: tikzparser.parser.hpp: No such file or directory
enableParallelBuilding = false;
meta = with lib; {
description = "Graphical tool for rapidly creating graphs and diagrams using PGF/TikZ";
longDescription = ''
TikZiT is a simple GUI editor for graphs and string diagrams.
Its native file format is a subset of PGF/TikZ, which means TikZiT files
can be included directly in papers typeset using LaTeX.
For preview support the texlive package 'preview' has to be installed.
'';
homepage = "https://tikzit.github.io/";
license = licenses.gpl3Plus;
platforms = platforms.all;
maintainers = [
maintainers.iblech
maintainers.mgttlinger
];
mainProgram = "tikzit";
};
}

View File

@@ -0,0 +1,96 @@
{
autoreconfHook,
bash,
coreutils,
docbook_xml_dtd_45,
docbook_xsl,
docbook-xsl-nons,
fetchgit,
findutils,
flex,
getopt,
gnugrep,
gnused,
lib,
libxml2,
libxslt,
makeWrapper,
stdenv,
testers,
w3m,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "xmlto";
version = "0.0.29";
src = fetchgit {
url = "https://pagure.io/xmlto.git";
rev = finalAttrs.version;
hash = "sha256-wttag8J1t9cBPBHNY7me2H0IPOzS8IjfCLIHNWq67Do=";
};
postPatch = ''
patchShebangs xmlif/test/run-test
substituteInPlace "xmlto.in" \
--replace-fail "@XMLTO_BASH_PATH@" "${bash}/bin/bash" \
--replace-fail "@FIND@" "${findutils}/bin/find" \
--replace-fail "@GETOPT@" "${getopt}/bin/getopt" \
--replace-fail "@GREP@" "${gnugrep}/bin/grep" \
--replace-fail "@MKTEMP@" "$(type -P mktemp)" \
--replace-fail "@SED@" "${gnused}/bin/sed" \
--replace-fail "@TAIL@" "${coreutils}/bin/tail"
for f in format/docbook/* xmlto.in; do
substituteInPlace $f \
--replace-fail "http://docbook.sourceforge.net/release/xsl/current" "${docbook-xsl-nons}/xml/xsl/docbook"
done
'';
strictDeps = true;
# `libxml2' provides `xmllint', needed at build-time and run-time.
# `libxslt' provides `xsltproc', used by `xmlto' at run-time.
nativeBuildInputs = [
autoreconfHook
makeWrapper
getopt
libxml2
libxslt
];
postInstall = ''
# `w3m' is needed for HTML to text conversions.
wrapProgram "$out/bin/xmlto" \
--prefix PATH : "${
lib.makeBinPath [
libxslt
libxml2
getopt
w3m
]
}"
'';
passthru.tests.version = testers.testVersion {
command = "${lib.getExe finalAttrs.finalPackage} --version";
package = finalAttrs.finalPackage;
};
meta = {
changelog = "https://pagure.io/xmlto/blob/master/f/ChangeLog";
description = "Front-end to an XSL toolchain";
homepage = "https://pagure.io/xmlto/";
license = lib.licenses.gpl2Plus;
longDescription = ''
xmlto is a front-end to an XSL toolchain. It chooses an
appropriate stylesheet for the conversion you want and applies
it using an external XSL-T processor. It also performs any
necessary post-processing.
'';
mainProgram = "xmlto";
maintainers = [ ];
platforms = lib.platforms.unix;
};
})