Tailwind classes in OCaml
1(** Tailwind CLI integration for CSS processing *)
2
3open Unix
4
5type config = {
6 input_css: string; (** Path to input CSS file with Tailwind directives *)
7 output_css: string; (** Path to output CSS file *)
8 content: string list; (** List of content paths to scan for classes *)
9 minify: bool; (** Whether to minify the output *)
10}
11
12let default_config = {
13 input_css = "input.css";
14 output_css = "output.css";
15 content = ["*.html"; "*.ml"];
16 minify = true;
17}
18
19(** Check if Tailwind CLI is available *)
20let check_tailwind_cli () =
21 try
22 let ic = open_process_in "npx @tailwindcss/cli --help 2>/dev/null" in
23 let _ = input_line ic in
24 let status = close_process_in ic in
25 status = WEXITED 0
26 with _ -> false
27
28(** Generate Tailwind CSS from input file *)
29let process_css config =
30 if not (check_tailwind_cli ()) then
31 failwith "Tailwind CLI not found. Install with: npm install -D @tailwindcss/cli"
32 else
33 let content_args = String.concat " " (List.map (fun p -> Printf.sprintf "--content '%s'" p) config.content) in
34 let minify_flag = if config.minify then "--minify" else "" in
35 let cmd = Printf.sprintf "npx @tailwindcss/cli -i %s -o %s %s %s 2>&1"
36 config.input_css
37 config.output_css
38 content_args
39 minify_flag
40 in
41 let ic = open_process_in cmd in
42 let rec read_output acc =
43 try
44 let line = input_line ic in
45 read_output (line :: acc)
46 with End_of_file ->
47 List.rev acc
48 in
49 let output = read_output [] in
50 let status = close_process_in ic in
51 match status with
52 | WEXITED 0 -> Ok output
53 | WEXITED n -> Error (Printf.sprintf "Tailwind CLI exited with code %d:\n%s" n (String.concat "\n" output))
54 | _ -> Error "Tailwind CLI terminated abnormally"
55
56(** Process CSS for a specific HTML file *)
57let process_for_html ~input_css ~html_file ~output_css ?(minify=true) () =
58 let config = {
59 input_css;
60 output_css;
61 content = [html_file];
62 minify;
63 } in
64 process_css config
65
66(** Write HTML to file and process CSS *)
67let write_and_process ~html_content ~html_file ~input_css ~output_css () =
68 (* Write HTML to file *)
69 let oc = open_out html_file in
70 output_string oc html_content;
71 close_out oc;
72
73 (* Process CSS *)
74 match process_for_html ~input_css ~html_file ~output_css () with
75 | Ok _ ->
76 Printf.eprintf "✅ Generated %s and %s\n" html_file output_css;
77 Ok ()
78 | Error msg ->
79 Printf.eprintf "❌ CSS processing failed: %s\n" msg;
80 Error msg