192 lines
5.1 KiB
Nix
192 lines
5.1 KiB
Nix
{
|
|
lib,
|
|
config,
|
|
hasSystem,
|
|
pkgs,
|
|
flakeInputs,
|
|
...
|
|
}:
|
|
let
|
|
compileTypst =
|
|
{
|
|
pkgs,
|
|
# package to take the typst binary from
|
|
typstPackage ? pkgs.typst,
|
|
# possible values: pdf, png, svg, html, bundle
|
|
format ? "pdf",
|
|
# root of the typst project
|
|
rootDir,
|
|
# main typst file
|
|
entrypoint ? "${rootDir}/main.typ",
|
|
# lockfile, representing the dependencies
|
|
lockfile ? "${rootDir}/typst.lock",
|
|
# exposed in Typst as `sys.inputs`. must be an attrset of strings
|
|
inputs ? { },
|
|
# exposed in Typst as `sys.inputs`. must be an attrset of paths
|
|
inputFiles ? { },
|
|
# paths to fonts
|
|
fontPaths ? [ ],
|
|
# if set, Typst's own embedded fonts will be ignored
|
|
ignoreEmbeddedFonts ? false,
|
|
# UNIX timestamp exposed by datetime functions
|
|
creationTimestamp ? 0,
|
|
# pretty-format the output
|
|
pretty ? false,
|
|
pages ? null,
|
|
# see typst c --help
|
|
noPdfTags ? false,
|
|
# see typst c --help
|
|
ppi ? 144,
|
|
features ? [ ],
|
|
...
|
|
}:
|
|
let
|
|
typstPackage' = if builtins.isFunction typstPackage then typstPackage pkgs else typstPackage;
|
|
|
|
inputArgs = lib.flatten (
|
|
lib.mapAttrsToList (key: value: [
|
|
"--input"
|
|
"${key}=${builtins.toJSON value}"
|
|
]) inputs
|
|
);
|
|
inputFileArgs = lib.mapAttrsToList (
|
|
key: path:
|
|
" --input " + lib.escapeShellArg key + "=\"$(cat " + lib.escapeShellArg (toString path) + ")\""
|
|
) inputFiles;
|
|
|
|
args = [
|
|
"typst"
|
|
"compile"
|
|
"--format"
|
|
format
|
|
"--root"
|
|
rootDir
|
|
"--ignore-system-fonts"
|
|
"--package-path"
|
|
"/dev/null"
|
|
"--package-cache-path"
|
|
".cache/typst"
|
|
"--creation-timestamp"
|
|
(builtins.toString creationTimestamp)
|
|
"--ppi"
|
|
(builtins.toString ppi)
|
|
]
|
|
++ inputArgs
|
|
++ (
|
|
if (builtins.length fontPaths) > 0 then
|
|
[
|
|
"--font-path"
|
|
(lib.concatStringsSep ":" fontPaths)
|
|
]
|
|
else
|
|
[ ]
|
|
)
|
|
++ (if ignoreEmbeddedFonts then [ "--ignore-embedded-fonts" ] else [ ])
|
|
++ (if pretty then [ "--pretty" ] else [ ])
|
|
++ (
|
|
if (pages != null) then
|
|
[
|
|
"--pages"
|
|
pages
|
|
]
|
|
else
|
|
[ ]
|
|
)
|
|
++ (if noPdfTags then [ "--no-pdf-tags" ] else [ ])
|
|
++ (
|
|
if (builtins.length features) > 0 then
|
|
[
|
|
"--features"
|
|
(lib.concatStringsSep "," features)
|
|
]
|
|
else
|
|
[ ]
|
|
)
|
|
++ [ entrypoint ];
|
|
ext = if format == "bundle" then "" else ".${format}";
|
|
|
|
dependencies = builtins.fromJSON (builtins.readFile lockfile);
|
|
parseSpec =
|
|
spec:
|
|
let
|
|
parts = builtins.match "@([^/]+)/([^:]+):(.+)" spec;
|
|
in
|
|
assert lib.assertMsg (parts != null) "${spec} is not a valid package spec";
|
|
{
|
|
namespace = builtins.elemAt parts 0;
|
|
name = builtins.elemAt parts 1;
|
|
version = builtins.elemAt parts 2;
|
|
};
|
|
previewPackage =
|
|
{
|
|
name,
|
|
version,
|
|
hash,
|
|
}:
|
|
builtins.fetchTarball {
|
|
url = "https://packages.typst.org/preview/${name}-${version}.tar.gz";
|
|
sha256 = hash;
|
|
};
|
|
linkPackage =
|
|
entry:
|
|
let
|
|
spec = parseSpec entry.spec;
|
|
storeDir = previewPackage {
|
|
name = spec.name;
|
|
version = spec.version;
|
|
hash = entry.hash;
|
|
};
|
|
in
|
|
assert lib.assertMsg (
|
|
spec.namespace == "preview"
|
|
) "only packages from @preview are supported at the moment";
|
|
''
|
|
mkdir -p .cache/typst/preview/${spec.name}
|
|
ln -s ${storeDir} .cache/typst/preview/${spec.name}/${spec.version}
|
|
'';
|
|
linkDeps = lib.concatStringsSep "\n" (map linkPackage dependencies.packages);
|
|
in
|
|
assert lib.assertMsg (builtins.isAttrs inputs) "`inputs` must be an attrset";
|
|
assert lib.assertMsg (builtins.isAttrs inputFiles) "`inputFiles` must be an attrset";
|
|
pkgs.stdenv.mkDerivation {
|
|
name = "out${ext}";
|
|
src = rootDir;
|
|
buildInputs = with pkgs; [
|
|
coreutils
|
|
typstPackage'
|
|
];
|
|
buildPhase = ''
|
|
#!/bin/bash
|
|
set -euo pipefail
|
|
TMP="$(mktemp -d)"
|
|
cd "$TMP"
|
|
export HOME="$TMP"
|
|
${linkDeps}
|
|
${lib.escapeShellArgs args}${lib.concatStringsSep " " inputFileArgs} - >$out
|
|
'';
|
|
};
|
|
|
|
compileTypstSys = args: compileTypst ({ inherit pkgs; } // args);
|
|
|
|
naersk = flakeInputs.naersk;
|
|
naersk' = pkgs.callPackage naersk { };
|
|
typstLock = naersk'.buildPackage {
|
|
src = ./..;
|
|
buildInputs = [ pkgs.gcc ];
|
|
};
|
|
in
|
|
lib.recursiveUpdate
|
|
{
|
|
config.lib.compileTypst = if hasSystem then compileTypstSys else compileTypst;
|
|
}
|
|
(
|
|
lib.optionalAttrs hasSystem {
|
|
config.checks.testSimple = compileTypstSys {
|
|
rootDir = ../tests/simple;
|
|
};
|
|
config.packages.default = typstLock;
|
|
config.apps.default = {
|
|
program = "${typstLock}/bin/typst-lock";
|
|
};
|
|
}
|
|
)
|