| Author | Dave Jarvis <email> |
|---|---|
| Date | 2026-02-16 17:10:10 GMT-0800 |
| Commit | 01bdff3e50f6c71c33d35f25864ab5d6644ed75d |
| Parent | 8b0e585 |
| abstract class BasePage implements Page { | ||
| - protected $repositories; | ||
| - protected $title; | ||
| + private $repositories; | ||
| + private $title; | ||
| - public function __construct( array $repositories ) { | ||
| + public function __construct( array $repositories, string $title = '' ) { | ||
| $this->repositories = $repositories; | ||
| + $this->title = $title; | ||
| } | ||
| - protected function renderLayout( $contentCallback, $currentRepo = null ) { | ||
| + protected function renderLayout( | ||
| + $contentCallback, | ||
| + array $currentRepo = [] | ||
| + ) { | ||
| + $siteTitle = Config::SITE_TITLE; | ||
| + $pageTitle = $this->title | ||
| + ? ' - ' . htmlspecialchars( $this->title ) | ||
| + : ''; | ||
| + | ||
| ?> | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8"> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
| - <title><?php | ||
| - echo Config::SITE_TITLE . | ||
| - ( $this->title ? ' - ' . htmlspecialchars( $this->title ) : '' ); | ||
| - ?></title> | ||
| - <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | ||
| + <title><?php echo $siteTitle . $pageTitle; ?></title> | ||
| + <link rel="stylesheet" | ||
| + href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | ||
| <link rel="stylesheet" href="/styles/repo.css"> | ||
| </head> | ||
| <body> | ||
| <div class="container"> | ||
| <header> | ||
| <h1><?php echo Config::SITE_TITLE; ?></h1> | ||
| <nav class="nav"> | ||
| <a href="<?php echo (new UrlBuilder())->build(); ?>">Home</a> | ||
| - <?php if( $currentRepo ): | ||
| - $safeName = $currentRepo['safe_name']; | ||
| - ?> | ||
| - <a href="<?php echo (new UrlBuilder())->withRepo( $safeName )->withAction( 'tree' )->build(); ?>">Files</a> | ||
| - <a href="<?php echo (new UrlBuilder())->withRepo( $safeName )->withAction( 'commits' )->build(); ?>">Commits</a> | ||
| - <a href="<?php echo (new UrlBuilder())->withRepo( $safeName )->withAction( 'tags' )->build(); ?>">Tags</a> | ||
| + <?php if( $currentRepo ): ?> | ||
| + <?php $safeName = $currentRepo['safe_name']; ?> | ||
| + <a href="<?php echo (new UrlBuilder()) | ||
| + ->withRepo( $safeName ) | ||
| + ->withAction( 'tree' ) | ||
| + ->build(); ?>">Files</a> | ||
| + <a href="<?php echo (new UrlBuilder()) | ||
| + ->withRepo( $safeName ) | ||
| + ->withAction( 'commits' ) | ||
| + ->build(); ?>">Commits</a> | ||
| + <a href="<?php echo (new UrlBuilder()) | ||
| + ->withRepo( $safeName ) | ||
| + ->withAction( 'tags' ) | ||
| + ->build(); ?>">Tags</a> | ||
| <?php endif; ?> | ||
| <?php if( $currentRepo ): ?> | ||
| <div class="repo-selector"> | ||
| <label>Repository:</label> | ||
| - <select onchange="<?php echo (new UrlBuilder())->withSwitcher( 'this.value' )->build(); ?>"> | ||
| + <select onchange="<?php echo (new UrlBuilder()) | ||
| + ->withSwitcher( 'this.value' ) | ||
| + ->build(); ?>"> | ||
| <?php foreach( $this->repositories as $r ): ?> | ||
| - <option value="<?php echo htmlspecialchars( $r['safe_name'] ); ?>" | ||
| - <?php echo $r['safe_name'] === $currentRepo['safe_name'] ? 'selected' : ''; ?>> | ||
| + <option | ||
| + value="<?php echo htmlspecialchars( $r['safe_name'] ); ?>" | ||
| + <?php | ||
| + echo $r['safe_name'] === $currentRepo['safe_name'] | ||
| + ? 'selected' | ||
| + : ''; | ||
| + ?>> | ||
| <?php echo htmlspecialchars( $r['name'] ); ?> | ||
| </option> | ||
| } | ||
| - protected function renderBreadcrumbs( $repo, $trail = [] ) { | ||
| + protected function renderBreadcrumbs( array $repo, array $trail = [] ) { | ||
| $repoUrl = (new UrlBuilder())->withRepo( $repo['safe_name'] )->build(); | ||
| string $hash | ||
| ) { | ||
| - parent::__construct( $repositories ); | ||
| + parent::__construct( $repositories, $currentRepo['name'] ); | ||
| + | ||
| $this->currentRepo = $currentRepo; | ||
| - $this->git = $git; | ||
| - $this->hash = $hash; | ||
| - $this->title = $currentRepo['name']; | ||
| + $this->git = $git; | ||
| + $this->hash = $hash; | ||
| } | ||
| public function render() { | ||
| $this->renderLayout( function() { | ||
| $main = $this->git->getMainBranch(); | ||
| if( !$main ) { | ||
| echo '<div class="empty-state"><h3>No branches</h3>' . | ||
| '<p>Empty repository.</p></div>'; | ||
| - return; | ||
| - } | ||
| + } else { | ||
| + $this->renderBreadcrumbs( $this->currentRepo, ['Commits'] ); | ||
| - $this->renderBreadcrumbs( $this->currentRepo, ['Commits'] ); | ||
| + echo '<h2>Commit History <span class="branch-badge">' . | ||
| + htmlspecialchars( $main['name'] ) . '</span></h2>'; | ||
| + echo '<div class="commit-list">'; | ||
| - echo '<h2>Commit History <span class="branch-badge">' . | ||
| - htmlspecialchars( $main['name'] ) . '</span></h2>'; | ||
| - echo '<div class="commit-list">'; | ||
| + $start = $this->hash ?: $main['hash']; | ||
| - $start = $this->hash ?: $main['hash']; | ||
| + $this->git->history( $start, 100, function( $commit ) { | ||
| + $msg = htmlspecialchars( explode( "\n", $commit->message )[0] ); | ||
| - $this->git->history( $start, 100, function( $commit ) { | ||
| - $msg = htmlspecialchars( explode( "\n", $commit->message )[0] ); | ||
| + $url = (new UrlBuilder()) | ||
| + ->withRepo( $this->currentRepo['safe_name'] ) | ||
| + ->withAction( 'commit' ) | ||
| + ->withHash( $commit->sha ) | ||
| + ->build(); | ||
| - $url = (new UrlBuilder()) | ||
| - ->withRepo( $this->currentRepo['safe_name'] ) | ||
| - ->withAction( 'commit' ) | ||
| - ->withHash( $commit->sha ) | ||
| - ->build(); | ||
| + echo '<div class="commit-row">'; | ||
| + echo '<a href="' . $url . '" class="sha">' . | ||
| + substr( $commit->sha, 0, 7 ) . '</a>'; | ||
| + echo '<span class="message">' . $msg . '</span>'; | ||
| + echo '<span class="meta">' . | ||
| + htmlspecialchars( $commit->author ) . | ||
| + ' • ' . date( 'Y-m-d', $commit->date ) . '</span>'; | ||
| + echo '</div>'; | ||
| + } ); | ||
| - echo '<div class="commit-row">'; | ||
| - echo '<a href="' . $url . '" class="sha">' . substr( $commit->sha, 0, 7 ) . '</a>'; | ||
| - echo '<span class="message">' . $msg . '</span>'; | ||
| - echo '<span class="meta">' . htmlspecialchars( $commit->author ) . | ||
| - ' • ' . date( 'Y-m-d', $commit->date ) . '</span>'; | ||
| echo '</div>'; | ||
| - } ); | ||
| - | ||
| - echo '</div>'; | ||
| + } | ||
| }, $this->currentRepo ); | ||
| } |
| string $oldSha | ||
| ) { | ||
| - parent::__construct( $repositories ); | ||
| + $title = $currentRepo['name'] . ' - Compare'; | ||
| + parent::__construct( $repositories, $title ); | ||
| + | ||
| $this->currentRepo = $currentRepo; | ||
| - $this->git = $git; | ||
| - $this->newSha = $newSha; | ||
| - $this->oldSha = $oldSha; | ||
| - $this->title = $currentRepo['name'] . ' - Compare'; | ||
| + $this->git = $git; | ||
| + $this->newSha = $newSha; | ||
| + $this->oldSha = $oldSha; | ||
| } | ||
| ); | ||
| - $differ = new GitDiff( $this->git ); | ||
| + $differ = new GitDiff( $this->git ); | ||
| $changes = $differ->diff( $this->oldSha, $this->newSha ); | ||
| if( empty( $changes ) ) { | ||
| echo '<div class="empty-state"><h3>No changes</h3>' . | ||
| '<p>No differences.</p></div>'; | ||
| - return; | ||
| - } | ||
| - | ||
| - foreach( $changes as $change ) { | ||
| - $this->renderDiffFile( $change ); | ||
| + } else { | ||
| + foreach( $changes as $change ) { | ||
| + $this->renderDiffFile( $change ); | ||
| + } | ||
| } | ||
| }, $this->currentRepo ); | ||
| $statusClass = $typeMap[$change['type']] ?? 'modified'; | ||
| - $path = htmlspecialchars( $change['path'] ); | ||
| + $path = htmlspecialchars( $change['path'] ); | ||
| echo '<div class="diff-file">'; | ||
| if( isset( $line['t'] ) && $line['t'] === 'gap' ) { | ||
| echo '<tr class="diff-gap"><td colspan="3">...</td></tr>'; | ||
| - return; | ||
| - } | ||
| - | ||
| - $class = match( $line['t'] ) { | ||
| - '+' => 'diff-add', | ||
| - '-' => 'diff-del', | ||
| - default => '' | ||
| - }; | ||
| + } else { | ||
| + $class = match( $line['t'] ) { | ||
| + '+' => 'diff-add', | ||
| + '-' => 'diff-del', | ||
| + default => '' | ||
| + }; | ||
| - echo '<tr class="' . $class . '">'; | ||
| - echo '<td class="diff-line-num">' . ($line['no'] ?? '') . '</td>'; | ||
| - echo '<td class="diff-line-num">' . ($line['nn'] ?? '') . '</td>'; | ||
| - echo '<td class="diff-code"><pre>' . | ||
| - htmlspecialchars( $line['l'] ?? '' ) . '</pre></td>'; | ||
| - echo '</tr>'; | ||
| + echo '<tr class="' . $class . '">'; | ||
| + echo '<td class="diff-line-num">' . ($line['no'] ?? '') . '</td>'; | ||
| + echo '<td class="diff-line-num">' . ($line['nn'] ?? '') . '</td>'; | ||
| + echo '<td class="diff-code"><pre>' . | ||
| + htmlspecialchars( $line['l'] ?? '' ) . '</pre></td>'; | ||
| + echo '</tr>'; | ||
| + } | ||
| } | ||
| } | ||
| string $hash | ||
| ) { | ||
| - parent::__construct( $repositories ); | ||
| + parent::__construct( $repositories, substr( $hash, 0, 7 ) ); | ||
| + | ||
| $this->currentRepo = $currentRepo; | ||
| - $this->git = $git; | ||
| - $this->hash = $hash; | ||
| - $this->title = substr( $hash, 0, 7 ); | ||
| + $this->git = $git; | ||
| + $this->hash = $hash; | ||
| } | ||
| public function render() { | ||
| $this->renderLayout( function() { | ||
| $commitData = $this->git->read( $this->hash ); | ||
| $diffEngine = new GitDiff( $this->git ); | ||
| - $lines = explode( "\n", $commitData ); | ||
| - $msg = ''; | ||
| - $isMsg = false; | ||
| - $headers = []; | ||
| + $lines = explode( "\n", $commitData ); | ||
| + $msg = ''; | ||
| + $isMsg = false; | ||
| + $headers = []; | ||
| foreach( $lines as $line ) { | ||
| '<a href="' . $commitsUrl . '">Commits</a>', | ||
| substr( $this->hash, 0, 7 ) | ||
| - ]); | ||
| + ] ); | ||
| $author = $headers['author'] ?? 'Unknown'; | ||
| $author = preg_replace( '/<[^>]+>/', '<email>', $author ); | ||
| echo '<div class="commit-details">'; | ||
| echo '<div class="commit-header">'; | ||
| - echo '<h1 class="commit-title">' . htmlspecialchars( trim( $msg ) ) . '</h1>'; | ||
| + echo '<h1 class="commit-title">' . | ||
| + htmlspecialchars( trim( $msg ) ) . '</h1>'; | ||
| echo '<div class="commit-info">'; | ||
| - echo '<div class="commit-info-row"><span class="commit-info-label">Author</span>' . | ||
| - '<span class="commit-author">' . htmlspecialchars( $author ) . '</span></div>'; | ||
| - echo '<div class="commit-info-row"><span class="commit-info-label">Commit</span>' . | ||
| - '<span class="commit-info-value">' . $this->hash . '</span></div>'; | ||
| + echo '<div class="commit-info-row">' . | ||
| + '<span class="commit-info-label">Author</span>' . | ||
| + '<span class="commit-author">' . | ||
| + htmlspecialchars( $author ) . '</span></div>'; | ||
| + echo '<div class="commit-info-row">' . | ||
| + '<span class="commit-info-label">Commit</span>' . | ||
| + '<span class="commit-info-value">' . | ||
| + $this->hash . '</span></div>'; | ||
| if( isset( $headers['parent'] ) ) { | ||
| $url = (new UrlBuilder()) | ||
| ->withRepo( $this->currentRepo['safe_name'] ) | ||
| ->withAction( 'commit' ) | ||
| ->withHash( $headers['parent'] ) | ||
| ->build(); | ||
| - echo '<div class="commit-info-row"><span class="commit-info-label">Parent</span>' . | ||
| + echo '<div class="commit-info-row">' . | ||
| + '<span class="commit-info-label">Parent</span>' . | ||
| '<span class="commit-info-value">'; | ||
| echo '<a href="' . $url . '" class="parent-link">' . | ||
| private function renderFileDiff( $change ) { | ||
| - $statusIcon = 'fa-file'; | ||
| + $statusIcon = 'fa-file'; | ||
| $statusClass = ''; | ||
| if( $change['type'] === 'A' ) { | ||
| - $statusIcon = 'fa-plus-circle'; | ||
| + $statusIcon = 'fa-plus-circle'; | ||
| $statusClass = 'status-add'; | ||
| } | ||
| if( $change['type'] === 'D' ) { | ||
| - $statusIcon = 'fa-minus-circle'; | ||
| + $statusIcon = 'fa-minus-circle'; | ||
| $statusClass = 'status-del'; | ||
| } | ||
| if( $change['type'] === 'M' ) { | ||
| - $statusIcon = 'fa-pencil-alt'; | ||
| + $statusIcon = 'fa-pencil-alt'; | ||
| $statusClass = 'status-mod'; | ||
| } | ||
| echo '<div class="diff-file">'; | ||
| echo '<div class="diff-header">'; | ||
| echo '<span class="diff-status ' . $statusClass . '">' . | ||
| '<i class="fa ' . $statusIcon . '"></i></span>'; | ||
| - echo '<span class="diff-path">' . htmlspecialchars( $change['path'] ) . '</span>'; | ||
| + echo '<span class="diff-path">' . | ||
| + htmlspecialchars( $change['path'] ) . '</span>'; | ||
| echo '</div>'; | ||
| $class = 'diff-ctx'; | ||
| - $char = ' '; | ||
| + $char = ' '; | ||
| if( $line['t'] === '+' ) { | ||
| $class = 'diff-add'; | ||
| - $char = '+'; | ||
| + $char = '+'; | ||
| } | ||
| if( $line['t'] === '-' ) { | ||
| $class = 'diff-del'; | ||
| - $char = '-'; | ||
| + $char = '-'; | ||
| } | ||
| echo '<tr class="' . $class . '">'; | ||
| echo '<td class="diff-num" data-num="' . $line['no'] . '"></td>'; | ||
| echo '<td class="diff-num" data-num="' . $line['nn'] . '"></td>'; | ||
| - echo '<td class="diff-code"><span class="diff-marker">' . $char . '</span>' . | ||
| - htmlspecialchars( $line['l'] ) . '</td>'; | ||
| + echo '<td class="diff-code"><span class="diff-marker">' . | ||
| + $char . '</span>' . htmlspecialchars( $line['l'] ) . '</td>'; | ||
| echo '</tr>'; | ||
| } | ||
| class FilePage extends BasePage { | ||
| private const MAX_HIGHLIGHT_SIZE = 65536; | ||
| - private const MAX_DISPLAY_SIZE = 524288; | ||
| + private const MAX_DISPLAY_SIZE = 524288; | ||
| private $currentRepo; | ||
| string $path = '' | ||
| ) { | ||
| - parent::__construct( $repositories ); | ||
| + parent::__construct( $repositories, $currentRepo['name'] ); | ||
| + | ||
| $this->currentRepo = $currentRepo; | ||
| - $this->git = $git; | ||
| - $this->hash = $hash ?: 'HEAD'; | ||
| - $this->path = $path; | ||
| - $this->title = $currentRepo['name']; | ||
| + $this->git = $git; | ||
| + $this->hash = $hash ?: 'HEAD'; | ||
| + $this->path = $path; | ||
| } | ||
| } | ||
| - private function isExactFileMatch($entries) { | ||
| - return count( $entries ) === 1 && | ||
| - $entries[0]->isName( basename( $this->path ) ) && | ||
| - !$entries[0]->isDir; | ||
| + private function isExactFileMatch( $entries ) { | ||
| + return count( $entries ) === 1 && | ||
| + $entries[0]->isName( basename( $this->path ) ) && | ||
| + !$entries[0]->isDir; | ||
| } | ||
| echo '<table class="file-list-table">'; | ||
| - echo '<thead><tr><th></th><th>Name</th><th class="file-mode-cell">Mode</th><th class="file-size-cell">Size</th></tr></thead>'; | ||
| + echo '<thead><tr><th></th><th>Name</th>' . | ||
| + '<th class="file-mode-cell">Mode</th>' . | ||
| + '<th class="file-size-cell">Size</th></tr></thead>'; | ||
| echo '<tbody>'; | ||
| private function renderBlob( $targetHash ) { | ||
| $filename = $this->path; | ||
| - $file = $this->git->readFile( $targetHash, $filename ); | ||
| - $size = $this->git->getObjectSize( $targetHash, $filename ); | ||
| + $file = $this->git->readFile( $targetHash, $filename ); | ||
| + $size = $this->git->getObjectSize( $targetHash, $filename ); | ||
| - $renderer = new HtmlFileRenderer( $this->currentRepo['safe_name'], dirname($filename), $targetHash ); | ||
| + $renderer = new HtmlFileRenderer( | ||
| + $this->currentRepo['safe_name'], | ||
| + dirname( $filename ), | ||
| + $targetHash | ||
| + ); | ||
| $this->emitBreadcrumbs( $targetHash, 'File', $filename ); | ||
| if( $size === 0 && !$file ) { | ||
| - echo '<div class="empty-state">File not found.</div>'; | ||
| - return; | ||
| - } | ||
| + echo '<div class="empty-state">File not found.</div>'; | ||
| + } else { | ||
| + $rawUrl = (new UrlBuilder()) | ||
| + ->withRepo( $this->currentRepo['safe_name'] ) | ||
| + ->withAction( 'raw' ) | ||
| + ->withHash( $targetHash ) | ||
| + ->withName( $filename ) | ||
| + ->build(); | ||
| - $rawUrl = (new UrlBuilder()) | ||
| - ->withRepo( $this->currentRepo['safe_name'] ) | ||
| - ->withAction( 'raw' ) | ||
| - ->withHash( $targetHash ) | ||
| - ->withName( $filename ) | ||
| - ->build(); | ||
| + if( !$file->renderMedia( $renderer, $rawUrl ) ) { | ||
| + if( $file->isText() ) { | ||
| + if( $size > self::MAX_DISPLAY_SIZE ) { | ||
| + ob_start(); | ||
| + $file->renderSize( $renderer ); | ||
| + $sizeStr = ob_get_clean(); | ||
| + $this->renderDownloadState( | ||
| + $targetHash, | ||
| + "File is too large to display ($sizeStr)." | ||
| + ); | ||
| + } else { | ||
| + $content = ''; | ||
| + $this->git->stream( | ||
| + $targetHash, | ||
| + function( $d ) use ( &$content ) { | ||
| + $content .= $d; | ||
| + }, | ||
| + $filename | ||
| + ); | ||
| - if( !$file->renderMedia( $renderer, $rawUrl ) ) { | ||
| - if( $file->isText() ) { | ||
| - if( $size > self::MAX_DISPLAY_SIZE ) { | ||
| - ob_start(); | ||
| - $file->renderSize( $renderer ); | ||
| - $sizeStr = ob_get_clean(); | ||
| - $this->renderDownloadState( $targetHash, "File is too large to display ($sizeStr)." ); | ||
| + echo '<div class="blob-content"><pre class="blob-code">' . | ||
| + ($size > self::MAX_HIGHLIGHT_SIZE | ||
| + ? htmlspecialchars( $content ) | ||
| + : $file->highlight( $renderer, $content )) . | ||
| + '</pre></div>'; | ||
| + } | ||
| } else { | ||
| - $content = ''; | ||
| - $this->git->stream( $targetHash, function( $d ) use ( &$content ) { | ||
| - $content .= $d; | ||
| - }, $filename ); | ||
| - | ||
| - echo '<div class="blob-content"><pre class="blob-code">' . | ||
| - ($size > self::MAX_HIGHLIGHT_SIZE | ||
| - ? htmlspecialchars( $content ) | ||
| - : $file->highlight( $renderer, $content )) . | ||
| - '</pre></div>'; | ||
| + $this->renderDownloadState( | ||
| + $targetHash, | ||
| + "This is a binary file." | ||
| + ); | ||
| } | ||
| - } else { | ||
| - $this->renderDownloadState( $targetHash, "This is a binary file." ); | ||
| } | ||
| } | ||
| if( $path ) { | ||
| $parts = explode( '/', trim( $path, '/' ) ); | ||
| - $acc = ''; | ||
| + $acc = ''; | ||
| foreach( $parts as $idx => $part ) { | ||
| ->build(); | ||
| - $trail[] = '<a href="' . $url . '">' . htmlspecialchars( $part ) . '</a>'; | ||
| + $trail[] = '<a href="' . $url . '">' . | ||
| + htmlspecialchars( $part ) . '</a>'; | ||
| } | ||
| } | ||
| class HomePage extends BasePage { | ||
| + private $repositories; | ||
| private $git; | ||
| public function __construct( array $repositories, Git $git ) { | ||
| parent::__construct( $repositories ); | ||
| - $this->git = $git; | ||
| + $this->repositories = $repositories; | ||
| + $this->git = $git; | ||
| } | ||
| public function render() { | ||
| $this->renderLayout( function() { | ||
| echo '<h2>Repositories</h2>'; | ||
| if( empty( $this->repositories ) ) { | ||
| echo '<div class="empty-state">No repositories found.</div>'; | ||
| - return; | ||
| - } | ||
| + } else { | ||
| + echo '<div class="repo-grid">'; | ||
| - echo '<div class="repo-grid">'; | ||
| + foreach( $this->repositories as $repo ) { | ||
| + $this->renderRepoCard( $repo ); | ||
| + } | ||
| - foreach( $this->repositories as $repo ) { | ||
| - $this->renderRepoCard( $repo ); | ||
| + echo '</div>'; | ||
| } | ||
| - | ||
| - echo '</div>'; | ||
| } ); | ||
| } | ||
| private function renderRepoCard( $repo ) { | ||
| $this->git->setRepository( $repo['path'] ); | ||
| - $main = $this->git->getMainBranch(); | ||
| + $main = $this->git->getMainBranch(); | ||
| $stats = [ | ||
| 'branches' => 0, | ||
| - 'tags' => 0 | ||
| + 'tags' => 0 | ||
| ]; | ||
| $branchLabel = $stats['branches'] === 1 ? 'branch' : 'branches'; | ||
| - $tagLabel = $stats['tags'] === 1 ? 'tag' : 'tags'; | ||
| + $tagLabel = $stats['tags'] === 1 ? 'tag' : 'tags'; | ||
| echo $stats['branches'] . ' ' . $branchLabel . ', ' . | ||
| <?php | ||
| interface Page { | ||
| - public function render(); | ||
| + public function render(); | ||
| } | ||
| Git $git | ||
| ) { | ||
| - parent::__construct( $repositories ); | ||
| + parent::__construct( | ||
| + $repositories, | ||
| + $currentRepo['name'] . ' - Tags' | ||
| + ); | ||
| + | ||
| $this->currentRepo = $currentRepo; | ||
| - $this->git = $git; | ||
| - $this->title = $currentRepo['name'] . ' - Tags'; | ||
| + $this->git = $git; | ||
| } | ||
| echo '<p>No tags found.</p>'; | ||
| } else { | ||
| - $renderer = new HtmlTagRenderer( $this->currentRepo['safe_name'] ); | ||
| + $renderer = new HtmlTagRenderer( | ||
| + $this->currentRepo['safe_name'] | ||
| + ); | ||
| echo '<table class="tag-table">'; | ||
| $count = count( $tags ); | ||
| for( $i = 0; $i < $count; $i++ ) { | ||
| - $tag = $tags[$i]; | ||
| + $tag = $tags[$i]; | ||
| $prevTag = $tags[$i + 1] ?? null; | ||
| $tag->render( $renderer, $prevTag ); | ||
| Delta | 208 lines added, 157 lines removed, 51-line increase |
|---|