Update documentation for new JS variables and rendering pipeline Add script.js file support to content directories Implement cache-busting for JavaScript files Update static file serving to include JavaScript files Document page-specific script loading in base.php
5.5 KiB
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:
- Load metadata for
$pageDir - Load page plugins (from metadata
pluginsfield) - Render all content files, concatenate HTML
- Compute:
$pageTitle,$metaDescription,$pageCssUrl/$pageCssHash,$pageJsUrl/$pageJsHash,$socialImageUrl - Fire
Hook::TEMPLATE_VARSwith all variables extract()variables → renderpage.php→ capture output as$content- Render
base.phpwith$content+ base variables exit
List Rendering
Handled directly in router.php (not a separate function):
- Render directory's own content files as
$pageContent - Load metadata, check
hide_list - Select list template from
page_templatemetadata - Call
buildListItems()fromhelpers.php(builds + sorts items) - Store
pageTitle,metaDescription,pageCssUrl,pageCssHash,pageJsUrl,pageJsHash,feedUrlon context - Fire
Hook::TEMPLATE_VARS - Render list template → capture as
$content - Pass to
renderTemplate()which rendersbase.php
renderTemplate(Context $ctx, string $content, int $statusCode = 200): void — Wraps content in base template. Used for list views and error pages. Reads pageTitle, metaDescription, pageCssUrl, pageCssHash, pageJsUrl, pageJsHash, and feedUrl from the context object (set by the list case in router.php). For error pages, these context keys are unset, so base.php receives nulls.
Atom Feed Rendering
Handled in router.php before parseRequestPath(). When a request path ends with feed.xml:
- Strip
feed.xmlsuffix, resolve parent as list directory viaparseRequestPath() - Check
feed = truein metadata — 404 if missing or if parent is not a list - Call
buildListItems()to get items - For each item: call
findAllContentFiles()+renderContentFile()to get full HTML content - Build Atom XML with absolute URLs (
$_SERVER['HTTP_HOST']+ scheme detection) - Output
Content-Type: application/atom+xmland exit
Feed piggybacks on the existing Markdown cache — no separate feed cache needed. The rawDate field on items provides ISO dates for Atom <updated> elements. Content is wrapped in <![CDATA[...]]> with ]]> safely escaped.
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.
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, js
Files not in this list are not served as static assets.
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 and JS Cache Busting
Page-specific CSS and JS get an MD5 hash appended: ?v={hash}. Computed by findPageCss() and findPageJs() respectively. 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