diff --git a/README.md b/README.md index 77f78b41..298dc5df 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,45 @@ cd ~/code/github/incubaid/herolib bash doc.sh ``` - +## Export Behavior - Cross-Collection Assets - \ No newline at end of file +When exporting collections, Atlas now automatically handles cross-collection references: + +### Pages +If a page in Collection A links to a page in Collection B: +- The target page is copied to Collection A's export directory +- Filename is renamed to avoid conflicts: `collectionb_pagename.md` +- The link is updated to reference the local file + +### Images and Files +Images and files referenced from other collections are: +- Copied to the `img/` subdirectory of the exporting collection +- Renamed with cross-collection prefix: `othercol_filename.ext` +- Image/file references in pages are updated to the new paths + +### Result +The exported collection directory is **self-contained**: +``` +destination/ + collectiona/ + .collection + page1.md + collectionb_intro.md # Copied from Collection B + img/ + logo.png # Local image + collectionc_logo.png # Copied from Collection C +``` + +### Metadata Export + +Metadata is now exported separately using the `destination_meta` parameter: + +```heroscript +!!atlas.export + destination: './output' + destination_meta: './metadata' # Saves JSON metadata files here + include: true + redis: true +``` + +This exports collection metadata to: `./metadata/collection1.json`, `./metadata/collection2.json`, etc. \ No newline at end of file diff --git a/aiprompts/unpolly/unpolly_api.md b/aiprompts/unpolly/unpolly_api.md new file mode 100644 index 00000000..9781fce5 --- /dev/null +++ b/aiprompts/unpolly/unpolly_api.md @@ -0,0 +1,371 @@ +# Unpoly API – Complete Reference & Operational Guide for AI Coding Agents + +## Introduction + +This document serves as a complete, self-contained reference manual for the **Unpoly JavaScript API**. It is written explicitly for AI coding agents that need to generate, validate, or refactor Unpoly-enhanced HTML and JavaScript code. + +Unpoly is a front-end framework for progressive enhancement. It allows HTML pages to update fragments instead of reloading the full document, enabling seamless transitions, modals, caching, and navigation while maintaining server-side rendering. + +An AI agent should use this manual to: +- Understand each Unpoly module and its purpose. +- Generate correct `up-*` attributes and JavaScript calls. +- Detect configuration errors and provide correction suggestions. +- Apply Unpoly in automated scaffolding, validation, and optimization workflows. + +--- + +## 1. The up.link Module + +### Purpose +Handles Unpoly-enhanced navigation. Converts normal links into AJAX-based fragment updates rather than full-page reloads. + +### Core Concepts +When a user clicks a link with certain attributes, Unpoly intercepts the event and fetches the new page in the background. It then replaces specified fragments in the current document with matching elements from the response. + +### Common Attributes + +| Attribute | Description | +| --------------- | -------------------------------------------------------- | +| `up-follow` | Marks the link as handled by Unpoly. Usually implied. | +| `up-target` | CSS selector identifying which fragment(s) to replace. | +| `up-method` | Overrides HTTP method (e.g. `GET`, `POST`). | +| `up-params` | Adds query parameters to the request. | +| `up-headers` | Adds or overrides HTTP headers. | +| `up-layer` | Determines which layer (page, overlay, modal) to update. | +| `up-transition` | Defines animation during fragment replacement. | +| `up-cache` | Enables caching of the response. | +| `up-history` | Controls browser history behavior. | + +### JavaScript API Methods +- `up.link.isFollowable(element)` – Returns true if Unpoly will intercept the link. +- `up.link.follow(element, options)` – Programmatically follow the link via Unpoly. +- `up.link.preload(element, options)` – Preload the linked resource into the cache. + +### Agent Reasoning & Validation +- Ensure that every `up-follow` element has a valid `up-target` selector. +- Validate that target elements exist in both the current DOM and the server response. +- Recommend `up-cache` for commonly visited links to improve performance. +- Prevent using `target="_blank"` or `download` attributes with Unpoly links. + +### Example +```html +View Profile +``` + +--- + +## 2. The up.form Module + +### Purpose +Handles progressive enhancement for forms. Submissions happen via AJAX and update only specific fragments. + +### Core Attributes + +| Attribute | Description | +| ---------------- | --------------------------------------- | +| `up-submit` | Marks form to be submitted via Unpoly. | +| `up-target` | Fragment selector to update on success. | +| `up-fail-target` | Selector to update if submission fails. | +| `up-validate` | Enables live field validation. | +| `up-autosubmit` | Submits automatically on change. | +| `up-disable-for` | Disables fields during request. | +| `up-enable-for` | Enables fields after request completes. | + +### JavaScript API +- `up.form.submit(form, options)` – Submit programmatically. +- `up.validate(field, options)` – Trigger server validation. +- `up.form.fields(form)` – Returns all input fields. + +### Agent Reasoning +- Always ensure form has both `action` and `method` attributes. +- Match `up-target` to an element existing in the rendered HTML. +- For validation, ensure server supports `X-Up-Validate` header. +- When generating forms, add `up-fail-target` to handle errors gracefully. + +### Example +```html +
+ + +
+``` + +--- + +## 3. The up.layer Module + +### Purpose +Manages overlays, modals, and stacked layers of navigation. + +### Attributes + +| Attribute | Description | +| ---------------- | -------------------------------------------------- | +| `up-layer="new"` | Opens content in a new overlay. | +| `up-size` | Controls modal size (e.g., `small`, `large`). | +| `up-dismissable` | Allows overlay to close by clicking outside. | +| `up-history` | Determines if the overlay updates browser history. | +| `up-title` | Sets overlay title. | + +### JavaScript API +- `up.layer.open(options)` – Opens a new layer. +- `up.layer.close(layer)` – Closes a given layer. +- `up.layer.on(event, callback)` – Hooks into lifecycle events. + +### Agent Notes +- Ensure `up-layer="new"` only used with valid targets. +- For overlays, set `up-history="false"` unless explicitly required. +- Auto-generate dismiss buttons with `up-layer-close`. + +### Example +```html +Open Settings +``` + +--- + +## 4. The up.fragment Module + +### Purpose +Handles low-level fragment rendering, preserving, replacing, and merging. + +### JavaScript API +- `up.render(options)` – Replace fragment(s) with new content. +- `up.fragment.config` – Configure defaults for rendering. +- `up.fragment.get(target)` – Retrieve a fragment. + +### Example +```js +up.render({ target: '#main', url: '/dashboard', transition: 'fade' }) +``` + +### Agent Notes +- Ensure only fragment HTML is sent from server (not full document). +- Use `preserve` for elements like forms where input state matters. + +--- + +## 5. The up.network Module + +### Purpose +Handles network requests, caching, and aborting background loads. + +### JavaScript API +- `up.network.loadPage(url, options)` – Load a page via Unpoly. +- `up.network.abort()` – Abort ongoing requests. +- `up.network.config.timeout` – Default timeout setting. + +### Agent Tasks +- Preload probable links (`up.link.preload`). +- Use caching for frequent calls. +- Handle `up:network:late` event to show spinners. + +--- + +## 6. The up.event Module + +### Purpose +Manages custom events fired throughout Unpoly’s lifecycle. + +### Common Events +- `up:link:follow` +- `up:form:submit` +- `up:layer:open` +- `up:layer:close` +- `up:rendered` +- `up:network:late` + +### Example +```js +up.on('up:layer:close', (event) => { + console.log('Overlay closed'); +}); +``` + +### Agent Actions +- Register listeners for key events. +- Prevent duplicate bindings. +- Offer analytics hooks for `up:rendered` or `up:location:changed`. + +--- + +## 7. The up.motion Module + +Handles animations and transitions. + +### API +- `up.motion()` – Animate elements. +- `up.animate(element, keyframes, options)` – Custom animation. + +### Agent Notes +- Suggest `up-transition="fade"` or similar for fragment changes. +- Avoid heavy animations for performance-sensitive devices. + +--- + +## 8. The up.radio Module + +Handles broadcasting and receiving cross-fragment events. + +### Example +```js +up.radio.emit('user:updated', { id: 5 }) +up.radio.on('user:updated', (data) => console.log(data)) +``` + +### Agent Tasks +- Use for coordinating multiple fragments. +- Ensure channel names are namespaced (e.g., `form:valid`, `modal:open`). + +--- + +## 9. The up.history Module + +### Purpose +Manages URL history, titles, and restoration. + +### API +- `up.history.push(url, options)` – Push new history entry. +- `up.history.restore()` – Restore previous state. + +### Agent Guidance +- Disable history (`up-history="false"`) for temporary overlays. +- Ensure proper title update via `up-title`. + +--- + +## 10. The up.viewport Module + +### Purpose +Manages scrolling, focusing, and viewport restoration. + +### API +- `up.viewport.scroll(element)` – Scroll to element. +- `up.viewport.restoreScroll()` – Restore previous position. + +### Agent Tasks +- Restore scroll after fragment updates. +- Manage focus for accessibility after `up.render()`. + +--- + +## 11. The up.protocol Module + +Handles request headers and special HTTP status codes. + +### Key Concepts +- Adds `X-Up-Target` and `X-Up-Validate` headers. +- Interprets redirect and validation responses. + +### Agent Notes +- Ensure backend supports Unpoly headers. +- Warn if 204 or redirect status used without fragments. + +--- + +## 12. The up.util Module + +Contains helpers for arrays, strings, and timing. + +### Examples +```js +up.util.escapeHTML(" + + + + + + + + +``` + +### AI Agent Notes + +* Always include **`unpoly.min.css`** before any custom styles to ensure default animations and transitions function properly. +* **Never** load Unpoly twice; check if the page already has a ` +``` +--- + +## Agent Validation Checklist + +1. Verify `up-*` attributes match existing fragments. +2. Check backend returns valid fragment markup. +3. Ensure forms use `up-submit` and `up-fail-target`. +4. Overlay layers must have dismissable controls. +5. Use caching wisely (`up-cache`, `up.link.preload`). +6. Handle network and render events gracefully. +7. Log events (`up.log`) for debugging. +8. Confirm scroll/focus restoration after renders. +9. Gracefully degrade if JavaScript disabled. +10. Document reasoning and configuration. + + + + diff --git a/aiprompts/unpolly/unpolly_core.md b/aiprompts/unpolly/unpolly_core.md new file mode 100644 index 00000000..f97c51d2 --- /dev/null +++ b/aiprompts/unpolly/unpolly_core.md @@ -0,0 +1,647 @@ +# Unpoly Quick Reference for AI Agents + +## Installation + +Include Unpoly from CDN in your HTML ``: + +```html + + +``` + +## Core Concept + +Unpoly updates page fragments without full page reloads. Users click links/submit forms → server responds with HTML → Unpoly extracts and swaps matching fragments. + +--- + +## 1. Following Links (Fragment Updates) + +### Basic Link Following + +```html +View User +``` + +Updates the `
` element (or `` if no main exists) with content from `/users/5`. + +### Target Specific Fragment + +```html +View User + +
+ +
+``` + +### Multiple Fragments + +```html +View User +``` + +Updates both `.profile` and `.activity` from single response. + +### Append/Prepend Content + +```html + +Load More + + +Show Latest +``` + +### Handle All Links Automatically + +```js +up.link.config.followSelectors.push('a[href]') +``` + +Now all links update fragments by default. + +--- + +## 2. Submitting Forms + +### Basic Form Submission + +```html +
+ + +
+``` + +Submits via AJAX and updates `
` with response. + +### Target Specific Fragment + +```html +
+ + +
+ +
+ +
+``` + +### Handle Success vs. Error Responses + +```html +
+ + +
+ +
Success message here
+``` + +- **Success (2xx status)**: Updates `#success` +- **Error (4xx/5xx status)**: Re-renders `form` with validation errors + +**Server must return HTTP 422** (or similar error code) for validation failures. + +--- + +## 3. Opening Overlays (Modal, Drawer, Popup) + +### Modal Dialog + +```html +Open Modal +``` + +Opens `/details` in a modal overlay. + +### Drawer (Sidebar) + +```html +Open Drawer +``` + +### Popup (Anchored to Link) + +```html +Help +``` + +### Close Overlay When Condition Met + +```html + + New User + +``` + +Overlay auto-closes when URL matches `/users/123`, passes `{ id: 123 }` to callback. + +### Local Content (No Server Request) + +```html +Help +``` + +--- + +## 4. Validation + +### Validate on Field Change + +```html +
+ + + +
+``` + +When field loses focus → submits form with `X-Up-Validate: email` header → server re-renders form → Unpoly updates the field's parent `
` (or closest form group). + +**Server must return HTTP 422** for validation errors. + +### Validate While Typing + +```html + +``` + +Validates 300ms after user stops typing. + +--- + +## 5. Lazy Loading & Polling + +### Load When Element Appears in DOM + +```html + +``` + +Immediately loads `/menu` when placeholder renders. + +### Load When Scrolled Into View + +```html +
+ Loading comments... +
+``` + +Loads when element scrolls into viewport. + +### Auto-Refresh (Polling) + +```html +
+ Current status +
+``` + +Reloads fragment every 5 seconds from original URL. + +--- + +## 6. Caching & Revalidation + +### Enable Caching + +```html +Users +``` + +Caches response, instantly shows cached content, then revalidates with server. + +### Disable Caching + +```html +Live Prices +``` + +### Conditional Requests (Server-Side) + +Server sends: + +```http +HTTP/1.1 200 OK +ETag: "abc123" + +
Content
+``` + +Next reload, Unpoly sends: + +```http +GET /path +If-None-Match: "abc123" +``` + +Server responds `304 Not Modified` if unchanged → saves bandwidth. + +--- + +## 7. Navigation Bar (Current Link Highlighting) + +```html + +``` + +Current page link gets `.up-current` class automatically. + +**Style it:** + +```css +.up-current { + font-weight: bold; + color: blue; +} +``` + +--- + +## 8. Loading State + +### Feedback Classes + +Automatically applied: + +- `.up-active` on clicked link/button +- `.up-loading` on targeted fragment + +**Style them:** + +```css +.up-active { opacity: 0.6; } +.up-loading { opacity: 0.8; } +``` + +### Disable Form While Submitting + +```html +
+ + +
+``` + +All fields disabled during submission. + +### Show Placeholder While Loading + +```html + + Load Data + +``` + +--- + +## 9. Preloading + +### Preload on Hover + +```html +User Profile +``` + +Starts loading when user hovers (90ms delay by default). + +### Preload Immediately + +```html +Menu +``` + +Loads as soon as link appears in DOM. + +--- + +## 10. Templates (Client-Side HTML) + +### Define Template + +```html + +``` + +### Use Template + +```html + + Show User + +``` + +**Process variables with compiler:** + +```js +up.compiler('.card', function(element, data) { + element.innerHTML = element.innerHTML + .replace(/{{name}}/g, data.name) + .replace(/{{email}}/g, data.email) +}) +``` + +--- + +## 11. JavaScript API + +### Render Fragment + +```js +up.render({ + url: '/users/5', + target: '.user-details' +}) +``` + +### Navigate (Updates History) + +```js +up.navigate({ + url: '/users', + target: 'main' +}) +``` + +### Submit Form + +```js +let form = document.querySelector('form') +up.submit(form) +``` + +### Open Overlay + +```js +up.layer.open({ + url: '/users/new', + onAccepted: (event) => { + console.log('User created:', event.value) + } +}) +``` + +### Close Overlay with Value + +```js +up.layer.accept({ id: 123, name: 'Alice' }) +``` + +### Reload Fragment + +```js +up.reload('.status') +``` + +--- + +## 12. Request Headers (Server Protocol) + +Unpoly sends these headers with requests: + +| Header | Value | Purpose | +| --------------- | -------- | ------------------------------- | +| `X-Up-Version` | `1.0.0` | Identifies Unpoly request | +| `X-Up-Target` | `.users` | Fragment selector being updated | +| `X-Up-Mode` | `modal` | Current layer mode | +| `X-Up-Validate` | `email` | Field being validated | + +**Server can respond with:** + +| Header | Effect | +| ------------------------ | ------------------------ | +| `X-Up-Target: .other` | Changes target selector | +| `X-Up-Accept-Layer: {}` | Closes overlay (success) | +| `X-Up-Dismiss-Layer: {}` | Closes overlay (cancel) | + +--- + +## 13. Common Patterns + +### Infinite Scrolling + +```html +
+
Item 1
+
Item 2
+
+ + +``` + +### Dependent Form Fields + +```html +
+ + + + +
+``` + +### Confirm Before Action + +```html + + Delete + +``` + +### Auto-Submit on Change + +```html +
+ +
+``` + +Submits form when any field changes. + +--- + +## 14. Error Handling + +### Handle Network Errors + +```js +up.on('up:fragment:offline', function(event) { + if (confirm('You are offline. Retry?')) { + event.retry() + } +}) +``` + +### Handle Failed Responses + +```js +try { + await up.render({ url: '/path', target: '.data' }) +} catch (error) { + if (error instanceof up.RenderResult) { + console.log('Server error:', error) + } +} +``` + +--- + +## 15. Compilers (Enhance Elements) + +### Basic Compiler + +```js +up.compiler('.current-time', function(element) { + element.textContent = new Date().toString() +}) +``` + +Runs when `.current-time` is inserted (initial load OR fragment update). + +### Compiler with Cleanup + +```js +up.compiler('.auto-refresh', function(element) { + let timer = setInterval(() => { + element.textContent = new Date().toString() + }, 1000) + + // Return destructor function + return () => clearInterval(timer) +}) +``` + +Destructor called when element is removed from DOM. + +--- + +## Quick Reference Table + +| Task | HTML | JavaScript | +| --------------- | ---------------------------- | -------------------------- | +| Follow link | `` | `up.follow(link)` | +| Submit form | `
` | `up.submit(form)` | +| Target fragment | `up-target=".foo"` | `{ target: '.foo' }` | +| Open modal | `up-layer="new"` | `up.layer.open({ url })` | +| Validate field | `up-validate` | `up.validate(field)` | +| Lazy load | `up-defer` | — | +| Poll fragment | `up-poll` | — | +| Preload link | `up-preload` | `up.link.preload(link)` | +| Local content | `up-content="

Hi

"` | `{ content: '

Hi

' }` | +| Append content | `up-target=".list:after"` | — | +| Confirm action | `up-confirm="Sure?"` | `{ confirm: 'Sure?' }` | + +--- + +## Key Defaults + +- **Target**: Updates `
` (or ``) if no `up-target` specified +- **Caching**: Auto-enabled for GET requests during navigation +- **History**: Auto-updated when rendering `
` or major fragments +- **Scrolling**: Auto-scrolls to top when updating `
` +- **Focus**: Auto-focuses new fragment +- **Validation**: Targets field's parent `
` or form group + +--- + +## Best Practices for AI Agents + +1. **Always provide HTTP error codes**: Return 422 for validation errors, 404 for not found, etc. +2. **Send full HTML responses**: Include entire page structure; Unpoly extracts needed fragments +3. **Use semantic HTML**: `
`, `