feat(build): surface structured template diagnostics
Add public .heml syntax authority and refactor the unkeyed generated-target error into structured diagnostic data while preserving the human compiler error. req: diagnostics/001 req: diagnostics/002
This commit is contained in:
+4
-1
@@ -6,7 +6,10 @@ raw ids, selector targeting, runtime opcodes, or Cargo internals in the normal
|
||||
path. req: diagnostics/001 req: diagnostics/002 req: diagnostics/003
|
||||
|
||||
Use this guide as the v1 checklist for common mistakes in beginner and
|
||||
production-shaped apps.
|
||||
production-shaped apps. Structured `hemx-build` diagnostics expose a file path,
|
||||
directive, target, expected template fact, and repair action so an optional
|
||||
editor overlay can share compiler authority without becoming a custom editor
|
||||
framework.
|
||||
|
||||
## Where errors happen
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
# `.heml` syntax surface
|
||||
|
||||
`.heml` files are ordinary HTML plus the small hemplate surface below. Use normal
|
||||
HTML tooling first; hemx/hemplate adds checks for the few template facts that
|
||||
Rust code generation needs. req: diagnostics/001 req: diagnostics/002
|
||||
|
||||
## Text and HTML
|
||||
|
||||
- `{+ expr +}` inserts escaped text.
|
||||
- `{+= expr =+}` inserts trusted/rendered HTML. Use it only for values already
|
||||
represented as trusted HTML in Rust.
|
||||
|
||||
```html
|
||||
<h1>{+ self.title +}</h1>
|
||||
<div>{+= self.body_html =+}</div>
|
||||
```
|
||||
|
||||
## Dynamic attributes
|
||||
|
||||
Prefix an HTML attribute with `+` when its value is a Rust expression.
|
||||
|
||||
```html
|
||||
<a +href="self.url">{+ self.label +}</a>
|
||||
<button +disabled="self.saving">Save</button>
|
||||
```
|
||||
|
||||
Dynamic attributes render HTML. They do not replace template facts such as
|
||||
`h-key` on a loop or `data-hemx-slot` names used by generated helpers.
|
||||
|
||||
## Control flow
|
||||
|
||||
```html
|
||||
<section h-if="self.logged_in">Welcome back</section>
|
||||
|
||||
<li h-for="todo in &self.todos" h-key="todo.id">
|
||||
{+ todo.title +}
|
||||
</li>
|
||||
|
||||
<div h-match="self.state">
|
||||
<p h-case="State::Loading">Loading</p>
|
||||
<p h-case="State::Ready">Ready</p>
|
||||
<p h-case="_">Unknown</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
`h-key` is required when generated targets live inside `h-for`; it must be the
|
||||
stable template fact on the loop that owns the repeated target. `+data-key` on a
|
||||
child is just rendered HTML and is not enough for generated keyed helpers.
|
||||
|
||||
## Generated hemx targets
|
||||
|
||||
Generated targets are named in templates and used from Rust through generated
|
||||
helpers. Do not target them with CSS selectors or raw ids in normal app code.
|
||||
|
||||
```html
|
||||
<main data-hemx-root="todos">
|
||||
<form data-hemx-form="new_todo" data-hemx-handle="add_todo">
|
||||
<input name="title" required>
|
||||
</form>
|
||||
|
||||
<p data-hemx-slot="notice">{+ self.notice +}</p>
|
||||
|
||||
<ul>
|
||||
<li h-for="row in &self.rows" h-key="row.id" data-hemx-slot="todo_row">
|
||||
{+ row.title +}
|
||||
</li>
|
||||
</ul>
|
||||
</main>
|
||||
```
|
||||
|
||||
Rust handlers then use generated helpers such as
|
||||
`ui::notice.set("Saved")`, `ui::todo_row.replace(row)`, and composed
|
||||
`IntoEffect` batches. The template owns target names; Rust owns state, commands,
|
||||
events, and projections.
|
||||
|
||||
## Boundary
|
||||
|
||||
This file defines the stable public authoring surface for hemx examples and
|
||||
beginner docs. It does not introduce a client component framework, custom editor
|
||||
framework, JavaScript expression language, selector targeting model, or stored DOM
|
||||
truth.
|
||||
Reference in New Issue
Block a user