| require_once __DIR__ . '/../model/UrlBuilder.php'; | ||
| +class DiffStats { | ||
| + private $added = 0; | ||
| + private $deleted = 0; | ||
| + private $empty = true; | ||
| + | ||
| + public function track( array $change ): array { | ||
| + $this->empty = false; | ||
| + | ||
| + foreach( $change['hunks'] as $hunkLine ) { | ||
| + if( $hunkLine['t'] === '+' ) { | ||
| + $this->added++; | ||
| + } elseif( $hunkLine['t'] === '-' ) { | ||
| + $this->deleted++; | ||
| + } | ||
| + } | ||
| + | ||
| + return $change; | ||
| + } | ||
| + | ||
| + public function isEmpty(): bool { | ||
| + return $this->empty; | ||
| + } | ||
| + | ||
| + public function __toString(): string { | ||
| + $diffNet = $this->added - $this->deleted; | ||
| + $addPl = $this->added !== 1 ? 's' : ''; | ||
| + $delPl = $this->deleted !== 1 ? 's' : ''; | ||
| + $msg = $this->added . ' line' . $addPl . ' added, ' . | ||
| + $this->deleted . ' line' . $delPl . ' removed'; | ||
| + | ||
| + if( $diffNet !== 0 ) { | ||
| + $dir = $diffNet > 0 ? 'increase' : 'decrease'; | ||
| + $msg .= ', ' . \abs( $diffNet ) . "-line $dir"; | ||
| + } | ||
| + | ||
| + return $msg; | ||
| + } | ||
| +} | ||
| + | ||
| class DiffPage extends BasePage { | ||
| private $currentRepo; | ||
| } | ||
| - $commitsUrl = (new UrlBuilder())->withRepo( $this->currentRepo['safe_name'] )->withAction( 'commits' )->build(); | ||
| + $commitsUrl = (new UrlBuilder()) | ||
| + ->withRepo( $this->currentRepo['safe_name'] ) | ||
| + ->withAction( 'commits' ) | ||
| + ->build(); | ||
| $trail = [ | ||
| [ | ||
| $tpl->assign( 'parent_url', $parentUrl ); | ||
| $tpl->assign( 'parent_sha', $parentSha ); | ||
| - | ||
| - $added = 0; | ||
| - $deleted = 0; | ||
| - $changes = []; | ||
| - | ||
| - foreach( $diffEngine->compare( $this->hash ) as $change ) { | ||
| - foreach( $change['hunks'] as $hunkLine ) { | ||
| - if( $hunkLine['t'] === '+' ) { | ||
| - $added++; | ||
| - } elseif( $hunkLine['t'] === '-' ) { | ||
| - $deleted++; | ||
| - } | ||
| - } | ||
| - $changes[] = $change; | ||
| - } | ||
| + $stats = new DiffStats(); | ||
| - $tpl->assign( 'empty_changes', empty( $changes ) ); | ||
| - $tpl->assign( 'changes', $changes ); | ||
| + $tpl->assign( 'stats', $stats ); | ||
| + $tpl->assign( 'changes', $this->generateChanges( $diffEngine, $stats ) ); | ||
| - $diffNet = $added - $deleted; | ||
| - $deltaMsg = $added . ' line' . ($added !== 1 ? 's' : '') . ' added, ' . | ||
| - $deleted . ' line' . ($deleted !== 1 ? 's' : '') . ' removed'; | ||
| + echo $tpl->render( 'diff.tpl' ); | ||
| + } | ||
| - if( $diffNet !== 0 ) { | ||
| - $direction = $diffNet > 0 ? 'increase' : 'decrease'; | ||
| - $deltaMsg .= ', ' . \abs( $diffNet ) . "-line $direction"; | ||
| + private function generateChanges( | ||
| + GitDiff $diffEngine, | ||
| + DiffStats $stats | ||
| + ): Generator { | ||
| + foreach( $diffEngine->compare( $this->hash ) as $change ) { | ||
| + yield $stats->track( $change ); | ||
| } | ||
| - | ||
| - $tpl->assign( 'delta_msg', $deltaMsg ); | ||
| - | ||
| - echo $tpl->render( 'diff.tpl' ); | ||
| } | ||
| } | ||
| </div> | ||
| + <div class="diff-container" style="order:3"> | ||
| + {foreach $changes as $change} | ||
| + <div class="diff-file"> | ||
| + <div class="diff-header"> | ||
| + <span class="diff-status {if $change.type === 'A'}status-add{elseif $change.type === 'D'}status-del{elseif $change.type === 'M'}status-mod{/if}"> | ||
| + <i class="fa {if $change.type === 'A'}fa-plus-circle{elseif $change.type === 'D'}fa-minus-circle{elseif $change.type === 'M'}fa-pencil-alt{else}fa-file{/if}"></i> | ||
| + </span> | ||
| + <span class="diff-path">{$change.path}</span> | ||
| + </div> | ||
| + | ||
| + {if $change.is_binary} | ||
| + <div class="diff-binary">Binary files differ</div> | ||
| + {else} | ||
| + <div class="diff-content"> | ||
| + <table> | ||
| + <tbody> | ||
| + {foreach $change.hunks as $line} | ||
| + {if $line.t === 'gap'} | ||
| + <tr class="diff-gap"> | ||
| + <td colspan="3"><img src="/images/diff-gap.svg" class="diff-gap-icon" /></td> | ||
| + </tr> | ||
| + {else} | ||
| + {strip} | ||
| + <tr class="{if $line.t === '+'}diff-add{elseif $line.t === '-'}diff-del{else}diff-ctx{/if}"> | ||
| + <td class="diff-num" data-num="{$line.no}"></td> | ||
| + <td class="diff-num" data-num="{$line.nn}"></td> | ||
| + <td class="diff-code"> | ||
| + <span class="diff-marker">{if $line.t === '+'}+{elseif $line.t === '-'}-{else} {/if}</span>{$line.l} | ||
| + </td> | ||
| + </tr> | ||
| + {/strip} | ||
| + {/if} | ||
| + {/foreach} | ||
| + </tbody> | ||
| + </table> | ||
| + </div> | ||
| + {/if} | ||
| + </div> | ||
| + {/foreach} | ||
| + | ||
| + {if $stats->isEmpty()} | ||
| + <div class="empty-state"> | ||
| + <p>No changes detected.</p> | ||
| + </div> | ||
| + {/if} | ||
| + </div> | ||
| + | ||
| <div class="diff-delta" style="order:2"> | ||
| <table class="commit-info-table"> | ||
| <tbody> | ||
| <tr> | ||
| <th class="commit-info-label">Delta</th> | ||
| - <td class="commit-info-value">{$delta_msg}</td> | ||
| + <td class="commit-info-value">{$stats}</td> | ||
| </tr> | ||
| </tbody> | ||
| </table> | ||
| - </div> | ||
| - | ||
| - <div class="diff-container" style="order:3"> | ||
| - {if $empty_changes} | ||
| - <div class="empty-state"> | ||
| - <p>No changes detected.</p> | ||
| - </div> | ||
| - {else} | ||
| - {foreach $changes as $change} | ||
| - <div class="diff-file"> | ||
| - <div class="diff-header"> | ||
| - <span class="diff-status {if $change.type === 'A'}status-add{elseif $change.type === 'D'}status-del{elseif $change.type === 'M'}status-mod{/if}"> | ||
| - <i class="fa {if $change.type === 'A'}fa-plus-circle{elseif $change.type === 'D'}fa-minus-circle{elseif $change.type === 'M'}fa-pencil-alt{else}fa-file{/if}"></i> | ||
| - </span> | ||
| - <span class="diff-path">{$change.path}</span> | ||
| - </div> | ||
| - | ||
| - {if $change.is_binary} | ||
| - <div class="diff-binary">Binary files differ</div> | ||
| - {else} | ||
| - <div class="diff-content"> | ||
| - <table> | ||
| - <tbody> | ||
| - {foreach $change.hunks as $line} | ||
| - {if $line.t === 'gap'} | ||
| - <tr class="diff-gap"> | ||
| - <td colspan="3"><img src="/images/diff-gap.svg" class="diff-gap-icon" /></td> | ||
| - </tr> | ||
| - {else} | ||
| - {strip} | ||
| - <tr class="{if $line.t === '+'}diff-add{elseif $line.t === '-'}diff-del{else}diff-ctx{/if}"> | ||
| - <td class="diff-num" data-num="{$line.no}"></td> | ||
| - <td class="diff-num" data-num="{$line.nn}"></td> | ||
| - <td class="diff-code"> | ||
| - <span class="diff-marker">{if $line.t === '+'}+{elseif $line.t === '-'}-{else} {/if}</span>{$line.l} | ||
| - </td> | ||
| - </tr> | ||
| - {/strip} | ||
| - {/if} | ||
| - {/foreach} | ||
| - </tbody> | ||
| - </table> | ||
| - </div> | ||
| - {/if} | ||
| - </div> | ||
| - {/foreach} | ||
| - {/if} | ||
| </div> | ||
| </div> |
| Author | Dave Jarvis <email> |
|---|---|
| Date | 2026-03-02 12:42:50 GMT-0800 |
| Commit | 6a26f9643ac9dc6fa6be78e30c57f6b1fdd50cba |
| Parent | f56efd3 |
| Delta | 102 lines added, 76 lines removed, 26-line increase |