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
+12
View File
@@ -0,0 +1,12 @@
[package]
name = "hemx"
version.workspace = true
edition.workspace = true
[lib]
path = "src/lib.rs"
[dependencies]
hemplate = { path = "../../hemplate/hemplate" }
hemx-core = { path = "../hemx-core" }
hemx-derive = { path = "../hemx-derive" }
+203
View File
@@ -0,0 +1,203 @@
//! Public authoring facade for hemx applications.
//!
//! Most application code should depend on this crate, use the proc-macros from
//! here, and import generated resources through `#[hemx::surface]`.
use hemx_core::{Effect, KeyedSlot, SafeHtml, Slot};
pub use hemx_core::{
navigate, push, redirect, replace, Atom, ComponentRef, CssClass, CssClasses, EventName, Form,
FormContract, FormControlKind, FormError, FormField, FormModel, FormValue, FromForm,
GeneratedTarget, Handle, IntoEffect, ParamName,
};
pub use hemx_derive::{app, component, form, handler, surface};
/// Advanced/raw hemx primitives used by generated code, integrations, and tests.
///
/// Beginner-facing application code should prefer generated targets, generated
/// handles/forms/classes, `Html`, `IntoEffect`, and tuple composition. req: dx/001 req: public_api/005
pub mod advanced {
pub use hemx_core::*;
}
/// Rendered, checked HTML produced by hemplate/hemx rendering helpers.
///
/// Raw trusted HTML construction remains an advanced boundary; beginner-facing
/// code should receive `Html` values from generated render helpers. req: public_api/005
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Html(SafeHtml);
impl Html {
pub fn as_str(&self) -> &str {
self.0.as_str()
}
pub fn into_string(self) -> String {
self.0.into_string()
}
pub fn join(fragments: impl IntoIterator<Item = Html>) -> Self {
Self(SafeHtml::join(fragments.into_iter().map(Into::into)))
}
}
impl From<Html> for SafeHtml {
fn from(value: Html) -> Self {
value.0
}
}
impl AsRef<str> for Html {
fn as_ref(&self) -> &str {
self.as_str()
}
}
impl core::fmt::Display for Html {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(self.as_str())
}
}
#[doc(hidden)]
pub mod __private {
use super::{Html, SafeHtml};
pub fn html_trusted(value: impl Into<String>) -> Html {
Html(SafeHtml::trusted(value))
}
}
pub fn render(view: &impl hemplate::Hemplate) -> Html {
let mut html = String::new();
view.render_into(&mut html)
.expect("hemplate view renders into hemx effect payload");
__private::html_trusted(html)
}
/// A hemplate partial that carries the stable key for a generated keyed target.
///
/// Generated keyed target helpers use this to keep ordinary handler code at the
/// level of `ui::row.replace(row)` instead of `ui::row.replace(row.id, &row)`.
/// req: canonical_authoring/003 req: codegen/002
pub trait KeyedPartial {
fn hemx_key(&self) -> String;
}
#[doc(hidden)]
pub fn render_html(view: &impl hemplate::Hemplate) -> Html {
render(view)
}
/// Compatibility shim for raw slot rendering.
///
/// Prefer generated target objects such as `targets::list.put(&view)` so
/// generated resource lowering stays attached to the view boundary. req: dx/006
#[doc(hidden)]
pub trait RenderSlotExt {
fn render(self, view: &impl hemplate::Hemplate) -> Effect;
fn render_view(self, view: &impl hemplate::Hemplate) -> Effect
where
Self: Sized,
{
self.render(view)
}
}
impl<T> RenderSlotExt for Slot<T> {
fn render(self, view: &impl hemplate::Hemplate) -> Effect {
self.html(render(view))
}
}
/// Compatibility shim for raw keyed slot rendering.
///
/// Prefer generated target objects such as `targets::row.append(&view)` so
/// generated resource lowering stays attached to the view boundary. req: dx/006
#[doc(hidden)]
pub trait RenderKeyedSlotExt<K> {
fn append(self, key: K, view: &impl hemplate::Hemplate) -> Effect;
fn prepend(self, key: K, view: &impl hemplate::Hemplate) -> Effect;
fn replace(self, key: K, view: &impl hemplate::Hemplate) -> Effect;
fn append_view(self, key: K, view: &impl hemplate::Hemplate) -> Effect
where
Self: Sized,
{
self.append(key, view)
}
fn prepend_view(self, key: K, view: &impl hemplate::Hemplate) -> Effect
where
Self: Sized,
{
self.prepend(key, view)
}
fn replace_view(self, key: K, view: &impl hemplate::Hemplate) -> Effect
where
Self: Sized,
{
self.replace(key, view)
}
}
impl<K, T> RenderKeyedSlotExt<K> for KeyedSlot<K, T>
where
K: ToString,
{
fn append(self, key: K, view: &impl hemplate::Hemplate) -> Effect {
self.append_html(key, render(view))
}
fn prepend(self, key: K, view: &impl hemplate::Hemplate) -> Effect {
self.prepend_html(key, render(view))
}
fn replace(self, key: K, view: &impl hemplate::Hemplate) -> Effect {
self.replace_html(key, render(view))
}
}
pub mod prelude {
pub use crate::render;
pub use crate::Html;
pub use hemx_core::{
navigate, push, redirect, replace, Atom, ComponentRef, CssClass, CssClasses, EventName,
Form, FormModel, FormValue, Handle, IntoEffect, ParamName,
};
pub use hemx_derive::{app, component, form, handler, surface};
}
#[cfg(test)]
mod tests {
struct InlineView;
impl hemplate::Hemplate for InlineView {
fn render_into(&self, out: &mut String) -> Result<(), hemplate::error::HemplateError> {
out.push_str("<strong>ok</strong>");
Ok(())
}
}
#[test]
fn render_is_the_short_safe_html_helper() {
// req: dx/006 req: html_safety/002
assert_eq!(crate::render(&InlineView).as_str(), "<strong>ok</strong>");
assert_eq!(
crate::render_html(&InlineView).as_str(),
"<strong>ok</strong>"
);
}
#[test]
fn prelude_exports_html_for_page_composition() {
// req: dx/006 req: public_api/005 req: html_safety/002
use crate::prelude::*;
let html = Html::join([render(&InlineView)]);
assert_eq!(html.as_str(), "<strong>ok</strong>");
}
}