aboutsummaryrefslogtreecommitdiffstats
path: root/changelog/api/parser.php
blob: fe0dd8543765ead803df78c95aed399019d4433d (plain) (blame)
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'] . ') &rarr;</a>';
        $html .= '</li>';
    }
    $html .= '</ul>';
    return $html;
}