--- /dev/null
+*.epub filter=git-crypt diff=git-crypt
+*.pdf filter=git-crypt diff=git-crypt
--- /dev/null
+#!/usr/bin/env nix
+#! nix shell --impure --expr ``
+#! nix with (builtins.getFlake "git+file://${toString ./../..}/..").packages.${builtins.currentSystem};
+#! nix [
+#! nix (haskellPackages.ghcWithPackages (
+#! nix haskellPackages: [
+#! nix haskellPackages.pandoc-types
+#! nix ]
+#! nix ))
+#! nix ]
+#! nix ``
+#! nix --command runhaskell
+
+{-#LANGUAGE OverloadedStrings#-}
+{-#LANGUAGE ViewPatterns #-}
+import Text.Pandoc.JSON
+import Data.List qualified as List
+import Data.Text qualified as Text
+
+main :: IO ()
+main = toJSONFilter filt
+
+filt :: Block -> Block
+-- Put chapter images into the chapter
+filt (Div as@(_, ["Section1"], _) es) = Div as (fixChapterImage es)
+-- Remove useless images
+filt (Para (Image _ _ ("Images/philos0.jpg", _):_)) = Para []
+filt x = x
+
+fixChapterImage (p@(Para
+ [ Span
+ ( _ , _ , _ )
+ (Image ( _ , _ , _ ) _ ( Text.isPrefixOf "Images/Chapter" -> True , _ )
+ :_)
+ ])
+ :h@Header{}
+ :xs
+ ) = h:p:xs
+fixChapterImage (x:xs) = x:fixChapterImage xs
+fixChapterImage [] = []
+
+-- vim: syntax=haskell
--- /dev/null
+{
+ "nodes": {
+ "flake-compat": {
+ "flake": false,
+ "locked": {
+ "lastModified": 1696426674,
+ "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
+ "owner": "edolstra",
+ "repo": "flake-compat",
+ "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
+ "type": "github"
+ },
+ "original": {
+ "owner": "edolstra",
+ "repo": "flake-compat",
+ "type": "github"
+ }
+ },
+ "gitignore": {
+ "inputs": {
+ "nixpkgs": [
+ "pre-commit-hooks",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1709087332,
+ "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
+ "owner": "hercules-ci",
+ "repo": "gitignore.nix",
+ "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
+ "type": "github"
+ },
+ "original": {
+ "owner": "hercules-ci",
+ "repo": "gitignore.nix",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1734323986,
+ "narHash": "sha256-m/lh6hYMIWDYHCAsn81CDAiXoT3gmxXI9J987W5tZrE=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "394571358ce82dff7411395829aa6a3aad45b907",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixos-24.11",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "pre-commit-hooks": {
+ "inputs": {
+ "flake-compat": "flake-compat",
+ "gitignore": "gitignore",
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1737465171,
+ "narHash": "sha256-R10v2hoJRLq8jcL4syVFag7nIGE7m13qO48wRIukWNg=",
+ "owner": "cachix",
+ "repo": "pre-commit-hooks.nix",
+ "rev": "9364dc02281ce2d37a1f55b6e51f7c0f65a75f17",
+ "type": "github"
+ },
+ "original": {
+ "owner": "cachix",
+ "repo": "pre-commit-hooks.nix",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "nixpkgs": "nixpkgs",
+ "pre-commit-hooks": "pre-commit-hooks"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
--- /dev/null
+{
+ description = "books";
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
+ pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs";
+ pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix";
+ };
+
+ outputs =
+ inputs:
+ let
+ inherit (inputs.nixpkgs) lib;
+ forAllSystems =
+ f:
+ lib.genAttrs lib.systems.flakeExposed (
+ system:
+ f rec {
+ inherit system;
+ pkgs = inputs.nixpkgs.legacyPackages.${system};
+ }
+ );
+ in
+ {
+ # nix -L build .#hello
+ packages = forAllSystems ({ pkgs, ... }: pkgs);
+
+ # nix -L develop or direnv allow
+ devShell = forAllSystems (
+ {
+ pkgs,
+ system,
+ ...
+ }:
+ pkgs.mkShell {
+ name = "shell";
+ src = null;
+ buildInputs = [
+ pkgs.fontconfig
+ #pkgs.gitFull
+ pkgs.jq
+ pkgs.pandoc
+ pkgs.reuse
+ pkgs.shellcheck
+ ];
+ inherit (inputs.self.checks.${system}.pre-commit-check) shellHook;
+ }
+ );
+
+ # nix flake check
+ checks = forAllSystems (
+ args: with args; {
+ pre-commit-check = inputs.pre-commit-hooks.lib.${system}.run {
+ src = inputs.self;
+ hooks = {
+ nixfmt-rfc-style.enable = true;
+ };
+ };
+ }
+ );
+ };
+}
--- /dev/null
+#!/usr/bin/env nix
+#! nix shell --impure --expr ``
+#! nix with (builtins.getFlake "git+file://${toString ./.}/..").packages.${builtins.currentSystem};
+#! nix let fonts = [
+#! nix pkgs.comic-mono
+#! nix pkgs.crimson
+#! nix pkgs.dejavu_fonts
+#! nix pkgs.fira-code
+#! nix pkgs.freefont_ttf
+#! nix pkgs.gyre-fonts # TrueType substitutes for standard PostScript fonts
+#! nix pkgs.hack-font
+#! nix pkgs.liberation_ttf
+#! nix pkgs.lmodern
+#! nix pkgs.noto-fonts-emoji
+#! nix pkgs.tex-gyre.adventor
+#! nix pkgs.tex-gyre.bonum
+#! nix pkgs.tex-gyre.chorus
+#! nix pkgs.tex-gyre.cursor
+#! nix pkgs.tex-gyre.heros
+#! nix pkgs.tex-gyre.pagella
+#! nix pkgs.tex-gyre.schola
+#! nix pkgs.tex-gyre.termes
+#! nix pkgs.unifont
+#! nix ]; in
+#! nix [
+#! nix (pkgs.writeShellScriptBin "interpreter" ''
+#! nix # used by luaotfload (lualatex)
+#! nix export OSFONTDIR="${lib.concatStringsSep "//:" (map toString fonts)}"
+#! nix exec bash "$@"
+#! nix '')
+#! nix pandoc
+#! nix pdftk
+#! nix qpdf
+#! nix (pkgs.texlive.combine {
+#! nix inherit (pkgs.texlive)
+#! nix collection-fontsrecommended
+#! nix collection-langenglish
+#! nix collection-langfrench
+#! nix collection-latexrecommended
+#! nix collection-luatex
+#! nix pdfbook2
+#! nix pdfcrop
+#! nix pdfjam
+#! nix scheme-basic
+#! nix tex-gyre
+#! nix ;
+#! nix })
+#! nix ]
+#! nix ``
+#! nix --command interpreter
+
+epubPath=$1
+epubDir=$(realpath -e "$(dirname "$epubPath")")
+styleDir=$(realpath -e "$(dirname "$0")")/styles
+outDir=$epubDir/pdf
+pdfFile="$outDir"/out.pdf
+rm -rf "$outDir"
+mkdir -p "$outDir"
+
+# Converting EPUB to PDF
+set -eux
+pandoc \
+ --embed-resources \
+ --include-in-header "$styleDir"/epub.header.tex \
+ --filter "$epubDir"/filter \
+ --number-sections \
+ --pdf-engine lualatex \
+ --standalone \
+ --toc \
+ --toc-depth 6 \
+ --top-level-division chapter \
+ -V documentclass=scrbook \
+ -V classoption=english \
+ -V mainfont="TeX Gyre Termes" \
+ -V fontsize=13pt \
+ -V papersize=a5 \
+ -i "$epubPath" \
+ -t pdf \
+ -o "$pdfFile"
+
+# Slicing on chapters and splitting into chunks of at most 18 pages (for easy binding)
+ mkdir -p "$outDir"/sections
+ pdftk "$pdfFile" dump_data | grep '^BookmarkPageNumber:' |
+ {
+ sectionNum=1
+ sectionBegin=1
+ splitSection () {
+ qpdf \
+ "$pdfFile" \
+ "$outDir"/sections/sectionNum="$sectionNum".pages="$sectionPages".chunk=%d.pdf \
+ --pages "$pdfFile" "$sectionPages" -- \
+ --split-pages=18
+ }
+ while read -r _BookmarkPageNumber sectionEnd; do
+ test "$sectionEnd" != 1 || continue
+ sectionPages=$sectionBegin-$((sectionEnd-1))
+ splitSection
+ sectionNum=$((sectionNum+1))
+ sectionBegin=$sectionEnd
+ done
+ sectionPages="$sectionBegin"-r1
+ splitSection
+ }
+
+# Converting to booklet
+ find "$outDir"/sections -type f |
+ sort -n |
+ while read -r pdfSection; do
+ # Margins have already been set correctly by the geometry package in header.tex
+ # pdfbook2 fails to move the .pdf over filesystems
+ pdfbook2 --no-crop \
+ --paper "${paper:-a4paper}" \
+ --outer-margin "${outerMargin:-80}" \
+ --inner-margin "${innerMargin:-150}" \
+ --top-margin "${topmargin:-30}" \
+ --bottom-margin "${bottomMargin:-30}" \
+ "$pdfSection"
+ rm "$pdfSection"
+
+ # Split odd and even pages to print in the same direction
+ pdftk "${pdfSection%.pdf}"-book.pdf cat oddSouth output "${pdfSection%.pdf}".book.odds.pdf
+ pdftk "${pdfSection%.pdf}"-book.pdf cat even output "${pdfSection%.pdf}".book.even.pdf
+ rm "${pdfSection%.pdf}"-book.pdf
+ done
--- /dev/null
+% Geometry for the booklet
+\usepackage[portrait, left=1.5cm, right=1.5cm, top=2.5cm, bottom=2cm, headheight=1.5cm, headsep=1cm, footskip=1cm, marginparsep=0pt, marginparwidth=0pt, bindingoffset=1cm, twoside]{geometry}
+
+% No title
+\renewcommand{\maketitle}{}