View Source
The actual code behind this page. No minification. No transpilation. What you see is what runs.
|
| $pageTitle = 'View Source — dispelled.ca'; |
| $currentPage = 'source'; |
| require_once __DIR__ . '/includes/config.php'; |
| // ── Viewable files ──────────────────────────────────────────────────────────── |
| // Each entry: display label => path relative to this file's directory |
| $files = [ |
| 'pages' => [ |
| 'index.php' => ['label' => 'index.php', 'path' => __DIR__ . '/index.php'], |
| 'cori.php' => ['label' => 'cori.php', 'path' => __DIR__ . '/cori.php'], |
| 'j.php' => ['label' => 'j.php', 'path' => __DIR__ . '/j.php'], |
| 'weather.php' => ['label' => 'weather.php', 'path' => __DIR__ . '/weather.php'], |
| 'community.php' => ['label' => 'community.php', 'path' => __DIR__ . '/community.php'], |
| 'github.php' => ['label' => 'github.php', 'path' => __DIR__ . '/github.php'], |
| 'stocks.php' => ['label' => 'stocks.php', 'path' => __DIR__ . '/stocks.php'], |
| 'links.php' => ['label' => 'links.php', 'path' => __DIR__ . '/links.php'], |
| 'about.php' => ['label' => 'about.php', 'path' => __DIR__ . '/about.php'], |
| 'agent.php' => ['label' => 'agent.php', 'path' => __DIR__ . '/agent.php'], |
| 'source.php' => ['label' => 'source.php', 'path' => __FILE__], |
| ], |
| 'includes' => [ |
| 'includes/config.php' => ['label' => 'config.php', 'path' => __DIR__ . '/includes/config.php'], |
| 'includes/header.php' => ['label' => 'header.php', 'path' => __DIR__ . '/includes/header.php'], |
| 'includes/footer.php' => ['label' => 'footer.php', 'path' => __DIR__ . '/includes/footer.php'], |
| 'includes/rss.php' => ['label' => 'rss.php', 'path' => __DIR__ . '/includes/rss.php'], |
| 'includes/weather.php' => ['label' => 'weather.php', 'path' => __DIR__ . '/includes/weather.php'], |
| 'includes/reddit.php' => ['label' => 'reddit.php', 'path' => __DIR__ . '/includes/reddit.php'], |
| ], |
| 'assets' => [ |
| 'css/style.css' => ['label' => 'style.css', 'path' => __DIR__ . '/css/style.css'], |
| 'router.php' => ['label' => 'router.php', 'path' => __DIR__ . '/../router.php'], |
| ], |
| ]; |
| // Build a flat lookup for validation |
| $allFiles = array_merge(...array_values($files)); |
| $requested = $_GET['file'] ?? 'index.php'; |
| if (!array_key_exists($requested, $allFiles)) { |
| $requested = 'index.php'; |
| } |
| $fileInfo = $allFiles[$requested]; |
| $source = file_get_contents($fileInfo['path']); |
| $ext = pathinfo($fileInfo['path'], PATHINFO_EXTENSION); |
| // Tune PHP's built-in highlighter to match the dark theme |
| ini_set('highlight.comment', '#6d95b0'); |
| ini_set('highlight.default', '#ccdde8'); |
| ini_set('highlight.html', '#5ab8e8'); |
| ini_set('highlight.keyword', '#79c0ff'); |
| ini_set('highlight.string', '#e8a87c'); |
| /** |
| * Split highlighted PHP HTML into per-line strings, keeping spans balanced. |
| * |
| * highlight_string() wraps tokens in <span> tags that can straddle <br /> |
| * boundaries (e.g. a multi-line string). We track every span opened on |
| * previous lines and prepend them (unclosed) to the next line, closing them |
| * at the end of that line so each line is valid HTML on its own. |
| */ |
| function splitHighlightedLines(string $html): array |
| { |
| // PHP versions differ on outer wrapper (<code> vs <span>) and line-break |
| // representation (<br /> in older versions, real \n in PHP 8.3+). |
| // Strip whichever outer tag is present. |
| $inner = preg_replace('#^<(?:code|span)[^>]*>(.*)</(?:code|span)>$#s', '$1', $html); |
| // Normalise every line-break variant to a plain \n so we split once. |
| $inner = str_replace(['<br />', '<br/>', '<br>'], "\n", $inner); |
| $rawLines = explode("\n", $inner); |
| $lines = []; |
| $openTags = []; // stack of currently-open <span …> strings |
| foreach ($rawLines as $raw) { |
| // Prepend any spans that were still open from the previous line |
| $line = implode('', $openTags) . $raw; |
| // Find all <span …> and </span> tags in this line to update the stack |
| preg_match_all('#<span\s[^>]*>|</span>#i', $raw, $m); |
| foreach ($m[0] as $tag) { |
| if (stripos($tag, '</span') === 0) { |
| array_pop($openTags); |
| } else { |
| $openTags[] = $tag; |
| } |
| } |
| // Close any spans that are still open so the line is valid HTML |
| $line .= str_repeat('</span>', count($openTags)); |
| $lines[] = $line; |
| } |
| return $lines; |
| } |
| // Build the numbered lines array |
| if ($ext === 'php') { |
| $highlighted = highlight_string($source, true); |
| $numberedLines = splitHighlightedLines($highlighted); |
| } else { |
| $numberedLines = array_map('htmlspecialchars', explode("\n", $source)); |
| } |
| require_once __DIR__ . '/includes/header.php'; |
| ?> |
| <div class="source-header"> |
| <div style="display:flex;align-items:flex-start;justify-content:space-between;flex-wrap:wrap;gap:1rem;"> |
| <div> |
| <h1 class="page-title" style="margin-bottom:.5rem;">View Source</h1> |
| <p class="source-subtitle">The actual code behind this page. No minification. No transpilation. What you see is what runs.</p> |
| </div> |
| <a href="/api/source/package" download="dispelled-ca.zip" class="dl-btn">↓ Download PHP edition</a> |
| </div> |
| </div> |
| <div class="source-layout"> |
| <!-- File browser sidebar --> |
| <nav class="source-nav" aria-label="Source files"> |
| <?php foreach ($files as $groupName => $group): ?> |
| <div class="source-nav-group"> |
| <span class="source-nav-label"><?= htmlspecialchars($groupName) ?></span> |
| <?php foreach ($group as $key => $info): ?> |
| <a href="?file=<?= urlencode($key) ?>" |
| class="source-nav-link<?= $key === $requested ? ' active' : '' ?>"> |
| <?= htmlspecialchars($info['label']) ?> |
| </a> |
| <?php endforeach; ?> |
| </div> |
| <?php endforeach; ?> |
| </nav> |
| <!-- Source panel --> |
| <div class="source-panel"> |
| <div class="source-toolbar"> |
| <span class="source-filename"><?= htmlspecialchars($fileInfo['label']) ?></span> |
| <span class="source-lines"><?= count($numberedLines) ?> lines</span> |
| </div> |
| <div class="source-code-wrap"> |
| <table class="source-table" aria-label="Source code"> |
| <tbody> |
| <?php foreach ($numberedLines as $i => $line): ?> |
| <tr> |
| <td class="source-ln" aria-hidden="true"><?= $i + 1 ?></td> |
| <td class="source-line"><?= $line !== '' ? $line : ' ' ?></td> |
| </tr> |
| <?php endforeach; ?> |
| </tbody> |
| </table> |
| </div> |
| </div> |
| </div> |
| <?php require_once __DIR__ . '/includes/footer.php'; ?> |
dispelled