#!/usr/bin/env php $project) { $pages[] = [ 'key' => $project['route'], 'output' => $project['output'], 'title' => $project['title'] . ' | Sharkk', 'description' => $project['summary'], 'template' => 'project', 'order' => 100 + $index, 'project' => $project, 'slider' => [ 'class' => 'work-header', ], ]; } foreach ($site['blogPosts'] as $index => $post) { $pages[] = [ 'key' => $post['route'], 'output' => $post['output'], 'title' => $post['title'] . ' | Sharkk', 'description' => $post['description'], 'template' => 'blog-post', 'order' => 200 + $index, 'post' => $post, ]; } $routes = []; $outputs = []; foreach ($pages as $page) { foreach (['key', 'output', 'title', 'template'] as $field) { if (!isset($page[$field]) || $page[$field] === '') { throw new RuntimeException("Every page must define a non-empty {$field} field."); } } if (isset($routes[$page['key']])) { throw new RuntimeException("Duplicate route key: {$page['key']}"); } $output = normalize_site_path($page['output']); if (isset($outputs[$output])) { throw new RuntimeException("Duplicate output path: {$output}"); } $page['output'] = $output; $routes[$page['key']] = $page; $outputs[$output] = true; } usort($pages, static fn (array $a, array $b): int => ($a['order'] ?? 999) <=> ($b['order'] ?? 999)); $renderedPages = []; foreach ($pages as $page) { $currentOutput = $page['output']; $link = static function (string $routeKey) use ($routes, $currentOutput): string { if (!isset($routes[$routeKey])) { throw new RuntimeException("Unknown route key: {$routeKey}"); } return relative_url($currentOutput, $routes[$routeKey]['output']); }; $asset = static fn (string $path): string => relative_url($currentOutput, normalize_site_path($path)); $renderPartial = null; $shared = [ 'site' => $site, 'page' => $page, 'routes' => $routes, 'link' => $link, 'asset' => $asset, ]; $renderPartial = static function (string $name, array $vars = []) use ($sourceRoot, $shared, &$renderPartial): string { return render_template( $sourceRoot . '/templates/partials/' . normalize_site_path($name) . '.php', array_merge($shared, $vars, ['renderPartial' => $renderPartial]) ); }; $bodyHtml = $renderPartial($page['template']); $html = render_template($sourceRoot . '/templates/layout.php', array_merge($shared, [ 'bodyHtml' => $bodyHtml, 'renderPartial' => $renderPartial, ])); $renderedPages[] = [ 'page' => $page, 'html' => $html, ]; } foreach ($renderedPages as $renderedPage) { $outputPath = join_site_path($outputRoot, $renderedPage['page']['output']); $outputDir = dirname($outputPath); if (!is_dir($outputDir) && !mkdir($outputDir, 0777, true) && !is_dir($outputDir)) { throw new RuntimeException("Unable to create output directory: {$outputDir}"); } if (file_put_contents($outputPath, $renderedPage['html']) === false) { throw new RuntimeException("Unable to write output file: {$outputPath}"); } } $blogIndexPath = join_site_path($outputRoot, 'blog/search-index.json'); $encodedBlogIndex = json_payload(blog_search_index($site['blogPosts']), true); if (file_put_contents($blogIndexPath, $encodedBlogIndex . "\n") === false) { throw new RuntimeException("Unable to write blog search index: {$blogIndexPath}"); } foreach ($renderedPages as $renderedPage) { validate_local_references($outputRoot, $renderedPage['page']['output'], $renderedPage['html']); } echo 'Built ' . count($renderedPages) . " pages into public/:\n"; foreach ($renderedPages as $renderedPage) { echo ' - ' . $renderedPage['page']['output'] . "\n"; }