refactor!: rename slhx to hemx

Rename the tracked product identity, crate/package names, Rust paths/macros, generated artifacts, runtime files, public attributes, examples, docs, requirements, and tests from slhx to hemx without compatibility shims.

Verified with cargo run -p hemx-xtask -- test, cargo test -p hemx-derive --test compile_fail, cargo test -p hemx-js, cargo test -p hemx-axum, cargo test -p hemx-v0-examples, cargo check --workspace, redgate list, redgate refs, redgate health --strict, git diff --check, and git grep/ls-files legacy-name audits.

req: misc/001

req: codegen/001

req: component/004

req: runtime/001
This commit is contained in:
slhx agent
2026-06-05 06:52:37 +02:00
parent d4e865ef92
commit c33500440e
69 changed files with 1415 additions and 1415 deletions
+5 -5
View File
@@ -1,5 +1,5 @@
[package]
name = "slhx-v0-examples"
name = "hemx-v0-examples"
version.workspace = true
edition.workspace = true
publish = false
@@ -11,13 +11,13 @@ path = "src/lib.rs"
axum = "0.7"
futures-util = "0.3"
hemplate = { path = "../../../hemplate/hemplate" }
slhx = { path = "../../slhx" }
slhx-axum = { path = "../../slhx-axum" }
hemx = { path = "../../hemx" }
hemx-axum = { path = "../../hemx-axum" }
tokio = { version = "1", features = ["macros", "net", "rt-multi-thread", "time"] }
[dev-dependencies]
scraper = "0.23"
slhx-test = { path = "../../slhx-test" }
hemx-test = { path = "../../hemx-test" }
[build-dependencies]
slhx-build = { path = "../../slhx-build" }
hemx-build = { path = "../../hemx-build" }
+2 -2
View File
@@ -1,9 +1,9 @@
# slhx v0 browser examples
# hemx v0 browser examples
Run the examples server:
```sh
cargo run -p slhx-v0-examples
cargo run -p hemx-v0-examples
```
Open <http://127.0.0.1:3000>.
+1 -1
View File
@@ -1,3 +1,3 @@
fn main() {
slhx_build::app().run().unwrap();
hemx_build::app().run().unwrap();
}
+14 -14
View File
@@ -1,12 +1,12 @@
#[slhx::surface]
#[hemx::surface]
pub mod ui {}
#[cfg(test)]
mod tests {
use super::ui::{auth, counter, notifications, page_swap, todos, wizard};
use hemplate::Hemplate;
use slhx::{push, IntoEffect};
use slhx_test::inspect;
use hemx::{push, IntoEffect};
use hemx_test::inspect;
#[derive(Clone, Debug)]
struct Todo {
@@ -15,19 +15,19 @@ mod tests {
}
#[derive(Clone, Debug)]
#[slhx::form("new_todo")]
#[hemx::form("new_todo")]
struct TodoInput {
title: String,
}
#[derive(Clone, Debug)]
#[slhx::form("wizard_input")]
#[hemx::form("wizard_input")]
struct WizardInput {
step: u8,
}
#[derive(Clone, Debug)]
#[slhx::form("credentials")]
#[hemx::form("credentials")]
struct Credentials {
email: String,
password: String,
@@ -40,8 +40,8 @@ mod tests {
title: String,
}
impl slhx::KeyedPartial for TodoRow {
fn slhx_key(&self) -> String {
impl hemx::KeyedPartial for TodoRow {
fn hemx_key(&self) -> String {
self.id.to_string()
}
}
@@ -67,8 +67,8 @@ mod tests {
// req: examples/001 req: form/001 req: form/004 req: form/006 req: derive_handler/003
#[test]
fn form_handler_is_checked_against_hemplate_form() {
#[slhx::handler]
fn add_todo(_form: slhx::Form<TodoInput>) -> impl IntoEffect {
#[hemx::handler]
fn add_todo(_form: hemx::Form<TodoInput>) -> impl IntoEffect {
todos::todo_list.set("queued")
}
@@ -101,8 +101,8 @@ mod tests {
// req: examples/001 req: form/001 req: form/004 req: form/006 req: derive_handler/003
#[test]
fn wizard_form_handler_is_checked_against_hemplate_form() {
#[slhx::handler]
fn next_step(_form: slhx::Form<WizardInput>) -> impl IntoEffect {
#[hemx::handler]
fn next_step(_form: hemx::Form<WizardInput>) -> impl IntoEffect {
wizard::wizard_step.set("queued")
}
@@ -146,8 +146,8 @@ mod tests {
// req: examples/001 req: form/001 req: form/004 req: form/006 req: derive_handler/003
#[test]
fn auth_form_handler_is_checked_against_hemplate_form() {
#[slhx::handler]
fn login(_form: slhx::Form<Credentials>) -> impl IntoEffect {
#[hemx::handler]
fn login(_form: hemx::Form<Credentials>) -> impl IntoEffect {
auth::login_status.set("queued")
}
+32 -32
View File
@@ -4,12 +4,12 @@ use axum::routing::get;
use axum::Router;
use futures_util::{stream, StreamExt};
use hemplate::Hemplate;
use slhx::{Html, IntoEffect};
use slhx_axum::{
use hemx::{Html, IntoEffect};
use hemx_axum::{
interactions, runtime_js, sse, EffectResponse, Form, InteractionRequest, PageRequest, Registry,
};
use slhx_v0_examples::ui;
use slhx_v0_examples::ui::{auth, counter, notifications, page_swap, todo_row, todos, wizard};
use hemx_v0_examples::ui;
use hemx_v0_examples::ui::{auth, counter, notifications, page_swap, todo_row, todos, wizard};
use std::collections::BTreeMap;
use std::convert::Infallible;
use std::net::SocketAddr;
@@ -31,28 +31,28 @@ struct TodoRecord {
title: String,
}
#[slhx::form("new_todo")]
#[hemx::form("new_todo")]
struct NewTodo {
title: String,
}
#[slhx::form("rename_todo")]
#[hemx::form("rename_todo")]
struct RenameTodo {
id: u64,
title: String,
}
#[slhx::form("delete_todo")]
#[hemx::form("delete_todo")]
struct DeleteTodo {
id: u64,
}
#[slhx::form("wizard_input")]
#[hemx::form("wizard_input")]
struct WizardInput {
step: String,
}
#[slhx::form("credentials")]
#[hemx::form("credentials")]
struct Credentials {
email: String,
password: String,
@@ -82,8 +82,8 @@ struct TodoRow {
title: String,
}
impl slhx::KeyedPartial for TodoRow {
fn slhx_key(&self) -> String {
impl hemx::KeyedPartial for TodoRow {
fn hemx_key(&self) -> String {
self.id.to_string()
}
}
@@ -129,12 +129,12 @@ async fn main() {
.route("/", get(home).post(interact))
.route("/docs", get(docs).post(interact))
.route("/events", get(events))
.route("/slhx.js", get(runtime))
.route("/hemx.js", get(runtime))
.with_state(state);
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
println!("slhx v0 examples: http://{addr}");
println!("hemx v0 examples: http://{addr}");
axum::serve(listener, app).await.unwrap();
}
@@ -142,7 +142,7 @@ async fn main() {
async fn home(request: PageRequest) -> impl IntoResponse {
request
.page_html(all_examples(), shell)
.title("slhx v0 examples")
.title("hemx v0 examples")
.fingerprint(ui::BUILD_FINGERPRINT)
}
@@ -188,7 +188,7 @@ async fn events(Query(params): Query<BTreeMap<String, String>>) -> impl IntoResp
sse(batches)
}
#[slhx::app(
#[hemx::app(
counter_handlers,
todo_handlers,
todo_row_handlers,
@@ -216,11 +216,11 @@ fn shell(body: Html) -> Html {
ui::render(&AppShell { body })
}
#[slhx::component("counter")]
#[hemx::component("counter")]
mod counter_handlers {
use super::*;
#[slhx::handler]
#[hemx::handler]
async fn increment(State(state): State<Arc<ExampleState>>) -> impl IntoEffect {
// req: examples/001
let mut counter = state.counter.lock().unwrap();
@@ -229,11 +229,11 @@ mod counter_handlers {
}
}
#[slhx::component("todos")]
#[hemx::component("todos")]
mod todo_handlers {
use super::*;
#[slhx::handler]
#[hemx::handler]
async fn add_todo(
State(state): State<Arc<ExampleState>>,
Form(form): Form<NewTodo>,
@@ -261,7 +261,7 @@ mod todo_handlers {
))
}
#[slhx::handler]
#[hemx::handler]
async fn rename_todo(
State(state): State<Arc<ExampleState>>,
Form(form): Form<RenameTodo>,
@@ -269,7 +269,7 @@ mod todo_handlers {
rename_todo_effect(state, form)
}
#[slhx::handler]
#[hemx::handler]
async fn delete_todo(
State(state): State<Arc<ExampleState>>,
Form(form): Form<DeleteTodo>,
@@ -278,11 +278,11 @@ mod todo_handlers {
}
}
#[slhx::component("todo_row")]
#[hemx::component("todo_row")]
mod todo_row_handlers {
use super::*;
#[slhx::handler]
#[hemx::handler]
async fn rename_todo_row(
State(state): State<Arc<ExampleState>>,
Form(form): Form<RenameTodo>,
@@ -290,7 +290,7 @@ mod todo_row_handlers {
rename_todo_effect(state, form)
}
#[slhx::handler]
#[hemx::handler]
async fn delete_todo_row(
State(state): State<Arc<ExampleState>>,
Form(form): Form<DeleteTodo>,
@@ -299,11 +299,11 @@ mod todo_row_handlers {
}
}
#[slhx::component("wizard")]
#[hemx::component("wizard")]
mod wizard_handlers {
use super::*;
#[slhx::handler]
#[hemx::handler]
async fn next_step(
State(state): State<Arc<ExampleState>>,
Form(form): Form<WizardInput>,
@@ -316,11 +316,11 @@ mod wizard_handlers {
}
}
#[slhx::component("auth")]
#[hemx::component("auth")]
mod auth_handlers {
use super::*;
#[slhx::handler]
#[hemx::handler]
async fn login(
State(_state): State<Arc<ExampleState>>,
Form(credentials): Form<Credentials>,
@@ -401,7 +401,7 @@ fn render_docs_content(message: &'static str) -> Html {
mod tests {
use super::*;
use scraper::{Html, Selector};
use slhx_test::{
use hemx_test::{
article_selector, document_title_selector, escaped_markup_selector, heading_selector,
inspect_batch, keyed_items_selector, keyed_selector, list_item_selector,
page_nav_link_selector, prose_selector, root_element_selector, runtime_script_selector,
@@ -411,8 +411,8 @@ mod tests {
Selector::parse(value).expect("test selector parses")
}
fn form<I>(handle: slhx::Handle<I>, fields: &[(&str, &str)]) -> slhx_axum::InteractionForm {
slhx_axum::InteractionForm::for_handle(
fn form<I>(handle: hemx::Handle<I>, fields: &[(&str, &str)]) -> hemx_axum::InteractionForm {
hemx_axum::InteractionForm::for_handle(
handle,
fields
.iter()
@@ -430,7 +430,7 @@ mod tests {
.select(&selector(document_title_selector()))
.next()
.map(|title| title.text().collect::<String>()),
Some("slhx v0 examples".to_owned())
Some("hemx v0 examples".to_owned())
);
assert_eq!(
document
+3 -3
View File
@@ -3,8 +3,8 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>slhx v0 examples</title>
<script src="/slhx.js" defer></script>
<title>hemx v0 examples</title>
<script src="/hemx.js" defer></script>
<style>
body { font-family: system-ui, sans-serif; margin: 2rem; max-width: 54rem; }
section, main { border: 1px solid #ddd; border-radius: .5rem; margin: 1rem 0; padding: 1rem; }
@@ -13,7 +13,7 @@
</style>
</head>
<body>
<h1>slhx v0 browser examples</h1>
<h1>hemx v0 browser examples</h1>
<p>Try the counter, todo form, wizard, login, page swap, and live SSE notifications.</p>
{+= self.body =+}
</body>
+3 -3
View File
@@ -1,8 +1,8 @@
<section data-slhx-root="auth">
<form data-slhx-handle="login" data-slhx-form="credentials">
<section data-hemx-root="auth">
<form data-hemx-handle="login" data-hemx-form="credentials">
<input name="email" type="email" autocomplete="username" required>
<input name="password" type="password" autocomplete="current-password" required>
<button type="submit">Sign in</button>
</form>
<p data-slhx-slot="login_status">Signed out</p>
<p data-hemx-slot="login_status">Signed out</p>
</section>
+3 -3
View File
@@ -1,4 +1,4 @@
<section data-slhx-root="counter">
<output data-slhx-slot="counter_value">0</output>
<button type="button" data-slhx-handle="increment">+</button>
<section data-hemx-root="counter">
<output data-hemx-slot="counter_value">0</output>
<button type="button" data-hemx-handle="increment">+</button>
</section>
+2 -2
View File
@@ -1,4 +1,4 @@
<section data-slhx-root="notifications" data-slhx-sse="/events">
<section data-hemx-root="notifications" data-hemx-sse="/events">
<h2>Notifications</h2>
<div data-slhx-slot="notifications">No notifications</div>
<div data-hemx-slot="notifications">No notifications</div>
</section>
+5 -5
View File
@@ -1,7 +1,7 @@
<main data-slhx-root="docs">
<nav data-slhx-slot="nav">
<a href="/docs" data-slhx-nav="">Docs</a>
<main data-hemx-root="docs">
<nav data-hemx-slot="nav">
<a href="/docs" data-hemx-nav="">Docs</a>
</nav>
<article data-slhx-slot="content">{+= self.content =+}</article>
<title data-slhx-slot="title">{+ self.title +}</title>
<article data-hemx-slot="content">{+= self.content =+}</article>
<title data-hemx-slot="title">{+ self.title +}</title>
</main>
+2 -2
View File
@@ -1,10 +1,10 @@
<li>
<span>{+ self.title +}</span>
<form data-slhx-handle="rename_todo_row">
<form data-hemx-handle="rename_todo_row">
<input type="hidden" name="id" +value="self.id">
<button type="submit" name="title" value="Renamed todo">Rename</button>
</form>
<form data-slhx-handle="delete_todo_row">
<form data-hemx-handle="delete_todo_row">
<button type="submit" name="id" +value="self.id">Delete</button>
</form>
</li>
+8 -8
View File
@@ -1,19 +1,19 @@
<section data-slhx-root="todos">
<form data-slhx-handle="add_todo" data-slhx-form="new_todo">
<section data-hemx-root="todos">
<form data-hemx-handle="add_todo" data-hemx-form="new_todo">
<input name="title" required="required">
<button type="submit">Add</button>
</form>
<p data-slhx-slot="summary">{+ self.summary +}</p>
<div data-slhx-slot="todo_list">
<ul data-slhx-slot="todo_row">
<p data-hemx-slot="summary">{+ self.summary +}</p>
<div data-hemx-slot="todo_list">
<ul data-hemx-slot="todo_row">
<template h-for="todo in &self.items" h-key="todo.id">
<li data-slhx-slot="todo_row" +data-key="todo.id">
<li data-hemx-slot="todo_row" +data-key="todo.id">
<span>{+ todo.title +}</span>
<form data-slhx-handle="rename_todo">
<form data-hemx-handle="rename_todo">
<input type="hidden" name="id" +value="todo.id">
<button type="submit" name="title" value="Renamed todo">Rename</button>
</form>
<form data-slhx-handle="delete_todo">
<form data-hemx-handle="delete_todo">
<button type="submit" name="id" +value="todo.id">Delete</button>
</form>
</li>
+3 -3
View File
@@ -1,7 +1,7 @@
<section data-slhx-root="wizard">
<form data-slhx-handle="next_step" data-slhx-form="wizard_input">
<section data-hemx-root="wizard">
<form data-hemx-handle="next_step" data-hemx-form="wizard_input">
<input type="hidden" name="step" value="1" required>
<div data-slhx-slot="wizard_step">Step 1</div>
<div data-hemx-slot="wizard_step">Step 1</div>
<button type="submit">Next</button>
</form>
</section>