{ pkgs ? import { } }: let inherit (pkgs) lib; package = pkgs.runCommand "typst_web_magic-0.1.0" { } '' destination="$out/share/typst/packages/local/typst_web_magic/0.1.0" mkdir -p "$destination" cp ${./lib.typ} "$destination/lib.typ" cp ${./pdf.typ} "$destination/pdf.typ" cp ${./metadata.typ} "$destination/metadata.typ" cp ${./blog.typ} "$destination/blog.typ" cp ${./default.css} "$destination/default.css" cp -r ${./color} "$destination/color" cp ${./typst.toml} "$destination/typst.toml" ''; files = directory: let entries = builtins.readDir directory; in lib.concatMap (name: if entries.${name} == "directory" then map (child: "${name}/${child}") (files (directory + "/${name}")) else lib.optional (entries.${name} == "regular") name ) (builtins.attrNames entries); content = src: let pages = builtins.filter (lib.hasSuffix ".typ") (files (src + "/src")); assets = directory: prefix: if builtins.pathExists (src + "/${directory}") then map (file: '' (path: ${builtins.toJSON (prefix + file)}, source: path(${builtins.toJSON "/${directory}/${file}"})), '') (files (src + "/${directory}")) else []; in pkgs.writeText "content.typ" '' #let pages = ( ${lib.concatMapStrings (file: '' (path: ${builtins.toJSON (lib.removeSuffix ".typ" file + ".html")}, entry: { import ${builtins.toJSON "/src/${file}"} as source source.entry }, body: include ${builtins.toJSON "/src/${file}"}), '') pages} ) #let assets = ( ${lib.concatStrings (assets "assets" "assets/" ++ assets "public" "")} ) ''; clean = src: lib.cleanSourceWith { src = lib.cleanSource src; filter = path: type: let name = baseNameOf path; in !(builtins.elem name [ "site" ".generated" ".jj" "__pycache__" ]) && !(lib.hasPrefix "result" name); }; environment = fonts: { nativeBuildInputs = [ pkgs.typst ]; TYPST_PACKAGE_PATH = "${package}/share/typst/packages"; TYPST_FONT_PATHS = lib.makeSearchPath "share/fonts" ([ pkgs.montserrat pkgs.fira-math ] ++ fonts); }; mkSite = { src, name ? "website", fonts ? [] }: let source = clean src; prepare = '' mkdir -p .generated cp -f ${content (toString source)} .generated/content.typ ''; in pkgs.stdenvNoCC.mkDerivation ((environment fonts) // { pname = name; version = "0.1.0"; src = source; shellHook = prepare; passthru.shell = pkgs.mkShell ((environment fonts) // { packages = [ pkgs.tinymist ]; shellHook = prepare; }); buildPhase = '' runHook preBuild ${prepare} typst compile --format bundle --features bundle,html site.typ site runHook postBuild ''; installPhase = '' runHook preInstall mkdir -p "$out" cp -r site/. "$out/" runHook postInstall ''; }); mkPdf = { src, name ? "document", main ? "main.typ", fonts ? [] }: pkgs.stdenvNoCC.mkDerivation ((environment fonts) // { pname = name; version = "0.1.0"; src = clean src; passthru.shell = pkgs.mkShell ((environment fonts) // { packages = [ pkgs.tinymist ]; }); buildPhase = '' runHook preBuild typst compile --root . ${lib.escapeShellArg main} document.pdf runHook postBuild ''; installPhase = '' runHook preInstall mkdir -p "$out" cp document.pdf "$out/"${lib.escapeShellArg (name + ".pdf")} runHook postInstall ''; }); in { inherit package mkSite mkPdf; init = pkgs.writeShellApplication { name = "typst-web-init"; runtimeInputs = [ pkgs.coreutils ]; text = '' if [ "$#" -ne 1 ]; then echo "Usage: typst-web-init DIRECTORY" >&2 exit 1 fi destination="$1" mkdir -- "$destination" cp -R --no-preserve=mode ${./template}/. "$destination/" echo "Created $destination. Edit site.typ, then run nix-build inside it." ''; }; }