From 2b4827715a7bc8cff56933749d16a4815f39e510 Mon Sep 17 00:00:00 2001 From: Tristan Druyen Date: Sun, 9 Mar 2025 21:46:11 +0100 Subject: [PATCH] WIP Switch to hypertext --- Cargo.lock | 173 +++++++++++++----- Cargo.toml | 2 +- darm_test/Cargo.toml | 3 +- darm_test/src/main.rs | 251 +++++++++------------------ darm_test/src/templates/404.html | 1 - darm_test/src/templates/asd/def.html | 4 - darm_test/src/templates/index.html | 26 --- darm_test/src/templates/test.html | 25 --- flake.lock | 18 +- package-lock.json | 165 +++++++++++++++++- package.json | 1 + rust-toolchain.toml | 24 +-- 12 files changed, 393 insertions(+), 300 deletions(-) delete mode 100644 darm_test/src/templates/404.html delete mode 100644 darm_test/src/templates/asd/def.html delete mode 100644 darm_test/src/templates/index.html delete mode 100644 darm_test/src/templates/test.html diff --git a/Cargo.lock b/Cargo.lock index b73541c..fab7746 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,6 +72,26 @@ dependencies = [ "memchr", ] +[[package]] +name = "aide" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ef7da148319b3f1ac7d338f7a144521ee399cd65e4381aa0c17994e74304aa8" +dependencies = [ + "axum 0.8.1", + "bytes", + "cfg-if", + "http 1.2.0", + "indexmap 2.7.1", + "schemars", + "serde", + "serde_json", + "thiserror 2.0.12", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -367,7 +387,7 @@ dependencies = [ [[package]] name = "axum-controller" -version = "0.2.0" +version = "0.2.1" dependencies = [ "axum-controller-macros", "axum-typed-routing 0.2.0", @@ -375,7 +395,7 @@ dependencies = [ [[package]] name = "axum-controller-macros" -version = "0.2.0" +version = "0.2.1" dependencies = [ "prettyplease", "proc-macro2", @@ -450,6 +470,7 @@ dependencies = [ name = "axum-typed-routing" version = "0.2.0" dependencies = [ + "aide", "axum 0.8.1", "axum-macros 0.5.0", "axum-typed-routing-macros 0.2.0", @@ -1237,9 +1258,8 @@ dependencies = [ "axum-controller-macros", "axum-typed-routing 0.2.0 (git+https://github.com/jvdwrf/axum-typed-routing)", "datastar", - "maud", + "hypertext", "mime_guess", - "minijinja", "rust-embed", "serde", "tokio", @@ -1457,6 +1477,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +[[package]] +name = "dyn-clone" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" + [[package]] name = "either" version = "1.15.0" @@ -2487,6 +2513,34 @@ dependencies = [ "tracing", ] +[[package]] +name = "hypertext" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "508fb3d4a66e3649600d00b2c82cd0ca52227ab2970537899903b3c9fd17ab21" +dependencies = [ + "axum-core 0.5.0", + "html-escape", + "http 1.2.0", + "hypertext-macros", + "itoa 1.0.15", + "ryu", +] + +[[package]] +name = "hypertext-macros" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b679587a4d3f8cc3c6517d7fa78c86ec2945bb4b55247103a0cedf9c935f7d5d" +dependencies = [ + "html-escape", + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "rstml 0.12.1", + "syn 2.0.99", +] + [[package]] name = "iana-time-zone" version = "0.1.61" @@ -2707,6 +2761,7 @@ checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown 0.15.2", + "serde", ] [[package]] @@ -2965,7 +3020,7 @@ dependencies = [ "parking_lot 0.12.3", "proc-macro2", "quote", - "rstml", + "rstml 0.11.2", "serde", "syn 2.0.99", "walkdir", @@ -3001,7 +3056,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "rstml", + "rstml 0.11.2", "server_fn_macro", "syn 2.0.99", "tracing", @@ -3401,30 +3456,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" -[[package]] -name = "maud" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8156733e27020ea5c684db5beac5d1d611e1272ab17901a49466294b84fc217e" -dependencies = [ - "axum-core 0.5.0", - "http 1.2.0", - "itoa 1.0.15", - "maud_macros", -] - -[[package]] -name = "maud_macros" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7261b00f3952f617899bc012e3dbd56e4f0110a038175929fa5d18e5a19913ca" -dependencies = [ - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.99", -] - [[package]] name = "md-5" version = "0.10.6" @@ -3450,12 +3481,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memo-map" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d1115007560874e373613744c6fba374c17688327a71c1476d1a5954cc857b" - [[package]] name = "memoffset" version = "0.9.1" @@ -3481,17 +3506,6 @@ dependencies = [ "unicase", ] -[[package]] -name = "minijinja" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e36f1329330bb1614c94b78632b9ce45dd7d761f3304a1bed07b2990a7c5097" -dependencies = [ - "memo-map", - "self_cell", - "serde", -] - [[package]] name = "minimal-lexical" version = "0.2.1" @@ -4910,10 +4924,25 @@ dependencies = [ "proc-macro2-diagnostics", "quote", "syn 2.0.99", - "syn_derive", + "syn_derive 0.1.8", "thiserror 1.0.69", ] +[[package]] +name = "rstml" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61cf4616de7499fc5164570d40ca4e1b24d231c6833a88bff0fe00725080fd56" +dependencies = [ + "derive-where", + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn 2.0.99", + "syn_derive 0.2.0", + "thiserror 2.0.12", +] + [[package]] name = "rust-embed" version = "8.6.0" @@ -5085,6 +5114,31 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "schemars" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +dependencies = [ + "dyn-clone", + "indexmap 2.7.1", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.99", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -5226,6 +5280,17 @@ dependencies = [ "syn 2.0.99", ] +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.99", +] + [[package]] name = "serde_json" version = "1.0.140" @@ -5906,6 +5971,18 @@ dependencies = [ "syn 2.0.99", ] +[[package]] +name = "syn_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb066a04799e45f5d582e8fc6ec8e6d6896040d00898eb4e6a835196815b219" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.99", +] + [[package]] name = "sync_wrapper" version = "1.0.2" diff --git a/Cargo.toml b/Cargo.toml index 7139395..b111318 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ panic = "abort" [workspace] members = ["darm_test", "llama_forge_rs", "llama_proxy_man", "redvault_el_rs"] -resolver = "3" +resolver = "2" [workspace.package] authors = ["Tristan Druyen"] diff --git a/darm_test/Cargo.toml b/darm_test/Cargo.toml index 27d8bf3..9ca108c 100644 --- a/darm_test/Cargo.toml +++ b/darm_test/Cargo.toml @@ -15,9 +15,8 @@ axum-controller = { version = "0.2.0", path = "../../axum-controller/axum-contro axum-controller-macros = { version = "0.2.0", path = "../../axum-controller/axum-controller-macros" } axum-typed-routing = { git = "https://github.com/jvdwrf/axum-typed-routing", version = "0.2.0" } datastar = { git = "https://github.com/starfederation/datastar.git", version = "0.1.0" } -maud = { version = "0.27.0", features = ["axum"] } +hypertext = { version = "0.6.0", features = ["axum"] } mime_guess = "2.0.5" -minijinja = { version = "2.7.0", features = ["loader"] } rust-embed = { version = "8.5.0", features = ["axum", "compression"] } serde = { version = "1.0", features = ["derive"] } tokio = { version = "1.43", features = ["full", "tracing"] } diff --git a/darm_test/src/main.rs b/darm_test/src/main.rs index a2a67a9..1b87b45 100644 --- a/darm_test/src/main.rs +++ b/darm_test/src/main.rs @@ -1,22 +1,77 @@ -use std::sync::{Arc, Once}; +use std::sync::Once; use axum::{ body::Body, extract::State, http::{header, Response, StatusCode, Uri}, - response::{Html, IntoResponse}, + response::IntoResponse, routing::get, }; use axum_controller::*; -use maud::{html, Markup}; +use hypertext::{maud, GlobalAttributes, Renderable}; use rust_embed::RustEmbed; +mod html_elements { + use hypertext::elements; + pub use hypertext::html_elements::*; + + elements! { + bla { + blub + } + my_element { + my_attribute + } + } +} + struct TestController {} #[controller( state = AppState )] impl TestController { + #[route(GET "/")] + async fn index(State(_): State) -> impl IntoResponse { + maud! { + html lang="en" { + head { + meta charset="UTF-8"; + meta name="viewport" content="width=device-width, initial-scale=1.0"; + title { + "My Website" + } + script type="module" src="/dist/datastar.min.js" {} + link rel="stylesheet" href="/dist/styles.min.css"; + link rel="icon" href="/dist/favicon.ico"; + } + body { + main { + h1 { + "Welcome to My Website" + } + div."m-1" { + "div" + } + div."m1" { + "div" + } + div ."m1" { + "m1" + } + div ."m2" { + "m2" + } + div ."m3" { + "m3" + } + } + } + } + } + .render() + } + #[allow(unused)] #[route(GET "/item/:id?amount&offset")] async fn item_handler( @@ -25,15 +80,16 @@ impl TestController { offset: Option, State(state): State, // Json(json): Json, - ) -> Markup { + ) -> impl IntoResponse { // todo!("handle request") - html! { + maud! { h1 { "Item" } p { (format!("{id:?} {amount:?} {offset:?} {state:?}")) } } + .render() } } @@ -49,18 +105,18 @@ impl DistController { } } -fn markup_404(uri: String) -> Markup { - html! { +fn markup_404(uri: String) -> impl Renderable { + maud! { h1 { "404" } - p { (format!("{uri:?} Not Found")) } + p { (uri) " Not Found" } @for i in 0..5 { div .{"m-" (i)} { (i) } } } } -fn markup_405() -> Markup { - html! { +fn markup_405() -> impl Renderable { + maud! { h1 { "404" } p { "Method not allowed!" } @for i in 1..3 { @@ -71,11 +127,19 @@ fn markup_405() -> Markup { // Finally, we use a fallback route for anything that didn't match. async fn handle_404(uri: Uri) -> impl IntoResponse { - (StatusCode::NOT_FOUND, markup_404(format!("{uri:?}"))).into_response() + ( + StatusCode::NOT_FOUND, + axum::response::Html(markup_404(format!("{uri:?}")).render()), + ) + .into_response() } async fn handle_405() -> impl IntoResponse { - (StatusCode::METHOD_NOT_ALLOWED, markup_405()).into_response() + ( + StatusCode::METHOD_NOT_ALLOWED, + axum::response::Html(markup_405().render()), + ) + .into_response() } pub struct StaticFile(pub T); @@ -97,7 +161,11 @@ where ([(header::CONTENT_TYPE, mime.as_ref())], content.data).into_response() } - None => (StatusCode::NOT_FOUND, markup_404(path)).into_response(), + None => ( + StatusCode::NOT_FOUND, + axum::response::Html(markup_404(path).render()), + ) + .into_response(), } } } @@ -117,180 +185,23 @@ pub fn initialize_logger() { }); } -use minijinja::{Environment, Template}; - #[derive(Clone, Debug)] struct AppState { _field: String, - mj_env: Arc>, -} - -struct JinjaController; - -#[controller(state=AppState)] -impl JinjaController { - #[route(GET "/")] - async fn jinja_index_handler(state: State) -> impl IntoResponse { - RenderTemplate::new("/".to_string(), state.mj_env.clone()) - } - - #[route(GET "/*path")] - async fn jinja_index_handler_path(path: String, state: State) -> impl IntoResponse { - RenderTemplate::new(path, state.mj_env.clone()) - } -} - -struct RenderTemplate { - tmpl_name: String, - env: Arc>, - ctx: minijinja::Value, - block: Option, -} - -impl RenderTemplate { - fn new(tmpl_name: String, env: Arc>) -> Self { - Self { - tmpl_name, - env, - ctx: minijinja::Value::from(()), - block: None, - } - } - - fn _new_with_ctx( - tmpl_name: String, - env: Arc>, - ctx: minijinja::Value, - ) -> Self { - Self { - tmpl_name, - env, - ctx, - block: None, - } - } -} - -impl IntoResponse for RenderTemplate { - fn into_response(self) -> axum::response::Response { - let path = self.tmpl_name; - let env = self.env; - let ctx = self.ctx; - let block = self.block; - - let res = env.get_template(&path); - - let render = move |template: Template| match block { - None => match template.render(ctx) { - Ok(html) => Html(html).into_response(), - Err(_) => ( - StatusCode::INTERNAL_SERVER_ERROR, - "Failed to render template", - ) - .into_response(), - }, - Some(block) => match template.eval_to_state(ctx).unwrap().render_block(&block) { - Ok(html) => Html(html).into_response(), - Err(_) => ( - StatusCode::INTERNAL_SERVER_ERROR, - "Failed to render block template", - ) - .into_response(), - }, - }; - - match res { - Ok(template) => render(template), - Err(_) => { - let template = env.get_template("404").unwrap(); - let html = render(template); - (StatusCode::NOT_FOUND, html).into_response() - } - } - } -} - -/// Template loader for embedded templates. Uses Symbol’s value as variable is void: rust-embed to embed templates into the binary. -/// For input path example/template -/// it looks up: -/// - $template_dir/example/template/index.html -/// - $template_dir/example/template.html -/// -/// Instead of example/template -/// any of: -/// - example//template/ -/// - example/template/// -/// - example/template.html -/// - example/template/index.html -/// would also resolve to the same 2 templates above -/// TODO Canonilize path with a middleware that redirects any weird variants to the canonical path? -fn template_loader(name: &str) -> Result, minijinja::Error> { - #[derive(RustEmbed)] - #[folder = "src/templates/"] - struct Templ; - // lets extract the "clean path" (i.e. '.html' or '/index.html' suffix) - let mut clean_path = name - .to_string() - .chars() - .fold(String::new(), |mut acc, c| { - if c == '/' && acc.chars().last() != Some('/') { - acc.push(c); - } else if c != '/' { - acc.push(c); - } - - acc - }) - .to_string(); - clean_path = clean_path - .strip_suffix("index.html") - .unwrap_or(&clean_path) - .to_string(); - - clean_path = clean_path - .strip_suffix(".html") - .unwrap_or(&clean_path) - .to_string(); - - let cleaned_path = clean_path.to_string(); - - let files_to_try = vec![ - format!("./{}.html", cleaned_path), - format!("./{}/index.html", cleaned_path), - ]; - - let found_template = files_to_try.into_iter().find_map(|path| { - tracing::info!(?path); - match Templ::get(path.as_str()) { - Some(content) => { - let content = std::str::from_utf8(&content.data).unwrap().to_string(); - Some(content) - } - None => None, - } - }); - - Ok(found_template) } #[tokio::main] async fn main() { initialize_logger(); - let mut mj_env = Environment::new(); - - mj_env.set_loader(template_loader); - let app_state = AppState { _field: "".to_string(), - mj_env: Arc::new(mj_env), }; // TODO pick free port/config let listener = tokio::net::TcpListener::bind("0.0.0.0:8000").await.unwrap(); let router: axum::Router = axum::Router::new() - .merge(JinjaController::into_router(app_state.clone())) .merge(TestController::into_router(app_state.clone())) .merge(DistController::into_router(app_state.clone())) .fallback_service(get(handle_404)) diff --git a/darm_test/src/templates/404.html b/darm_test/src/templates/404.html deleted file mode 100644 index 245cd00..0000000 --- a/darm_test/src/templates/404.html +++ /dev/null @@ -1 +0,0 @@ -

Not Found!

diff --git a/darm_test/src/templates/asd/def.html b/darm_test/src/templates/asd/def.html deleted file mode 100644 index c729f9f..0000000 --- a/darm_test/src/templates/asd/def.html +++ /dev/null @@ -1,4 +0,0 @@ -

Def

-{% block sidebar %} - "Sidebar test" -{% endblock sidebar %} diff --git a/darm_test/src/templates/index.html b/darm_test/src/templates/index.html deleted file mode 100644 index 816d6ec..0000000 --- a/darm_test/src/templates/index.html +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - My Website - - - - - - - - -
-

Welcome to My Website

-
div
-
div
-
div
- m1 - m2 - m3 -
- - - diff --git a/darm_test/src/templates/test.html b/darm_test/src/templates/test.html deleted file mode 100644 index d51fc5e..0000000 --- a/darm_test/src/templates/test.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - My Website - - - - - - - - -
-

Welcome to My Website

-
div
-
div
-
div
- div -
- - - diff --git a/flake.lock b/flake.lock index c24d6b9..844183f 100644 --- a/flake.lock +++ b/flake.lock @@ -5,11 +5,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1735644329, - "narHash": "sha256-tO3HrHriyLvipc4xr+Ewtdlo7wM1OjXNjlWRgmM7peY=", + "lastModified": 1741473158, + "narHash": "sha256-kWNaq6wQUbUMlPgw8Y+9/9wP0F8SHkjy24/mN3UAppg=", "owner": "numtide", "repo": "devshell", - "rev": "f7795ede5b02664b57035b3b757876703e2c3eac", + "rev": "7c9e793ebe66bcba8292989a68c0419b737a22a0", "type": "github" }, "original": { @@ -111,11 +111,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1741246872, - "narHash": "sha256-Q6pMP4a9ed636qilcYX8XUguvKl/0/LGXhHcRI91p0U=", + "lastModified": 1741379970, + "narHash": "sha256-Wh7esNh7G24qYleLvgOSY/7HlDUzWaL/n4qzlBePpiw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "10069ef4cf863633f57238f179a0297de84bd8d3", + "rev": "36fd87baa9083f34f7f5027900b62ee6d09b1f2f", "type": "github" }, "original": { @@ -173,11 +173,11 @@ "nixpkgs": "nixpkgs_3" }, "locked": { - "lastModified": 1741314698, - "narHash": "sha256-6Yp0CTwAY/jq/F81Sa8NM0Zi1EwxAdASO6y4A5neGuc=", + "lastModified": 1741486734, + "narHash": "sha256-3hrpyTLNmnJpioVT1DDoVgsp7fWYkuS3JWCtfHsX1rk=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "4e9af61c1a631886cdc7e13032af4fc9e75bb76b", + "rev": "d95582a900bd0e7e516ce3bed0503f742649fffb", "type": "github" }, "original": { diff --git a/package-lock.json b/package-lock.json index d02bdc9..be46d15 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,15 @@ { - "name": "oeko-mono", + "name": "redvault-ai", "version": "0.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "oeko-mono", + "name": "redvault-ai", "version": "0.1.1", "license": "AGPL", "devDependencies": { + "@anthropic-ai/claude-code": "^0.2.35", "@starfederation/datastar": "^1.0.0-beta.7", "@tailwindcss/forms": "0.5.7", "@tailwindcss/typography": "0.5.10", @@ -70,6 +71,26 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/@anthropic-ai/claude-code": { + "version": "0.2.35", + "resolved": "https://registry.npmjs.org/@anthropic-ai/claude-code/-/claude-code-0.2.35.tgz", + "integrity": "sha512-OTCLa2kvtbYJ2tDbKNxZ7N2kUMXGXTIzr5DW18zYSMMu5RpOLyL+A/DfKXNgcvri76ttttj7lcQRLmQ0pCqZDA==", + "dev": true, + "hasInstallScript": true, + "license": "SEE LICENSE IN README.md", + "bin": { + "claude": "cli.js" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "^0.33.5", + "@img/sharp-linux-arm": "^0.33.5", + "@img/sharp-linux-x64": "^0.33.5", + "@img/sharp-win32-x64": "^0.33.5" + } + }, "node_modules/@esbuild/android-arm": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", @@ -490,6 +511,146 @@ "mlly": "^1.7.4" } }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", diff --git a/package.json b/package.json index 5b7936d..b20239b 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "build-all": "npm run build-unocss & npm run build-bundle" }, "devDependencies": { + "@anthropic-ai/claude-code": "^0.2.35", "@starfederation/datastar": "^1.0.0-beta.7", "@tailwindcss/forms": "0.5.7", "@tailwindcss/typography": "0.5.10", diff --git a/rust-toolchain.toml b/rust-toolchain.toml index bcf35b0..790b0a3 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,16 +1,16 @@ [toolchain] -channel = "nightly-2025-01-30" -targets = [ - "x86_64-unknown-linux-gnu", - "wasm32-unknown-unknown", - "x86_64-pc-windows-msvc", -] +channel = "nightly-2025-03-01" components = [ - "cargo", - "rustfmt", - "rust-analyzer", - "rust-src", - "rustc-codegen-cranelift", - "rustc-dev", + "cargo", + "rust-analyzer", + "rust-src", + "rustc-codegen-cranelift", + "rustc-dev", + "rustfmt", ] profile = "default" +targets = [ + "wasm32-unknown-unknown", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu", +]