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
+340
View File
@@ -0,0 +1,340 @@
#[test]
fn runtime_posts_urlencoded_forms_by_default() {
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("new URLSearchParams()"));
assert!(source.contains("form.getAttribute(\"method\")"));
assert!(source.contains("multipart/form-data"));
assert!(source.contains("const body = method === \"GET\" || method === \"HEAD\" ? undefined : requestBody(data, multipart)"));
assert!(source.contains("application/x-www-form-urlencoded;charset=UTF-8"));
}
#[test]
fn runtime_preserves_multipart_file_upload_fallback_shape() {
// req: multipart/003
let source = hemx_js::RUNTIME_JS;
assert!(source.contains(
"multipart: form && String(form.enctype).toLowerCase() === \"multipart/form-data\""
));
assert!(source.contains("if (value instanceof File) continue"));
assert!(source.contains("return multipart ? data : urlEncoded(data)"));
assert!(source.contains("if (body instanceof URLSearchParams) headers[\"Content-Type\"] = \"application/x-www-form-urlencoded;charset=UTF-8\""));
}
#[test]
fn runtime_uses_root_scoped_walks_not_dom_selector_apis() {
// req: pitch/002 req: runtime/001 req: target_policy/001
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("function firstElement(scope, predicate)"));
assert!(source.contains("function closestInRoot(start, root, predicate)"));
assert!(source.contains("root.addEventListener(name, (event) =>"));
assert!(!source.contains("querySelector"));
assert!(!source.contains("querySelectorAll"));
assert!(!source.contains(".closest("));
assert!(!source.contains(".matches("));
assert!(!source.contains("getElementsBy"));
assert!(!source.contains("document.getElementById"));
}
#[test]
fn runtime_targets_generated_resources_not_response_selectors() {
// req: target_policy/001 req: target_policy/002
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("function targetFor(scope, ref)"));
assert!(source.contains("return generatedTarget(scope, ref.resource.id)"));
assert!(source.contains("function firstElement(scope, predicate)"));
assert!(source.contains("function generatedResource(el, id)"));
assert!(source.contains("return firstElement(scope, (el) => attrEquals(el, \"data-key\", key) && withinGeneratedResource(el, scope, id))"));
assert!(
source.contains("const nodes = fragmentNodes(op.payload, op.key, op.target.resource.id)")
);
assert!(source.contains("if (op.target.scope && op.target.scope.kind === \"key\" && op.payload.kind === \"html\") replacePayload(target, op.payload, op.target.scope.value, op.target.resource.id)"));
assert!(source.contains("function replacePayload(target, payload, key, resourceId)"));
assert!(source.contains("target.replaceWith(...nodes)"));
assert!(source.contains("firstElement.setAttribute(\"data-sid\", resourceId)"));
assert!(source.contains("const target = generatedTarget(scope, id)"));
assert!(source.contains("if (!target) return missing(scope, op.target)"));
assert!(!source.contains("data-hemx-target"));
assert!(!source.contains("data-hemx-select"));
}
#[test]
fn runtime_interval_dispatch_avoids_duplicate_timers() {
// req: convention/005
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("const everyTimers = new WeakMap()"));
assert!(source.contains("forEachElement(root, (el) =>"));
assert!(source.contains("!el.hasAttribute(\"data-hemx-every\") || everyTimers.has(el)"));
assert!(
source.contains("if (!el.hasAttribute(\"data-hemx-every\") || everyTimers.has(el)) return")
);
assert!(source.contains(
"setInterval(() => document.contains(el) ? send(el, \"every\") : stopPolling(el), ms)"
));
assert!(source.contains("function stopPolling(el)"));
assert!(source.contains("clearInterval(everyTimers.get(el))"));
assert!(source.contains("everyTimers.delete(el)"));
}
#[test]
fn runtime_toggles_pending_conventions_around_requests() {
// req: convention/007 req: convention/008
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("function showPending(el, on)"));
assert!(source.contains("el.getAttribute(\"data-hemx-pending-class\")"));
assert!(source.contains("const pendingClassStates = new WeakMap()"));
assert!(source.contains("function togglePendingClass(el, klass, on)"));
assert!(source.contains("hadClass: el.classList.contains(klass)"));
assert!(source.contains("if (state.hadClass) el.classList.add(state.className)"));
assert!(source.contains("const indicatorStates = new WeakMap()"));
assert!(source.contains("function toggleIndicator(indicator, on)"));
assert!(source.contains("toggleIndicator(i, on)"));
assert!(source.contains("indicator.hidden = state.hidden"));
assert!(source.contains("el.hasAttribute(\"data-hemx-disable-while-pending\")"));
assert!(source.contains("if (isDisableControl(el)) controls.push(el)"));
assert!(source.contains(
"forEachElement(el, (child) => { if (isDisableControl(child)) controls.push(child); })"
));
assert!(source.contains("const disabledStates = new WeakMap()"));
assert!(source.contains("function toggleDisabled(control, on)"));
assert!(source
.contains("else disabledStates.set(control, { count: 1, disabled: control.disabled })"));
assert!(source.contains("control.disabled = state.disabled"));
assert!(source.contains("controls.forEach((c) => toggleDisabled(c, on))"));
assert!(source.contains("showPending(target, true)"));
assert!(source.contains("showPending(target, false)"));
}
#[test]
fn runtime_confirms_before_handler_dispatch() {
// req: convention/004
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("el.getAttribute(\"data-hemx-confirm\") && !confirm(el.getAttribute(\"data-hemx-confirm\"))"));
assert!(source.contains("return;"));
}
#[test]
fn runtime_fetches_with_same_origin_credentials() {
// req: auth/005
let source = hemx_js::RUNTIME_JS;
assert_eq!(source.matches("credentials: \"same-origin\"").count(), 2);
}
#[test]
fn runtime_handles_get_forms_without_request_body() {
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("function requestUrl(form, data, method)"));
assert!(source.contains("method === \"GET\" || method === \"HEAD\" ? undefined : requestBody"));
assert!(source.contains("if (method === \"GET\") url.search = urlEncoded(data).toString()"));
}
#[test]
fn runtime_clicking_submitter_schedules_form_submit() {
// req: convention/004 req: runtime/001
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("function formOwner(el)"));
assert!(source.contains("function formHandleId(form)"));
assert!(source.contains("function elementById(scope, id)"));
assert!(
source.contains("return elementById(rootOf(el) || document, el.getAttribute(\"form\"))")
);
assert!(!source.contains("document.getElementById(el.getAttribute(\"form\"))"));
assert!(source.contains(
"const direct = closestInRoot(event.target, root, (el) => el.hasAttribute(HID))"
));
assert!(source.contains("const submitter = closestInRoot(event.target, root, (el) =>"));
assert!(source.contains("el.tagName === \"BUTTON\" && (!el.hasAttribute(\"type\") || el.getAttribute(\"type\") === \"submit\")"));
assert!(source.contains("form.reportValidity && !form.reportValidity()"));
assert!(source.contains("schedule(form, \"submit\", submitter)"));
assert!(source.contains("function formDataFor(el, eventName, source = el)"));
assert!(source.contains("data.append(source.name, source.value)"));
assert!(source.contains("schedule(el, name, event.submitter || el)"));
}
#[test]
fn runtime_supports_drag_drop_params_without_user_js() {
// req: htmx_equivalents/002, req: dx/008
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("const dragKeys = new WeakMap()"));
assert!(source.contains("dragstart"));
assert!(source.contains("dragover"));
assert!(source.contains("eventName === \"drop\""));
assert!(source.contains("data.set(\"work_id\", dragKey)"));
}
#[test]
fn runtime_supports_queued_request_policy() {
// req: convention/006
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("function normalizedPolicy(value)"));
assert!(source.contains("value === \"latest\" || value === \"queue\" || value === \"drop\" || value === \"parallel\""));
assert!(
source.contains("const policy = normalizedPolicy(el.getAttribute(\"data-hemx-policy\"))")
);
assert!(source.contains("const queues = new WeakMap()"));
assert!(source.contains("policy === \"queue\""));
assert!(source.contains("const base = queues.get(target) || active.done"));
}
#[test]
fn runtime_latest_request_policy_releases_superseded_pending_state() {
// req: convention/006 req: convention/007
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("if (active && policy === \"latest\") {\n active.abort.abort();\n showPending(target, false);\n }"));
assert!(source.contains("if (pending.get(target)?.abort === abort)"));
}
#[test]
fn runtime_parallel_request_policy_releases_each_pending_state() {
// req: convention/006 req: convention/007 req: convention/008
let source = hemx_js::RUNTIME_JS;
assert!(source.contains(
"else if (policy === \"parallel\") {\n showPending(target, false);\n }"
));
assert!(source.contains("const pendingClassStates = new WeakMap()"));
assert!(source.contains("const indicatorStates = new WeakMap()"));
assert!(source.contains("const disabledStates = new WeakMap()"));
}
#[test]
fn runtime_exposes_page_swap_hooks() {
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("data-hemx-nav"));
assert!(source.contains("data-hemx-boost"));
assert!(source.contains("history.pushState"));
assert!(source.contains("popstate"));
assert!(source.contains("x-hemx-title"));
assert!(source.contains("x-hemx-fingerprint"));
assert!(source.contains("hemx:missing-content-slot"));
assert!(source.contains("else location.href = href"));
}
#[test]
fn runtime_popstate_failed_partials_reload_instead_of_stale_ui() {
// req: page_swap/005 req: page_swap/006 req: runtime/004
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("if (mode === \"none\") location.reload();"));
assert!(source.contains("if (root) navigateUrl(location.href, root, \"none\")"));
}
#[test]
fn runtime_preserves_native_navigation_escape_hatches() {
// req: page_swap/007 req: failure/006
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("function sameOriginNav(event, anchor)"));
assert!(source.contains("!event.defaultPrevented"));
assert!(source.contains("event.button === 0"));
assert!(source.contains("!event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey"));
assert!(source.contains("anchor.origin === location.origin"));
assert!(source.contains("!anchor.download"));
assert!(source.contains("anchor.target !== \"_blank\""));
}
#[test]
fn runtime_refuses_partial_updates_on_fingerprint_mismatch() {
// req: abi/003 req: abi/004 req: runtime/004
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("function compatibleFingerprint(response, root)"));
assert!(source.contains("const received = response.headers.get(\"x-hemx-fingerprint\")"));
assert!(source.contains("const expected = root && root.getAttribute(FINGERPRINT)"));
assert!(source.contains("if (!compatibleFingerprint(response, root))"));
assert!(source.contains("location.reload()"));
assert!(source.contains("if (expected && String(batch.fingerprint) !== expected)"));
}
#[test]
fn runtime_malformed_bootstrap_state_reports_and_continues() {
// req: state/004 req: state/006 req: runtime/001
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("function bootstrapState(root)"));
assert!(source.contains("try {\n const store = atomStore(root);"));
assert!(source.contains("atomStores.delete(root)"));
assert!(source.contains("emit(root, \"hemx:state-error\", String(error))"));
assert!(source.contains("bindRoot(root)"));
assert!(source.contains("bindSse(root)"));
}
#[test]
fn runtime_applies_sse_effect_batches_inside_roots() {
// req: push/001 req: push/003 req: push/006 req: runtime/001
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("const sseSources = new WeakMap()"));
assert!(source.contains("const url = root.getAttribute(\"data-hemx-sse\")"));
assert!(source.contains("const href = new URL(url, location.href)"));
assert!(source.contains("if (href.origin !== location.origin)"));
assert!(source.contains("emit(root, \"hemx:sse-error\", url)"));
assert!(source.contains("new EventSource(href.href)"));
assert!(source
.contains("source.addEventListener(\"hemx\", (event) => applySseMessage(root, event))"));
assert!(source
.contains("source.addEventListener(\"message\", (event) => applySseMessage(root, event))"));
assert!(source.contains("applyBatch(bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength), root)"));
assert!(source.contains("emit(root, \"hemx:sse-error\", url)"));
}
#[test]
fn runtime_page_swaps_lowered_slot_ids() {
// req: wire/001
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("function replaceLoweredSlots(scope, doc)"));
assert!(source.contains("forEachElement(doc.body || doc, (source)"));
assert!(source.contains("const target = generatedTarget(scope, id)"));
assert!(source.contains("target.innerHTML = source.innerHTML"));
}
#[test]
fn runtime_keeps_form_field_targets_separate_from_error_targets() {
let source = hemx_js::RUNTIME_JS;
assert!(source.contains("function fieldTarget(scope, id, field)"));
assert!(
source.contains("attrEquals(el, \"name\", field) && withinGeneratedForm(el, scope, id)")
);
assert!(source.contains("function formErrorTarget(scope, id, field)"));
assert!(source.contains(
"attrEquals(el, \"data-hemx-error-for\", field) && withinGeneratedForm(el, scope, id)"
));
}
#[test]
fn runtime_preflights_batches_before_applying_ops() {
let source = hemx_js::RUNTIME_JS;
assert!(source.contains(
"const missingTarget = batch.ops.map((op) => canApplyOp(scope, op)).find(Boolean)"
));
assert!(source.contains("function canApplyOp(scope, op)"));
assert!(source.contains("for (const op of batch.ops) applyOp(scope, op)"));
}
#[test]
fn runtime_ships_typescript_definitions() {
let source = hemx_js::RUNTIME_D_TS;
assert!(source.contains("req: ts/001"));
assert!(source.contains("export interface EffectBatch"));
assert!(source.contains("fingerprint: bigint"));
assert!(source.contains("export type Effect ="));
assert!(source.contains("decodeBatch(buffer: ArrayBuffer): EffectBatch"));
assert!(source.contains("interface Window"));
}