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:
2026-05-17 00:52:41 +00:00
parent 958b45272d
commit 4020ad62c5
44 changed files with 4276 additions and 867 deletions
@@ -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.