1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
<?php
/**
* Helper to parse changelog TXT files and render them as HTML.
*/
function get_changelog_entries($limit = null) {
$files = glob(dirname(__DIR__) . '/*-changelog.txt');
rsort($files); // Newest years first
$all_entries = [];
foreach ($files as $file) {
$content = file_get_contents($file);
$lines = explode("\n", $content);
// An entry starts on a "* <date>: ..." line; following lines that do
// not start with "*" are wrapped continuations of that same entry, so
// fold them back in instead of dropping them (which truncated the text).
$current = null;
$flush = function () use (&$current, &$all_entries) {
if ($current === null) return;
$current['text'] = trim(preg_replace('/\s+/', ' ', $current['text']));
$all_entries[] = $current;
$current = null;
};
foreach ($lines as $line) {
$line = rtrim($line);
if (str_starts_with(ltrim($line), '*')) {
$flush();
// Format: * 9 Sept 2024: Description
if (preg_match('/^\*\s*(\d+\s+\w+\s+(\d{4})):\s*(.*)$/', trim($line), $matches)) {
$date_str = $matches[1];
$entry_year = (int)$matches[2];
$timestamp = strtotime($date_str);
$iso_date = $timestamp ? date('Y-m-d', $timestamp) : '';
$display_date = $timestamp ? date('Y-m-d', $timestamp) : $date_str;
$current = [
'year' => $entry_year,
'date' => $iso_date,
'display_date' => $display_date,
'text' => $matches[3],
'raw_date' => $date_str
];
}
} elseif ($current !== null && trim($line) !== '') {
$current['text'] .= ' ' . trim($line);
}
}
$flush();
}
// Sort by date DESC
usort($all_entries, function($a, $b) {
return strcmp($b['date'], $a['date']);
});
if ($limit !== null) {
return array_slice($all_entries, 0, $limit);
}
return $all_entries;
}
function get_changelog_by_year() {
$entries = get_changelog_entries();
$by_year = [];
foreach ($entries as $e) {
$by_year[$e['year']][] = $e;
}
krsort($by_year);
return $by_year;
}
function render_changelog_list($entries) {
if (empty($entries)) return '<p class="muted">No entries yet.</p>';
$html = '<ul class="changelog-list">';
foreach ($entries as $e) {
$html .= '<li class="changelog-entry">';
if ($e['date']) {
$html .= '<time datetime="' . htmlspecialchars($e['date']) . '">' . htmlspecialchars($e['display_date']) . '</time>';
}
$html .= '<div class="text">' . htmlspecialchars($e['text']) . '</div>';
$html .= '<a class="changelog-more" href="https://www.sillylaird.ca/changelog/#year-' . (int)$e['year'] . '">more (' . (int)$e['year'] . ') →</a>';
$html .= '</li>';
}
$html .= '</ul>';
return $html;
}
|