' . (new Parsedown())->text(file_get_contents($filePath)) . '';
setCachedMarkdown($filePath, $html);
echo $html;
}
} elseif (in_array($ext, ['html', 'php'])) {
include $filePath;
}
return ob_get_clean();
}
function renderTemplate(Context $ctx, string $content, int $statusCode = 200): void {
// Extract all necessary variables for base template
$currentLang = $ctx->currentLang;
$navigation = $ctx->navigation;
$homeLabel = $ctx->homeLabel;
$translations = $ctx->translations;
$pageTitle = null; // No specific page title for error pages
http_response_code($statusCode);
include $ctx->templates->base;
exit;
}
function renderFile(Context $ctx, string $filePath): void {
$realPath = realpath($filePath);
if (!$realPath || !str_starts_with($realPath, $ctx->contentDir) || !is_readable($realPath)) {
renderTemplate($ctx, "403 Forbidden
Access denied.
", 403);
}
$ext = pathinfo($realPath, PATHINFO_EXTENSION);
if (in_array($ext, CONTENT_EXTENSIONS)) {
$content = renderContentFile($realPath);
// Prepare template variables using property hooks
$currentLang = $ctx->currentLang;
$navigation = $ctx->navigation;
$homeLabel = $ctx->homeLabel;
$translations = $ctx->translations;
$pageDir = dirname($realPath);
$pageMetadata = loadMetadata($pageDir, $ctx->currentLang, $ctx->defaultLang);
$pageTitle = $pageMetadata['title'] ?? null;
$metaDescription = extractMetaDescription($pageDir, $pageMetadata, $ctx->currentLang, $ctx->defaultLang);
// Check for page-specific CSS
$pageCss = findPageCss($pageDir, $ctx->contentDir);
$pageCssUrl = $pageCss['url'] ?? null;
$pageCssHash = $pageCss['hash'] ?? null;
// Wrap content with page template
ob_start();
include $ctx->templates->page;
$content = ob_get_clean();
// Wrap with base template
include $ctx->templates->base;
exit;
}
// Serve other file types directly
header('Content-Type: ' . (mime_content_type($realPath) ?: 'application/octet-stream'));
readfile($realPath);
exit;
}
function renderMultipleFiles(Context $ctx, array $filePaths, string $pageDir): void {
// Validate all files are safe
foreach ($filePaths as $filePath) {
$realPath = realpath($filePath);
if (!$realPath || !str_starts_with($realPath, $ctx->contentDir) || !is_readable($realPath)) {
renderTemplate($ctx, "403 Forbidden
Access denied.
", 403);
}
}
// Render all content files in order
$content = implode('', array_map('renderContentFile', $filePaths));
// Prepare template variables using property hooks
$currentLang = $ctx->currentLang;
$navigation = $ctx->navigation;
$homeLabel = $ctx->homeLabel;
$translations = $ctx->translations;
$pageMetadata = loadMetadata($pageDir, $ctx->currentLang, $ctx->defaultLang);
$pageTitle = $pageMetadata['title'] ?? null;
$metaDescription = extractMetaDescription($pageDir, $pageMetadata, $ctx->currentLang, $ctx->defaultLang);
// Check for page-specific CSS
$pageCss = findPageCss($pageDir, $ctx->contentDir);
$pageCssUrl = $pageCss['url'] ?? null;
$pageCssHash = $pageCss['hash'] ?? null;
// Wrap content with page template
ob_start();
include $ctx->templates->page;
$content = ob_get_clean();
// Wrap with base template
include $ctx->templates->base;
exit;
}