From f165bd059e82ffc2c748a6b54b97b30b1c4053ee Mon Sep 17 00:00:00 2001 From: Ahmed Darrazi Date: Thu, 1 Jan 2026 21:33:19 +0100 Subject: [PATCH] feat: highlight changed lines in script diffs --- .../entries/normalized-diff.blade.php | 127 +++++++++++++++--- .../ScriptPoliciesNormalizedDisplayTest.php | 5 +- 2 files changed, 115 insertions(+), 17 deletions(-) diff --git a/resources/views/filament/infolists/entries/normalized-diff.blade.php b/resources/views/filament/infolists/entries/normalized-diff.blade.php index 4d9a154..844df9d 100644 --- a/resources/views/filament/infolists/entries/normalized-diff.blade.php +++ b/resources/views/filament/infolists/entries/normalized-diff.blade.php @@ -104,6 +104,94 @@ return null; } }; + + $splitLines = static function (string $text): array { + $text = str_replace(["\r\n", "\r"], "\n", $text); + + return $text === '' ? [] : explode("\n", $text); + }; + + $myersLineDiff = static function (array $a, array $b): array { + $n = count($a); + $m = count($b); + $max = $n + $m; + + $v = [1 => 0]; + $trace = []; + + for ($d = 0; $d <= $max; $d++) { + $trace[$d] = $v; + + for ($k = -$d; $k <= $d; $k += 2) { + $kPlus = $v[$k + 1] ?? 0; + $kMinus = $v[$k - 1] ?? 0; + + if ($k === -$d || ($k !== $d && $kMinus < $kPlus)) { + $x = $kPlus; + } else { + $x = $kMinus + 1; + } + + $y = $x - $k; + + while ($x < $n && $y < $m && $a[$x] === $b[$y]) { + $x++; + $y++; + } + + $v[$k] = $x; + + if ($x >= $n && $y >= $m) { + break 2; + } + } + } + + $ops = []; + $x = $n; + $y = $m; + + for ($d = count($trace) - 1; $d >= 0; $d--) { + $v = $trace[$d]; + $k = $x - $y; + + $kPlus = $v[$k + 1] ?? 0; + $kMinus = $v[$k - 1] ?? 0; + + if ($k === -$d || ($k !== $d && $kMinus < $kPlus)) { + $prevK = $k + 1; + } else { + $prevK = $k - 1; + } + + $prevX = $v[$prevK] ?? 0; + $prevY = $prevX - $prevK; + + while ($x > $prevX && $y > $prevY) { + $ops[] = ['type' => 'equal', 'line' => $a[$x - 1]]; + $x--; + $y--; + } + + if ($d === 0) { + break; + } + + if ($x === $prevX) { + $ops[] = ['type' => 'insert', 'line' => $b[$y - 1] ?? '']; + $y--; + } else { + $ops[] = ['type' => 'delete', 'line' => $a[$x - 1] ?? '']; + $x--; + } + } + + return array_reverse($ops); + }; + + $scriptLineDiff = static function (string $fromText, string $toText) use ($splitLines, $myersLineDiff): array { + return $myersLineDiff($splitLines($fromText), $splitLines($toText)); + }; @endphp
@@ -159,8 +247,7 @@ $toText = $stringify($to); $isScriptContent = $canHighlightScripts($policyType) && $isScriptKey($name); - $fromHighlight = $isScriptContent ? $highlight($policyType, (string) $fromText) : null; - $toHighlight = $isScriptContent ? $highlight($policyType, (string) $toText) : null; + $ops = $isScriptContent ? $scriptLineDiff((string) $fromText, (string) $toText) : []; @endphp
@@ -168,17 +255,21 @@
From - @if ($isExpandable($from)) + @if ($isScriptContent || $isExpandable($from))
View - @if (is_string($fromHighlight) && $fromHighlight !== '') - @once - @include('filament.partials.torchlight-dark-overrides') - @endonce - -
{!! $fromHighlight !!}
+ @if ($isScriptContent) +
+@foreach ($ops as $op)
+@if ($op['type'] === 'equal')
+{{ $op['line'] }}
+@elseif ($op['type'] === 'delete')
+- {{ $op['line'] }}
+@endif
+@endforeach
+                                                                
@else
{{ $fromText }}
@endif @@ -189,17 +280,21 @@
To - @if ($isExpandable($to)) + @if ($isScriptContent || $isExpandable($to))
View - @if (is_string($toHighlight) && $toHighlight !== '') - @once - @include('filament.partials.torchlight-dark-overrides') - @endonce - -
{!! $toHighlight !!}
+ @if ($isScriptContent) +
+@foreach ($ops as $op)
+@if ($op['type'] === 'equal')
+{{ $op['line'] }}
+@elseif ($op['type'] === 'insert')
++ {{ $op['line'] }}
+@endif
+@endforeach
+                                                                
@else
{{ $toText }}
@endif diff --git a/tests/Feature/Filament/ScriptPoliciesNormalizedDisplayTest.php b/tests/Feature/Filament/ScriptPoliciesNormalizedDisplayTest.php index 092ec9e..f2f9f78 100644 --- a/tests/Feature/Filament/ScriptPoliciesNormalizedDisplayTest.php +++ b/tests/Feature/Filament/ScriptPoliciesNormalizedDisplayTest.php @@ -116,7 +116,10 @@ $this->get($url.'?tab=diff') ->assertSuccessful() - ->assertSee('torchlight', false); + ->assertSeeText("- Write-Host 'one'") + ->assertSeeText("+ Write-Host 'two'") + ->assertSee('bg-danger-50', false) + ->assertSee('bg-success-50', false); $originalEnv !== false ? putenv("INTUNE_TENANT_ID={$originalEnv}")