✨ feat: enhance medialib image handling and add asset URL resolution
- Implemented `resolveApiAssetUrl` function to normalize asset URLs based on API base. - Updated `MedialibImage` component to utilize new asset URL resolution and added support for alt text and class properties. - Enhanced image loading behavior with improved width measurement and focal point handling. - Added placeholder image handling and improved accessibility with alt text. - Introduced new test script for auditing broken links in skill documentation. - Expanded seeded test content to include medialib entries and updated related tests for pagebuilder previews. - Improved global setup and teardown logging for clarity on seeded content management.
This commit is contained in:
@@ -238,6 +238,94 @@ Keep the backend responsible for:
|
||||
- persistence
|
||||
- normalization of response shape
|
||||
|
||||
## Hook step order: bind → validate → handle → return
|
||||
|
||||
Action hooks run in a **fixed step order** in tibi-server:
|
||||
|
||||
1. **bind** — runs first. `context.data` is NOT yet set (body not parsed).
|
||||
2. Body parsing — happens AFTER bind. JSON body is set to `context.data`.
|
||||
3. **validate** — `context.data` is available here for validation.
|
||||
4. **handle** — main business logic. `context.data` is available.
|
||||
5. **return** — final response shaping.
|
||||
|
||||
**Critical:** The bind hook runs BEFORE the HTTP body is parsed. Do NOT access `context.data` in bind — it will be undefined. Use `handle` or `validate` for data access.
|
||||
|
||||
```yaml
|
||||
# Correct: use handle step for data access
|
||||
hooks:
|
||||
post:
|
||||
handle:
|
||||
type: javascript
|
||||
file: hooks/actions/contact/handle.js
|
||||
```
|
||||
|
||||
Action URL pattern (through BrowserSync proxy): `/api/_actions/{name}` — NOT `/api/{name}`. The tibi-server registers actions under `/_actions/`.
|
||||
|
||||
```sh
|
||||
curl -X POST "https://project.code.testversion.online/api/_actions/contact"
|
||||
```
|
||||
|
||||
## Permissions for public actions
|
||||
|
||||
Actions need explicit public write permission for unauthenticated access:
|
||||
|
||||
```yaml
|
||||
- name: contact
|
||||
path: contact
|
||||
permissions:
|
||||
public:
|
||||
methods:
|
||||
post: true
|
||||
hooks:
|
||||
post:
|
||||
handle:
|
||||
type: javascript
|
||||
file: hooks/actions/contact/handle.js
|
||||
```
|
||||
|
||||
## Inline form validation (frontend)
|
||||
|
||||
Use `$state` variables for inline errors instead of `alert()`:
|
||||
|
||||
```svelte
|
||||
<script lang="ts">
|
||||
let startDate = $state("")
|
||||
let endDate = $state("")
|
||||
let dateError = $state("")
|
||||
|
||||
function handleSubmit() {
|
||||
if (!startDate) { dateError = "Bitte Mietbeginn wählen"; return }
|
||||
if (!endDate) { dateError = "Bitte Mietende wählen"; return }
|
||||
if (startDate > endDate) { dateError = "Mietende muss nach Mietbeginn liegen"; return }
|
||||
dateError = ""
|
||||
// submit logic
|
||||
}
|
||||
</script>
|
||||
|
||||
<form onsubmit={handleSubmit}>
|
||||
<input type="date" bind:value={startDate} />
|
||||
<input type="date" bind:value={endDate} />
|
||||
{#if dateError}
|
||||
<div class="text-red-600 bg-red-50 px-3 py-2 rounded-lg">{dateError}</div>
|
||||
{/if}
|
||||
<button type="submit">Absenden</button>
|
||||
</form>
|
||||
```
|
||||
|
||||
Errors should appear directly below the relevant field group, not as a browser alert.
|
||||
|
||||
## Frontend form submission
|
||||
|
||||
Submit to the action endpoint using the correct path:
|
||||
|
||||
```ts
|
||||
fetch("/api/_actions/contact", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ name, email, message, consent: true }),
|
||||
})
|
||||
```
|
||||
|
||||
## Response design
|
||||
|
||||
Return a small stable payload that the frontend can rely on.
|
||||
|
||||
Reference in New Issue
Block a user