package forester

  1. Overview
  2. Docs

Source file Build_latex.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
open Eio.Std
open Prelude
open Render

type 'a env = 'a constraint 'a = <
    cwd : Eio.Fs.dir_ty Eio.Path.t;
    process_mgr : _ Eio.Process.mgr;
    stdout : _ Eio.Flow.sink;
    ..
  > as 'a


let tex_fp name =
  Format.sprintf "%s.tex" name

let dvi_fp name =
  Format.sprintf "%s.dvi" name

let pdf_fp name =
  Format.sprintf "%s.pdf" name

let build_dir cwd =
  Eio.Path.(cwd/"build")

let tex_fname name = name ^ ".tex"
let dvi_fname name = name ^ ".dvi"
let pdf_fname name = name ^ ".pdf"


let write_tex_file ~env ~name ~packages ~source =
  let cwd = Eio.Stdenv.cwd env in
  let path = Eio.Path.(build_dir cwd / tex_fname name) in
  let create = `Or_truncate 0o644 in
  Eio.Path.with_open_out ~create path @@ fun sink ->
  Eio.Buf_write.with_flow sink @@ fun writer ->
  let fmt = Eio_util.formatter_of_writer writer in
  LaTeX_template.write fmt ~source ~packages

let render_dvi_file ~env ~name ~source =
  let cwd = build_dir @@ Eio.Stdenv.cwd env in
  Eio_util.ensure_remove_file Eio.Path.(cwd / dvi_fname name);
  Eio_util.ensure_remove_file Eio.Path.(cwd / pdf_fname name);
  Eio_util.run_process ~env ~cwd
    ["latex"; "-halt-on-error"; "-interaction=nonstopmode"; tex_fname name]

let render_pdf_file ~env ~name ~source =
  let cwd = build_dir @@ Eio.Stdenv.cwd env in
  Eio_util.ensure_remove_file Eio.Path.(cwd / pdf_fname name);
  Eio_util.run_process ~env ~cwd
    ["pdflatex"; "-halt-on-error"; "-interaction=nonstopmode"; tex_fname name]

let render_svg_file ~env ~name ~source =
  let cwd = build_dir @@ Eio.Stdenv.cwd env in
  let fname = dvi_fname name in
  Eio_util.run_process ~env ~cwd
    ["dvisvgm";
     "--exact";
     "--clipjoin";
     "--font-format=woff";
     "--bbox=papersize";
     "--zoom=1.5";
     fname;
     "--output=%f"];
  Eio_util.ensure_remove_file Eio.Path.(cwd / fname)


let build_latex ~env ~ignore_tex_cache ~name ~packages ~source =
  let cwd = Eio.Stdenv.cwd env in
  let web_name = name ^ "-web" in
  let print_name = name ^ "-print" in
  let svg_path = Eio.Path.(build_dir cwd / (web_name ^ ".svg")) in
  let pdf_path = Eio.Path.(build_dir cwd / (print_name ^ ".pdf")) in

  let svg_task () =
    if ignore_tex_cache || not @@ Eio_util.file_exists svg_path then
      begin
        write_tex_file ~env ~name:web_name ~packages ~source;
        render_dvi_file ~env ~name:web_name ~source;
        render_svg_file ~env ~name:web_name ~source
      end
  in
  let pdf_task () =
    if ignore_tex_cache || not @@ Eio_util.file_exists pdf_path then
      begin
        write_tex_file ~env ~name:print_name ~packages:(packages @ ["newpxtext"; "newpxmath"]) ~source;
        render_pdf_file ~env ~name:print_name ~source
      end
  in

  Eio.Fiber.both svg_task pdf_task
OCaml

Innovation. Community. Security.