View Source

The actual code behind this page. No minification. No transpilation. What you see is what runs.

↓ Download PHP edition
source.php 162 lines
<?php
$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">&#8595; 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 : '&nbsp;' ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
 
</div>
 
<?php require_once __DIR__ . '/includes/footer.php'; ?>