Update AGENT.md to reflect current project structure and philosophy Add comprehensive architecture documentation covering: - Directory layout - Stable contracts - Request flow - Module dependencies - Page vs list detection - Deployment models - Demo fallback Remove outdated plugin system documentation Add new content system documentation Add configuration documentation Add context API documentation Add hooks and plugins documentation Add templates documentation Add rendering documentation Add development environment documentation
104 lines
4.5 KiB
Markdown
104 lines
4.5 KiB
Markdown
# Rendering & Caching
|
|
|
|
## Content Rendering
|
|
|
|
**`renderContentFile(string $filePath, ?Context $ctx = null): string`**
|
|
|
|
Renders a single content file to HTML string based on extension:
|
|
|
|
| Extension | Rendering |
|
|
|---|---|
|
|
| `md` | Parsedown + ParsedownExtra → HTML. Cached. Language prefix injected into internal links. |
|
|
| `html` | Included directly (output buffered) |
|
|
| `php` | Included with `Hook::TEMPLATE_VARS` variables extracted into scope |
|
|
|
|
PHP content files receive variables from `Hook::TEMPLATE_VARS` (starting with an empty array). This includes plugin-provided variables like `$translations`, `$currentLang`, etc. However, page-level context like `$metadata` and `$pageTitle` is **not** included — those are only available in the wrapping template (page.php/list.php), not in content files.
|
|
|
|
## Page Rendering
|
|
|
|
**`renderMultipleFiles(Context $ctx, array $files, string $pageDir): void`**
|
|
|
|
Used for both frontpage and page views:
|
|
|
|
1. Load metadata for `$pageDir`
|
|
2. Load page plugins (from metadata `plugins` field)
|
|
3. Render all content files, concatenate HTML
|
|
4. Compute: `$pageTitle`, `$metaDescription`, `$pageCssUrl`/`$pageCssHash`, `$socialImageUrl`
|
|
5. Fire `Hook::TEMPLATE_VARS` with all variables
|
|
6. `extract()` variables → render `page.php` → capture output as `$content`
|
|
7. Render `base.php` with `$content` + base variables
|
|
8. `exit`
|
|
|
|
## List Rendering
|
|
|
|
Handled directly in `router.php` (not a separate function):
|
|
|
|
1. Render directory's own content files as `$pageContent`
|
|
2. Load metadata, check `hide_list`
|
|
3. Select list template from `page_template` metadata
|
|
4. Build `$items` array from subdirectories (metadata + extraction)
|
|
5. Sort items by date
|
|
6. Fire `Hook::TEMPLATE_VARS`
|
|
7. Render list template → capture as `$content`
|
|
8. Pass to `renderTemplate()` which renders `base.php`
|
|
|
|
**`renderTemplate(Context $ctx, string $content, int $statusCode = 200): void`** — Wraps content in base template. Used for list views and error pages.
|
|
|
|
## Markdown Caching
|
|
|
|
Defined in `app/cache.php`. File-based cache in `/tmp/folderweb_cache/`.
|
|
|
|
**Cache key:** `md5($filePath . $mtime . $langPrefix)`
|
|
|
|
- Invalidates when file is modified (mtime changes)
|
|
- Invalidates per-language (different link rewriting)
|
|
- No explicit TTL — entries persist until temp directory cleanup
|
|
- **Does not track plugin state** — if a plugin modifies Markdown output (e.g., via PROCESS_CONTENT on files), changing plugin config won't bust the cache. Clear `/tmp/folderweb_cache/` manually after plugin changes that affect rendered Markdown.
|
|
|
|
```php
|
|
getCachedMarkdown(string $filePath, string $langPrefix = ''): ?string
|
|
setCachedMarkdown(string $filePath, string $html, string $langPrefix = ''): void
|
|
```
|
|
|
|
## Static File Serving
|
|
|
|
### Content Assets (router.php)
|
|
|
|
Before content routing, the router serves static files from content directory with an explicit MIME type allowlist:
|
|
|
|
`css`, `jpg`, `jpeg`, `png`, `gif`, `webp`, `svg`, `pdf`, `woff`, `woff2`, `ttf`, `otf`
|
|
|
|
Files not in this list are not served as static assets. Notably, `.js` files are excluded — JavaScript must be placed in `custom/assets/` to be served (at the document root URL), or linked from an external source.
|
|
|
|
### Custom Assets (router.php)
|
|
|
|
Files in `custom/assets/` are served at the document root URL. Example: `custom/assets/favicon.ico` → `/favicon.ico`. Uses `mime_content_type()` for MIME detection.
|
|
|
|
### Framework Assets (static.php)
|
|
|
|
`/app/*` requests are handled by `static.php` with directory traversal protection (`../` stripped):
|
|
|
|
| URL Path | Filesystem Path |
|
|
|---|---|
|
|
| `/app/styles/*` | `custom/styles/*` |
|
|
| `/app/fonts/*` | `custom/fonts/*` |
|
|
| `/app/assets/*` | `custom/assets/*` |
|
|
| `/app/default-styles/*` | `app/default/styles/*` |
|
|
|
|
MIME types resolved from extension map, falling back to `mime_content_type()`.
|
|
|
|
## CSS Cache Busting
|
|
|
|
Page-specific CSS gets an MD5 hash appended: `?v={hash}`. Computed by `findPageCss()`. The default theme's CSS is linked directly without hash (uses browser caching).
|
|
|
|
## Parsedown
|
|
|
|
Markdown rendering uses `Parsedown` + `ParsedownExtra` from `app/vendor/`. These are the only third-party dependencies. Loaded lazily on first Markdown render.
|
|
|
|
**Internal link rewriting:** After Markdown→HTML conversion, `href="/..."` links are prefixed with the current language prefix (e.g., `/no`). This ensures Markdown links work correctly in multilingual sites.
|
|
|
|
## Error Responses
|
|
|
|
- **403:** Invalid path (outside content directory or unreadable)
|
|
- **404:** Slug resolution failed or unknown route type
|
|
- Both render via `renderTemplate()` with appropriate status code
|