xtask/
theme_svgs.rs

1use std::{fs, process::Command};
2
3use anyhow::{bail, Context, Result};
4
5pub fn run() -> Result<()> {
6    let tmpfile = crate::WORKSPACE_DIR.join("ignored/tmp.typ");
7    const ASSET_PATH: &str = "syntastica-themes/assets/theme-svgs";
8    let out_dir = crate::WORKSPACE_DIR.join(ASSET_PATH);
9    fs::create_dir_all(crate::WORKSPACE_DIR.join("ignored"))?;
10    fs::create_dir_all(&out_dir)?;
11
12    let mut md_list = String::from("## List of Themes\n");
13
14    for &theme_name in syntastica_themes::THEMES {
15        println!("{theme_name}");
16
17        let theme = syntastica_themes::from_str(theme_name).unwrap();
18        let bg = match theme.bg() {
19            Some(color) => {
20                let (r, g, b) = color.into_components();
21                format!("rgb({r}, {g}, {b})")
22            }
23            None => "none".to_string(),
24        };
25
26        let output = Command::new(env!("CARGO"))
27            .args(["run", "--example=custom_renderer", theme_name])
28            .current_dir(&*crate::WORKSPACE_DIR)
29            .output()?;
30        if !output.status.success() {
31            eprintln!("{}", String::from_utf8_lossy(&output.stderr));
32            bail!("cargo returned non-zero exit code: {}", output.status);
33        }
34        let render = String::from_utf8_lossy(&output.stdout);
35
36        let typst_file = format!(
37            r#"
38#set page(height: auto, width: auto, margin: 8pt)
39#show raw: text.with(font: "JetBrains Mono")
40
41#block(fill: {bg}, inset: 8pt, radius: 5pt)[
42  == *#box(
43    fill: luma(240),
44    inset: (x: 3pt, y: 0pt),
45    outset: (y: 3pt),
46    radius: 2pt,
47    raw("{theme_name}", block: false),
48  )*\
49  {render}
50]
51"#
52        );
53        fs::write(&tmpfile, typst_file)?;
54
55        let status = Command::new("typst")
56            .args(["compile", "--format=svg", "--root"])
57            .arg(&*crate::WORKSPACE_DIR)
58            .arg(&tmpfile)
59            .arg(out_dir.join(format!("{theme_name}.svg")))
60            .current_dir(&*crate::WORKSPACE_DIR)
61            .status()
62            .with_context(|| "failed to run typst compiler")?;
63        if !status.success() {
64            bail!("typst exited with non-zero exit code: {status}");
65        }
66
67        md_list += &format!(
68            r#"
69### `{theme_name}`
70
71<img alt="{theme_name}" width="100%" src="https://github.com/RubixDev/syntastica/raw/main/{ASSET_PATH}/{theme_name}.svg"></img>
72"#
73        )
74    }
75
76    fs::write(
77        crate::WORKSPACE_DIR.join("syntastica-themes/theme_list.md"),
78        md_list,
79    )?;
80
81    Ok(())
82}