Add JavaScript support to page templates

Add support for page-specific JavaScript files with cache busting
via MD5 hash. The script is loaded at the end of the body with
defer attribute. The JavaScript file must be named script.js and
located in the same directory as the page content.
This commit is contained in:
Ruben 2026-02-06 18:47:17 +01:00
parent 069ce389ea
commit f8a352afce
4 changed files with 37 additions and 1 deletions

View file

@ -54,5 +54,8 @@
<?php endif; ?>
</p>
</footer>
<?php if (!empty($pageJsUrl)): ?>
<script defer src="<?= htmlspecialchars($pageJsUrl) ?>?v=<?= htmlspecialchars($pageJsHash ?? '') ?>"></script>
<?php endif; ?>
</body>
</html>

View file

@ -132,6 +132,22 @@ function findPageCss(string $dirPath, string $contentDir): ?array {
];
}
function findPageJs(string $dirPath, string $contentDir): ?array {
$jsFile = "$dirPath/script.js";
if (!file_exists($jsFile) || !is_file($jsFile)) {
return null;
}
$relativePath = str_replace($contentDir, '', $dirPath);
$relativePath = trim($relativePath, '/');
$jsUrl = '/' . ($relativePath ? $relativePath . '/' : '') . 'script.js';
return [
'url' => $jsUrl,
'hash' => hash_file('md5', $jsFile)
];
}
function extractMetaDescription(string $dirPath, ?array $metadata): ?string {
// 1. Check for search_description in metadata
if ($metadata && isset($metadata['search_description'])) {

View file

@ -57,6 +57,8 @@ function renderTemplate(Context $ctx, string $content, int $statusCode = 200): v
'metaDescription' => $ctx->get('metaDescription'),
'pageCssUrl' => $ctx->get('pageCssUrl'),
'pageCssHash' => $ctx->get('pageCssHash'),
'pageJsUrl' => $ctx->get('pageJsUrl'),
'pageJsHash' => $ctx->get('pageJsHash'),
'feedUrl' => $ctx->get('feedUrl')
], $ctx);
@ -88,6 +90,10 @@ function renderMultipleFiles(Context $ctx, array $files, string $pageDir): void
$pageCssUrl = $pageCss['url'] ?? null;
$pageCssHash = $pageCss['hash'] ?? null;
$pageJs = findPageJs($pageDir, $ctx->contentDir);
$pageJsUrl = $pageJs['url'] ?? null;
$pageJsHash = $pageJs['hash'] ?? null;
$coverImage = findCoverImage($pageDir);
$socialImageUrl = null;
if ($coverImage) {
@ -104,6 +110,8 @@ function renderMultipleFiles(Context $ctx, array $files, string $pageDir): void
'metaDescription' => $metaDescription,
'pageCssUrl' => $pageCssUrl,
'pageCssHash' => $pageCssHash,
'pageJsUrl' => $pageJsUrl,
'pageJsHash' => $pageJsHash,
'socialImageUrl' => $socialImageUrl
], $ctx);

View file

@ -42,6 +42,7 @@ if (file_exists($contentAssetPath) && is_file($contentAssetPath)) {
'woff2' => 'font/woff2',
'ttf' => 'font/ttf',
'otf' => 'font/otf',
'js' => 'application/javascript',
];
$extLower = strtolower($ext);
@ -205,11 +206,15 @@ switch ($parsedPath['type']) {
$pageTitle = $metadata['title'] ?? null;
$metaDescription = extractMetaDescription($dir, $metadata);
// Check for page-specific CSS
// Check for page-specific CSS and JS
$pageCss = findPageCss($dir, $ctx->contentDir);
$pageCssUrl = $pageCss['url'] ?? null;
$pageCssHash = $pageCss['hash'] ?? null;
$pageJs = findPageJs($dir, $ctx->contentDir);
$pageJsUrl = $pageJs['url'] ?? null;
$pageJsHash = $pageJs['hash'] ?? null;
// Build feed URL if feed is enabled
$langPrefix = $ctx->get('langPrefix', '');
$feedUrl = (isset($metadata['feed']) && $metadata['feed'])
@ -221,6 +226,8 @@ switch ($parsedPath['type']) {
$ctx->set('metaDescription', $metaDescription);
$ctx->set('pageCssUrl', $pageCssUrl);
$ctx->set('pageCssHash', $pageCssHash);
$ctx->set('pageJsUrl', $pageJsUrl);
$ctx->set('pageJsHash', $pageJsHash);
$ctx->set('feedUrl', $feedUrl);
// Let plugins add template variables
@ -231,6 +238,8 @@ switch ($parsedPath['type']) {
'metaDescription' => $metaDescription,
'pageCssUrl' => $pageCssUrl,
'pageCssHash' => $pageCssHash,
'pageJsUrl' => $pageJsUrl,
'pageJsHash' => $pageJsHash,
'items' => $items,
'pageContent' => $pageContent,
'feedUrl' => $feedUrl