From 96f01f7a28c996b8e15c3a72b729bea6617cb009 Mon Sep 17 00:00:00 2001 From: adnaan <758447+adnaan@users.noreply.github.com> Date: Mon, 29 Jun 2026 05:10:59 +0000 Subject: [PATCH] Sync from livetemplate@v0.15.0 --- content/contributing/livetemplate.md | 6 ++-- content/guides/ephemeral-components.md | 4 +-- content/guides/observability.md | 4 +-- content/guides/progressive-complexity.md | 25 ++++++++++++--- content/guides/scaling.md | 4 +-- content/guides/standard-html-reactivity.md | 4 +-- content/reference/api.md | 4 +-- content/reference/authentication.md | 4 +-- content/reference/client-attributes.md | 20 +++++++----- content/reference/configuration.md | 4 +-- content/reference/controller-pattern.md | 4 +-- content/reference/error-handling.md | 4 +-- content/reference/limitations.md | 8 ++--- content/reference/navigate.md | 4 +-- content/reference/progressive-complexity.md | 6 ++-- content/reference/pubsub.md | 4 +-- content/reference/server-actions.md | 4 +-- content/reference/session.md | 16 ++++++++-- content/reference/template-support-matrix.md | 32 ++++++++++++++++++-- content/reference/uploads.md | 9 ++++-- 20 files changed, 117 insertions(+), 53 deletions(-) diff --git a/content/contributing/livetemplate.md b/content/contributing/livetemplate.md index 725814d..dab1800 100644 --- a/content/contributing/livetemplate.md +++ b/content/contributing/livetemplate.md @@ -2,8 +2,8 @@ title: "Contributing to LiveTemplate Core Library" source_repo: "https://github.com/livetemplate/livetemplate" source_path: "CONTRIBUTING.md" -source_ref: "v0.13.0" -source_commit: "4c5f1c71b2de9abf1abf76d0ddcafd1ec31201dd" +source_ref: "v0.15.0" +source_commit: "7a9b692568c98566bbf14cba77448cc6ab83cc56" --- # Contributing to LiveTemplate Core Library @@ -213,7 +213,7 @@ livetemplate/ │ ├── parse/ # Phase 1: Template parsing (AST evaluation) │ ├── build/ # Phase 2: Tree types, fingerprinting, wrapper injection │ ├── diff/ # Phase 3: Tree comparison and update generation -│ ├── render/ # Phase 4: HTML rendering and minification +│ ├── render/ # Phase 4: HTML rendering │ ├── send/ # Phase 5: Message parsing and serialization │ ├── session/ # WebSocket connection registry │ ├── observe/ # Metrics and Prometheus export diff --git a/content/guides/ephemeral-components.md b/content/guides/ephemeral-components.md index b0817ff..125f1f1 100644 --- a/content/guides/ephemeral-components.md +++ b/content/guides/ephemeral-components.md @@ -2,8 +2,8 @@ title: "Ephemeral Components Guide" source_repo: "https://github.com/livetemplate/livetemplate" source_path: "docs/guides/ephemeral-components.md" -source_ref: "v0.13.0" -source_commit: "4c5f1c71b2de9abf1abf76d0ddcafd1ec31201dd" +source_ref: "v0.15.0" +source_commit: "7a9b692568c98566bbf14cba77448cc6ab83cc56" --- # Ephemeral Components Guide diff --git a/content/guides/observability.md b/content/guides/observability.md index cedcb05..506fd8f 100644 --- a/content/guides/observability.md +++ b/content/guides/observability.md @@ -2,8 +2,8 @@ title: "LiveTemplate Observability Guide" source_repo: "https://github.com/livetemplate/livetemplate" source_path: "docs/guides/OBSERVABILITY.md" -source_ref: "v0.13.0" -source_commit: "4c5f1c71b2de9abf1abf76d0ddcafd1ec31201dd" +source_ref: "v0.15.0" +source_commit: "7a9b692568c98566bbf14cba77448cc6ab83cc56" --- # LiveTemplate Observability Guide diff --git a/content/guides/progressive-complexity.md b/content/guides/progressive-complexity.md index 858bd43..b936593 100644 --- a/content/guides/progressive-complexity.md +++ b/content/guides/progressive-complexity.md @@ -2,8 +2,8 @@ title: "Progressive Complexity Guide" source_repo: "https://github.com/livetemplate/livetemplate" source_path: "docs/guides/progressive-complexity.md" -source_ref: "v0.13.0" -source_commit: "4c5f1c71b2de9abf1abf76d0ddcafd1ec31201dd" +source_ref: "v0.15.0" +source_commit: "7a9b692568c98566bbf14cba77448cc6ab83cc56" --- # Progressive Complexity Guide @@ -116,7 +116,7 @@ The button's `name` routes to the corresponding Go method. Button `value` and `d ## 4. Validation from HTML Attributes -> **Note:** Auto-wiring the form schema from template statics is not yet implemented. Currently you must call `ctx.WithFormSchema(ExtractFormSchema(statics))` manually. For production validation, use `ctx.BindAndValidate()` with struct tags. `formnovalidate` on buttons is not yet respected server-side. +> **Note:** The form schema is auto-wired from your template's HTML attributes, so `ctx.ValidateForm()` works without calling `WithFormSchema` manually. For production validation with custom rules, use `ctx.BindAndValidate()` with struct tags. HTML validation attributes (`required`, `pattern`, `min`, `max`, `minlength`, `maxlength`, `type`) can be extracted by the framework. Use `ctx.ValidateForm()` instead of writing Go struct tags: @@ -152,13 +152,28 @@ func (c *Controller) Submit(state State, ctx *livetemplate.Context) (State, erro No Go struct tags needed. The `required`, `type="email"`, `minlength="5"`, `min="18"` attributes are the validation rules. -Use `formnovalidate` on buttons that should skip validation: +Use `formnovalidate` on a submit button to skip `ctx.ValidateForm()` for that +submit path — the canonical "save draft" flow: ```html - + ``` +The framework reads the `formnovalidate` button's `name` from your template and +skips validation when that button is the submitter — on every tier (WebSocket, +HTTP-fetch, and no-JS native POST). Three things to know: + +- **Name it.** The skip is matched by the submitter's `name`; a dynamic + (`{{...}}`) name can't be detected. +- **No-JS: no `value`.** On the pure no-JS tier the server identifies the + submitter by its empty-value form field, so a `formnovalidate` button that + carries a `value` won't be recognized as the submitter there (JS tiers send an + explicit submitter and are unaffected). +- **Not a security boundary.** Skipping is client-controlled convenience for + draft flows — enforce server-authoritative rules unconditionally where it + matters. + --- ## 5. Dialogs diff --git a/content/guides/scaling.md b/content/guides/scaling.md index d7b5a9b..9e84265 100644 --- a/content/guides/scaling.md +++ b/content/guides/scaling.md @@ -2,8 +2,8 @@ title: "LiveTemplate Scaling Guide" source_repo: "https://github.com/livetemplate/livetemplate" source_path: "docs/guides/SCALING.md" -source_ref: "v0.13.0" -source_commit: "4c5f1c71b2de9abf1abf76d0ddcafd1ec31201dd" +source_ref: "v0.15.0" +source_commit: "7a9b692568c98566bbf14cba77448cc6ab83cc56" --- # LiveTemplate Scaling Guide diff --git a/content/guides/standard-html-reactivity.md b/content/guides/standard-html-reactivity.md index 29c2012..16861f0 100644 --- a/content/guides/standard-html-reactivity.md +++ b/content/guides/standard-html-reactivity.md @@ -2,8 +2,8 @@ title: "Standard HTML Reactivity" source_repo: "https://github.com/livetemplate/livetemplate" source_path: "docs/guides/standard-html-reactivity.md" -source_ref: "v0.13.0" -source_commit: "4c5f1c71b2de9abf1abf76d0ddcafd1ec31201dd" +source_ref: "v0.15.0" +source_commit: "7a9b692568c98566bbf14cba77448cc6ab83cc56" --- # Standard HTML Reactivity diff --git a/content/reference/api.md b/content/reference/api.md index 00f8e69..0434a6b 100644 --- a/content/reference/api.md +++ b/content/reference/api.md @@ -2,8 +2,8 @@ title: "Go Library API Reference" source_repo: "https://github.com/livetemplate/livetemplate" source_path: "docs/references/api-reference.md" -source_ref: "v0.13.0" -source_commit: "4c5f1c71b2de9abf1abf76d0ddcafd1ec31201dd" +source_ref: "v0.15.0" +source_commit: "7a9b692568c98566bbf14cba77448cc6ab83cc56" --- # Go Library API Reference diff --git a/content/reference/authentication.md b/content/reference/authentication.md index 6da9da0..746746f 100644 --- a/content/reference/authentication.md +++ b/content/reference/authentication.md @@ -2,8 +2,8 @@ title: "Authentication Reference" source_repo: "https://github.com/livetemplate/livetemplate" source_path: "docs/references/authentication.md" -source_ref: "v0.13.0" -source_commit: "4c5f1c71b2de9abf1abf76d0ddcafd1ec31201dd" +source_ref: "v0.15.0" +source_commit: "7a9b692568c98566bbf14cba77448cc6ab83cc56" --- # Authentication Reference diff --git a/content/reference/client-attributes.md b/content/reference/client-attributes.md index 1ddcf52..98a927a 100644 --- a/content/reference/client-attributes.md +++ b/content/reference/client-attributes.md @@ -2,8 +2,8 @@ title: "Client Attributes Reference" source_repo: "https://github.com/livetemplate/livetemplate" source_path: "docs/references/client-attributes.md" -source_ref: "v0.13.0" -source_commit: "4c5f1c71b2de9abf1abf76d0ddcafd1ec31201dd" +source_ref: "v0.15.0" +source_commit: "7a9b692568c98566bbf14cba77448cc6ab83cc56" --- # Client Attributes Reference @@ -819,7 +819,16 @@ User-toggled `checked` state on `` and ` Item 1 ``` -**Radio group caveat:** Browser mutual exclusion fires synchronously during the morphdom pass. If you need to force-reset a radio group from the server, add `data-lvt-force-update` to *all* radios in the group, not just the one being checked. +**Exception — `lvt-on:click` controls are server-authoritative.** A checkbox or radio with an `lvt-on:click` handler routes its own toggle to the server, which echoes back the authoritative `checked` state in its re-render. There is no pending local-only selection to protect, so the server's rendered value wins automatically — without needing `data-lvt-force-update`. This is what makes a server-driven toggle (e.g. a todo checkbox) reflect correctly. + +```html + + +``` + +If instead you want the user's selection to win for a checkbox that *also* sends a click to the server (e.g. a click handler that only logs a side effect), use `lvt-on:change` — only `lvt-on:click` opts into server authority. + +**Radio group caveat:** Browser mutual exclusion fires synchronously during the morphdom pass. If you need to force-reset a radio group from the server, make the server send the authoritative state (via `lvt-on:click` or `data-lvt-force-update`) on *all* radios in the group, not just the one being checked. ### Dialog Open State @@ -873,7 +882,7 @@ All automatic preservation behaviors can be overridden by adding `data-lvt-force | Preserved State | Mechanism | Override | |-----------|-------------|---------| -| Checkbox/radio `checked` | Property copied to virtual DOM | `data-lvt-force-update` on the input | +| Checkbox/radio `checked` | Property copied to virtual DOM | `data-lvt-force-update` on the input, or an `lvt-on:click` handler (auto server-authoritative) | | Dialog `open` | morphdom update skipped while dialog is open | `data-lvt-force-update` on the dialog | | Datalist dropdown | Entire morphdom pass deferred while datalist input focused | `data-lvt-force-update` on the connected `` (overrides deferral for the entire pass) | | Focused input elements | morphdom update skipped | `data-lvt-force-update` on the input | @@ -1009,9 +1018,6 @@ Complete reference of all `lvt-*` and `data-*` template attributes. | `lvt-key` | Filter keyboard events by key | `lvt-key="Enter"` | | `lvt-mod:debounce` | Debounce delay in milliseconds | `lvt-mod:debounce="300"` | | `lvt-mod:throttle` | Throttle interval in milliseconds | `lvt-mod:throttle="100"` | -| `lvt-mod:skip-when-typing` | Suppress a keyboard binding while focus is in a text field | `
` | - -**`lvt-mod:skip-when-typing`** lets a global keyboard shortcut coexist with text entry. When the attribute is present, the binding does **not** fire if `document.activeElement` is (or is inside) an editable element — a text-like ``, `