use std::{error::Error, path::PathBuf, process::Command}; use convert_case::{Case, Casing}; use proc_macro2::TokenStream; use quote::{quote, ToTokens}; use crate::framework::Framework; pub struct Leptos; impl Framework for Leptos { fn name(&self) -> &'static str { "leptos" } fn lib_header(&self) -> Option { Some( "\ //! Leptos port of [Lucide](https://lucide.dev/).\n\ //!\n\ //! Lucide is a beautiful & consistent icon toolkit made by the community.\n\ //!\n\ //! See [the Rust Lucide book](https://lucide.rustforweb.org/leptos.html) for more documenation.\n\ " .to_owned() ) } fn generate(&self, component_name: String, svg: String) -> Result> { let component_name: TokenStream = component_name.parse()?; let svg: TokenStream = svg .replacen(", #[prop(default = "currentColor".into(), into)] color: Signal, #[prop(default = "none".into(), into)] fill: Signal, #[prop(default = 2.into(), into)] stroke_width: Signal, #[prop(default = false.into(), into)] absolute_stroke_width: Signal, #[prop(optional)] node_ref: NodeRef, ) -> impl IntoView { let stroke_width = Signal::derive(move || { if absolute_stroke_width.get() { stroke_width.get() * 24 / size.get() } else { stroke_width.get() } }); view! { #svg } } }) } fn generate_example(&self, component_names: &[String]) -> Result> { let mut letter_component_name: Vec = vec![]; let mut letter_component: Vec = vec![]; for letter in 'A'..='Z' { let mut component_name: Vec = vec![]; let mut human_name: Vec = vec![]; for name in component_names { if !name.starts_with(letter) { continue; } component_name.push(name.parse()?); human_name.push( name.trim_end_matches("Icon") .to_case(Case::Title) .to_token_stream(), ); } let name: TokenStream = format!("Icons{letter}").parse()?; letter_component_name.push(quote! { <#name /> }); letter_component.push(quote! { #[component] pub fn #name() -> impl IntoView { view! { }.into_any(), #human_name),)* ] key=|icon| icon.1 children=move |(icon, name)| { view! {
{icon} {name}
} } /> } } }); } Ok(quote! { use leptos::prelude::*; use lucide_leptos::*; #[component] pub fn Icons() -> impl IntoView { view! {
#(#letter_component_name)*
} } #(#letter_component)* }) } fn format(&self, package: String, path: PathBuf) -> Result<(), Box> { Command::new("cargo") .arg("fmt") .arg("-p") .arg(&package) .status()? .exit_ok()?; Command::new("leptosfmt") .arg("--quiet") .arg(path) .status()? .exit_ok()?; Ok(()) } }