diff --git a/app/plugins/global/languages.php b/app/plugins/global/languages.php index 22a2000..4425454 100644 --- a/app/plugins/global/languages.php +++ b/app/plugins/global/languages.php @@ -46,7 +46,10 @@ Hooks::add(Hook::PROCESS_CONTENT, function(mixed $data, string $dirOrType, strin // Filter content files by language variant if (is_array($data) && !empty($data) && isset($data[0]['path'])) { - return filterFilesByLanguage($data, $dirOrType, $ctx); + error_log("filterFilesByLanguage called with " . count($data) . " files, current lang: $currentLang"); + $filtered = filterFilesByLanguage($data, $dirOrType, $ctx); + error_log("Filtered to " . count($filtered) . " files"); + return $filtered; } return $data; diff --git a/app/rendering.php b/app/rendering.php index 08dc19e..c4a099a 100644 --- a/app/rendering.php +++ b/app/rendering.php @@ -59,8 +59,7 @@ function renderTemplate(Context $ctx, string $content, int $statusCode = 200): v 'pageCssHash' => $ctx->get('pageCssHash'), 'pageJsUrl' => $ctx->get('pageJsUrl'), 'pageJsHash' => $ctx->get('pageJsHash'), - 'feedUrl' => $ctx->get('feedUrl'), - 'socialImageUrl' => $ctx->get('socialImageUrl') + 'feedUrl' => $ctx->get('feedUrl') ], $ctx); extract($templateVars); @@ -74,8 +73,8 @@ function renderTemplate(Context $ctx, string $content, int $statusCode = 200): v function renderMultipleFiles(Context $ctx, array $files, string $pageDir): void { // Load metadata and page plugins BEFORE rendering content files // so that plugin-provided template variables are available to PHP content files - $metadata = loadMetadata($pageDir); - getPluginManager()->loadPagePlugins($metadata); + $pageMetadata = loadMetadata($pageDir); + getPluginManager()->loadPagePlugins($pageMetadata); $content = ''; foreach ($files as $file) { @@ -84,8 +83,8 @@ function renderMultipleFiles(Context $ctx, array $files, string $pageDir): void $navigation = $ctx->navigation; $homeLabel = $ctx->homeLabel; - $pageTitle = $metadata['title'] ?? null; - $metaDescription = extractMetaDescription($pageDir, $metadata); + $pageTitle = $pageMetadata['title'] ?? null; + $metaDescription = extractMetaDescription($pageDir, $pageMetadata); $pageCss = findPageCss($pageDir, $ctx->contentDir); $pageCssUrl = $pageCss['url'] ?? null; @@ -113,8 +112,7 @@ function renderMultipleFiles(Context $ctx, array $files, string $pageDir): void 'pageCssHash' => $pageCssHash, 'pageJsUrl' => $pageJsUrl, 'pageJsHash' => $pageJsHash, - 'socialImageUrl' => $socialImageUrl, - 'metadata' => $metadata + 'socialImageUrl' => $socialImageUrl ], $ctx); extract($templateVars); diff --git a/app/router.php b/app/router.php index 8ad8231..6f4d3a3 100644 --- a/app/router.php +++ b/app/router.php @@ -249,14 +249,6 @@ switch ($parsedPath['type']) { ? $langPrefix . '/' . trim($ctx->requestPath, '/') . '/feed.xml' : null; - // Build social image URL from cover image if present - $coverImage = findCoverImage($dir); - $socialImageUrl = null; - if ($coverImage) { - $relativePath = trim(str_replace($ctx->contentDir, '', $dir), '/'); - $socialImageUrl = '/' . ($relativePath ? $relativePath . '/' : '') . $coverImage; - } - // Store for base template (renderTemplate reads these from context) $ctx->set('pageTitle', $pageTitle); $ctx->set('metaDescription', $metaDescription); @@ -265,7 +257,6 @@ switch ($parsedPath['type']) { $ctx->set('pageJsUrl', $pageJsUrl); $ctx->set('pageJsHash', $pageJsHash); $ctx->set('feedUrl', $feedUrl); - $ctx->set('socialImageUrl', $socialImageUrl); // Let plugins add template variables $templateVars = Hooks::apply(Hook::TEMPLATE_VARS, [ @@ -279,9 +270,7 @@ switch ($parsedPath['type']) { 'pageJsHash' => $pageJsHash, 'items' => $items, 'pageContent' => $pageContent, - 'feedUrl' => $feedUrl, - 'socialImageUrl' => $socialImageUrl, - 'metadata' => $metadata + 'feedUrl' => $feedUrl ], $ctx); extract($templateVars); diff --git a/docs/04-development/02-content-system.md b/docs/04-development/02-content-system.md index 302976c..b821dbb 100644 --- a/docs/04-development/02-content-system.md +++ b/docs/04-development/02-content-system.md @@ -54,7 +54,6 @@ Returns flat key-value array with a special `_raw` key containing the full parse | `order` | string | `"descending"` | List sort direction (`ascending`\|`descending`) | | `redirect` | string | — | External URL (list items can redirect) | | `feed` | bool | `false` | Enable Atom feed on list pages (`feed.xml`) | -| `author` | string | title | Atom feed author name (falls back to page title) | | `plugins` | string | — | Comma-separated page-level plugin names | ### Settings Section diff --git a/docs/04-development/07-rendering.md b/docs/04-development/07-rendering.md index a761287..c2d1de1 100644 --- a/docs/04-development/07-rendering.md +++ b/docs/04-development/07-rendering.md @@ -57,8 +57,6 @@ Handled in `router.php` before `parseRequestPath()`. When a request path ends wi Feed piggybacks on the existing Markdown cache — no separate feed cache needed. The `rawDate` field on items provides ISO dates for Atom `` elements. Content is wrapped in `` with `]]>` safely escaped. -**Date deduplication:** Atom requires unique `` timestamps per entry. Items sharing the same date get seconds incremented (`T00:00:00Z`, `T00:00:01Z`, etc.) to ensure uniqueness while preserving sort order. - ## Markdown Caching Defined in `app/cache.php`. File-based cache in `/tmp/folderweb_cache/`. @@ -89,9 +87,7 @@ 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 an explicit MIME type map; falls back to `application/octet-stream`. - -Cache-Control headers: `json` and `geojson` files get `max-age=60` (short TTL for data files); all other asset types get `max-age=31536000` (1 year, immutable). +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)