Refactor to use plugin system for language support Remove hardcoded language features from core Move language handling to plugin system Improve content file discovery Simplify context creation Add plugin system documentation Implement hook system for extensibility Add template variable hook Add context storage for plugins Improve error handling Refactor rendering logic Improve list view sorting Add support for custom list templates Improve metadata handling Add plugin system reference documentation
164 lines
5.2 KiB
PHP
164 lines
5.2 KiB
PHP
<?php
|
|
|
|
function renderContentFile(string $filePath): string {
|
|
$ext = pathinfo($filePath, PATHINFO_EXTENSION);
|
|
|
|
ob_start();
|
|
if ($ext === 'md') {
|
|
require_once __DIR__ . '/cache.php';
|
|
$cached = getCachedMarkdown($filePath);
|
|
|
|
if ($cached !== null) {
|
|
echo $cached;
|
|
} else {
|
|
if (!class_exists('Parsedown')) {
|
|
require_once __DIR__ . '/vendor/Parsedown.php';
|
|
}
|
|
$html = '<article>' . (new Parsedown())->text(file_get_contents($filePath)) . '</article>';
|
|
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 {
|
|
global $GLOBALS;
|
|
|
|
// Get basic template vars
|
|
$navigation = $ctx->navigation;
|
|
$homeLabel = $ctx->homeLabel;
|
|
$pageTitle = null;
|
|
|
|
// Let plugins add template variables
|
|
$templateVars = Hooks::apply(Hook::TEMPLATE_VARS, [
|
|
'content' => $content,
|
|
'navigation' => $navigation,
|
|
'homeLabel' => $homeLabel,
|
|
'pageTitle' => $pageTitle
|
|
], $ctx);
|
|
|
|
extract($templateVars);
|
|
|
|
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, "<article><h1>403 Forbidden</h1><p>Access denied.</p></article>", 403);
|
|
}
|
|
|
|
$ext = pathinfo($realPath, PATHINFO_EXTENSION);
|
|
|
|
if (in_array($ext, CONTENT_EXTENSIONS)) {
|
|
$content = renderContentFile($realPath);
|
|
|
|
$pageDir = dirname($realPath);
|
|
$pageMetadata = loadMetadata($pageDir);
|
|
|
|
// Load page-level plugins
|
|
getPluginManager()->loadPagePlugins($pageMetadata);
|
|
|
|
$navigation = $ctx->navigation;
|
|
$homeLabel = $ctx->homeLabel;
|
|
$pageTitle = $pageMetadata['title'] ?? null;
|
|
$metaDescription = extractMetaDescription($pageDir, $pageMetadata);
|
|
|
|
// Check for page-specific CSS
|
|
$pageCss = findPageCss($pageDir, $ctx->contentDir);
|
|
$pageCssUrl = $pageCss['url'] ?? null;
|
|
$pageCssHash = $pageCss['hash'] ?? null;
|
|
|
|
// Check for cover image for social media
|
|
$coverImage = findCoverImage($pageDir);
|
|
$socialImageUrl = null;
|
|
if ($coverImage) {
|
|
$relativePath = str_replace($ctx->contentDir, '', $pageDir);
|
|
$relativePath = trim($relativePath, '/');
|
|
$socialImageUrl = '/' . ($relativePath ? $relativePath . '/' : '') . $coverImage;
|
|
}
|
|
|
|
// Let plugins add template variables
|
|
$templateVars = Hooks::apply(Hook::TEMPLATE_VARS, [
|
|
'content' => $content,
|
|
'navigation' => $navigation,
|
|
'homeLabel' => $homeLabel,
|
|
'pageTitle' => $pageTitle,
|
|
'metaDescription' => $metaDescription,
|
|
'pageCssUrl' => $pageCssUrl,
|
|
'pageCssHash' => $pageCssHash,
|
|
'socialImageUrl' => $socialImageUrl
|
|
], $ctx);
|
|
|
|
extract($templateVars);
|
|
|
|
// Wrap content with page template
|
|
ob_start();
|
|
require $ctx->templates->page;
|
|
$wrappedContent = ob_get_clean();
|
|
|
|
include $ctx->templates->base;
|
|
exit;
|
|
}
|
|
|
|
// Unknown type - 404
|
|
renderTemplate($ctx, "<article><h1>404 - Not Found</h1><p>The requested file could not be found.</p></article>", 404);
|
|
}
|
|
|
|
function renderMultipleFiles(Context $ctx, array $files, string $pageDir): void {
|
|
$content = '';
|
|
foreach ($files as $file) {
|
|
$content .= renderContentFile($file);
|
|
}
|
|
|
|
$pageMetadata = loadMetadata($pageDir);
|
|
|
|
// Load page-level plugins
|
|
getPluginManager()->loadPagePlugins($pageMetadata);
|
|
|
|
$navigation = $ctx->navigation;
|
|
$homeLabel = $ctx->homeLabel;
|
|
$pageTitle = $pageMetadata['title'] ?? null;
|
|
$metaDescription = extractMetaDescription($pageDir, $pageMetadata);
|
|
|
|
// Check for page-specific CSS
|
|
$pageCss = findPageCss($pageDir, $ctx->contentDir);
|
|
$pageCssUrl = $pageCss['url'] ?? null;
|
|
$pageCssHash = $pageCss['hash'] ?? null;
|
|
|
|
// Check for cover image
|
|
$coverImage = findCoverImage($pageDir);
|
|
$socialImageUrl = null;
|
|
if ($coverImage) {
|
|
$relativePath = str_replace($ctx->contentDir, '', $pageDir);
|
|
$relativePath = trim($relativePath, '/');
|
|
$socialImageUrl = '/' . ($relativePath ? $relativePath . '/' : '') . $coverImage;
|
|
}
|
|
|
|
// Let plugins add template variables
|
|
$templateVars = Hooks::apply(Hook::TEMPLATE_VARS, [
|
|
'content' => $content,
|
|
'navigation' => $navigation,
|
|
'homeLabel' => $homeLabel,
|
|
'pageTitle' => $pageTitle,
|
|
'metaDescription' => $metaDescription,
|
|
'pageCssUrl' => $pageCssUrl,
|
|
'pageCssHash' => $pageCssHash,
|
|
'socialImageUrl' => $socialImageUrl
|
|
], $ctx);
|
|
|
|
extract($templateVars);
|
|
|
|
// Wrap content with page template
|
|
ob_start();
|
|
require $ctx->templates->page;
|
|
$wrappedContent = ob_get_clean();
|
|
|
|
include $ctx->templates->base;
|
|
exit;
|
|
}
|