rustolio-build-utils 0.1.0

Build Utilities to use in the build.rs for the rustolio framework
Documentation
//
// SPDX-License-Identifier: MPL-2.0
//
// Copyright (c) 2026 Tobias Binnewies. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

use std::{io::Write, path::Path, process};

use rustolio_utils::prelude::*;

use crate::{cargo_pkg_name, fs, paths, Error, Result};

pub fn enabled() -> Result<bool> {
    Ok(paths::manifest_dir()?.join("tailwind.css").exists())
}

pub fn execute() -> Result<()> {
    let tmp_tw_css = paths::out_dir()?.join("tailwind.css");
    
    execute_inner(&tmp_tw_css)
}

pub fn execute_inner(tmp_tw_css: &Path) -> Result<()> {
    const IMPORT: &str = r#"
@source "{SRC_PATH}/src/**/*.rs";
@source "{SRC_PATH}/static/**/*.{html,css,js,mjs}";
"#;

    if !enabled()? {
        return Ok(());
    }

    let input = paths::manifest_dir()?.join("tailwind.css");
    let tailwind_css = std::fs::read_to_string(&input).context("Failed to read tailwind.css")?;

    // Add all dependecy paths to the tailwind.css
    let mut file =
        std::fs::File::create(tmp_tw_css).context("Failed to create tailwind_tmp.css")?;
    file.write_all(tailwind_css.as_bytes())
        .context("Failed to write to tailwind_tmp.css")?;

    for src_path in fs::read_file_from_all_dirs(&paths::web_build_dir()?, "tw_info")? {
        let import = IMPORT.replace("{SRC_PATH}", &src_path);
        file.write_all(import.as_bytes())
            .context("Failed to write to tailwind_tmp.css")?;
    }
    file.flush().context("Failed to flush tailwind_tmp.css")?;

    let output = paths::pkg_dir()?.join("tailwind.css");
    let status = process::Command::new("npx")
        .arg("tailwindcss")
        .arg("-i")
        .arg(tmp_tw_css)
        .arg("-o")
        .arg(output)
        // .current_dir(paths::manifest_dir()?)
        .status()
        .context("Failed to execute tailwind")?;
    if !status.success() {
        return Err(Error::new("Executing tailwind did not succeed"));
    }

    Ok(())
}

pub fn push_info() -> Result<()> {
    // Add this packages src path as an info so it can be applied to the tailwind.css on `execute`
    fs::create(
        &paths::web_build_dir()?
            .join(cargo_pkg_name()?)
            .join("tw_info"),
        paths::manifest_dir()?
            .to_str()
            .context("Failed to convert to str")?,
    )
}