manatsu 0.7.5

CLI tools for Manatsu
use crate::prelude::*;
use lightningcss::stylesheet::{ParserOptions, PrinterOptions, StyleSheet};

/// Create a Manatsu theme from tokens generated by the
/// [Material Design theme builder](https://m3.material.io/theme-builder#/custom).
pub fn create(source: PathBuf, output: PathBuf) -> Result<()> {
  let css = fs::read_to_string(source)?;
  let source = transform(css);

  let stylesheet = StyleSheet::parse(&source, ParserOptions::default())
    .map_err(|err| anyhow!("{err}"))
    .with_context(|| "failed to parse stylesheet")?;

  let css = stylesheet.to_css(PrinterOptions::default())?;
  fs::write(output, css.code)?;

  Ok(())
}

#[allow(clippy::needless_pass_by_value)]
fn transform(css: String) -> String {
  let mut result = String::with_capacity(css.len());
  let mut dark_colors = String::from("\n\n[class~=manatsu-dark] {\n");

  macro_rules! push {
    ($string:expr, $slice:expr) => {
      $string.push_str($slice);
      $string.push('\n');
    };
  }

  let skip = [
    // Surface tint is deprecated.
    // https://m3.material.io/styles/color/roles#22948d54-0450-4cab-8f4f-8853a8c6eccc
    "color-surface-tint",
  ];

  'lines: for line in css.lines() {
    if !line.contains("--md") {
      push!(result, line);
      continue;
    }

    for s in skip {
      if line.contains(s) {
        continue 'lines;
      }
    }

    if line.contains("--md-sys-color") {
      let line = line.replace("md-sys", "m");
      if line.contains("-light") {
        let line = line.replace("-light", "");
        push!(result, &line);
        continue;
      }

      if line.contains("-dark") && !line.contains("fixed") {
        let line = line.replace("-dark", "");
        push!(dark_colors, &line);
        continue;
      }
    }
  }

  dark_colors.push_str("}\n");
  result.push_str(&dark_colors);

  result.shrink_to_fit();

  result
}