From 72acc8db423096e3d4f422251dc54f0045db5e13 Mon Sep 17 00:00:00 2001 From: Ahmed Darrazi Date: Thu, 1 Jan 2026 22:54:23 +0100 Subject: [PATCH] feat: fullscreen script diff with scroll sync --- .../entries/normalized-diff.blade.php | 285 +++++++++++++++--- specs/013-scripts-management/tasks.md | 1 + .../ScriptPoliciesNormalizedDisplayTest.php | 1 + 3 files changed, 241 insertions(+), 46 deletions(-) diff --git a/resources/views/filament/infolists/entries/normalized-diff.blade.php b/resources/views/filament/infolists/entries/normalized-diff.blade.php index 80f8361..a8d45a8 100644 --- a/resources/views/filament/infolists/entries/normalized-diff.blade.php +++ b/resources/views/filament/infolists/entries/normalized-diff.blade.php @@ -282,6 +282,51 @@ $isScriptContent = $canHighlightScripts($policyType) && $isScriptKey($name); $ops = $isScriptContent ? $scriptLineDiff((string) $fromText, (string) $toText) : []; $useTorchlight = $isScriptContent && class_exists(\Torchlight\Engine\Engine::class); + + $rows = []; + if ($isScriptContent) { + $count = count($ops); + + for ($i = 0; $i < $count; $i++) { + $op = $ops[$i]; + $next = $ops[$i + 1] ?? null; + $type = $op['type'] ?? null; + $line = (string) ($op['line'] ?? ''); + + if ($type === 'equal') { + $rows[] = [ + 'left' => ['type' => 'equal', 'line' => $line], + 'right' => ['type' => 'equal', 'line' => $line], + ]; + continue; + } + + if ($type === 'delete' && is_array($next) && ($next['type'] ?? null) === 'insert') { + $rows[] = [ + 'left' => ['type' => 'delete', 'line' => $line], + 'right' => ['type' => 'insert', 'line' => (string) ($next['line'] ?? '')], + ]; + $i++; + continue; + } + + if ($type === 'delete') { + $rows[] = [ + 'left' => ['type' => 'delete', 'line' => $line], + 'right' => ['type' => 'blank', 'line' => ''], + ]; + continue; + } + + if ($type === 'insert') { + $rows[] = [ + 'left' => ['type' => 'blank', 'line' => ''], + 'right' => ['type' => 'insert', 'line' => $line], + ]; + continue; + } + } + } @endphp
@@ -291,7 +336,7 @@ @if ($isScriptContent)
Script -
+
View @@ -307,54 +352,13 @@ After + + + ⤢ Fullscreen +
- @php - $rows = []; - $count = count($ops); - - for ($i = 0; $i < $count; $i++) { - $op = $ops[$i]; - $next = $ops[$i + 1] ?? null; - $type = $op['type'] ?? null; - $line = (string) ($op['line'] ?? ''); - - if ($type === 'equal') { - $rows[] = [ - 'left' => ['type' => 'equal', 'line' => $line], - 'right' => ['type' => 'equal', 'line' => $line], - ]; - continue; - } - - if ($type === 'delete' && is_array($next) && ($next['type'] ?? null) === 'insert') { - $rows[] = [ - 'left' => ['type' => 'delete', 'line' => $line], - 'right' => ['type' => 'insert', 'line' => (string) ($next['line'] ?? '')], - ]; - $i++; - continue; - } - - if ($type === 'delete') { - $rows[] = [ - 'left' => ['type' => 'delete', 'line' => $line], - 'right' => ['type' => 'blank', 'line' => ''], - ]; - continue; - } - - if ($type === 'insert') { - $rows[] = [ - 'left' => ['type' => 'blank', 'line' => ''], - 'right' => ['type' => 'insert', 'line' => $line], - ]; - continue; - } - } - @endphp -
Old
@@ -476,6 +480,195 @@ @endif
+ +
+
+
+
+
Script diff
+
+ + Close + +
+
+ +
+
+
+ + Diff + + + Before + + + After + +
+ +
+
+
+
Old
+
@php
+foreach ($rows as $row) {
+    $left = $row['left'];
+    $leftType = $left['type'];
+    $leftLine = (string) ($left['line'] ?? '');
+
+    $leftHighlighted = $useTorchlight ? $highlightInline($policyType, $leftLine) : null;
+    $leftRendered = (is_string($leftHighlighted) && $leftHighlighted !== '') ? $leftHighlighted : e($leftLine);
+
+    if ($leftType === 'equal') {
+        if ($useTorchlight) {
+            @endphp
+            @once
+                @include('filament.partials.torchlight-dark-overrides')
+            @endonce
+            @php
+        }
+
+        echo $leftRendered."\n";
+        continue;
+    }
+
+    if ($leftType === 'delete') {
+        if ($useTorchlight) {
+            @endphp
+            @once
+                @include('filament.partials.torchlight-dark-overrides')
+            @endonce
+            @php
+        }
+
+        echo '- '.$leftRendered."\n";
+        continue;
+    }
+
+    echo "\n";
+}
+@endphp
+
+ +
+
New
+
@php
+foreach ($rows as $row) {
+    $right = $row['right'];
+    $rightType = $right['type'];
+    $rightLine = (string) ($right['line'] ?? '');
+
+    $rightHighlighted = $useTorchlight ? $highlightInline($policyType, $rightLine) : null;
+    $rightRendered = (is_string($rightHighlighted) && $rightHighlighted !== '') ? $rightHighlighted : e($rightLine);
+
+    if ($rightType === 'equal') {
+        if ($useTorchlight) {
+            @endphp
+            @once
+                @include('filament.partials.torchlight-dark-overrides')
+            @endonce
+            @php
+        }
+
+        echo $rightRendered."\n";
+        continue;
+    }
+
+    if ($rightType === 'insert') {
+        if ($useTorchlight) {
+            @endphp
+            @once
+                @include('filament.partials.torchlight-dark-overrides')
+            @endonce
+            @php
+        }
+
+        echo '+ '.$rightRendered."\n";
+        continue;
+    }
+
+    echo "\n";
+}
+@endphp
+
+
+
+ +
+
Before
+ @php + $highlightedBeforeFullscreen = $useTorchlight ? $highlight($policyType, (string) $fromText) : null; + @endphp + + @if (is_string($highlightedBeforeFullscreen) && $highlightedBeforeFullscreen !== '') + @once + @include('filament.partials.torchlight-dark-overrides') + @endonce + +
{!! $highlightedBeforeFullscreen !!}
+ @else +
{{ (string) $fromText }}
+ @endif +
+ +
+
After
+ @php + $highlightedAfterFullscreen = $useTorchlight ? $highlight($policyType, (string) $toText) : null; + @endphp + + @if (is_string($highlightedAfterFullscreen) && $highlightedAfterFullscreen !== '') + @once + @include('filament.partials.torchlight-dark-overrides') + @endonce + +
{!! $highlightedAfterFullscreen !!}
+ @else +
{{ (string) $toText }}
+ @endif +
+
+
+
+
@else diff --git a/specs/013-scripts-management/tasks.md b/specs/013-scripts-management/tasks.md index 332d7c8..92d99ee 100644 --- a/specs/013-scripts-management/tasks.md +++ b/specs/013-scripts-management/tasks.md @@ -22,6 +22,7 @@ ## Phase 4: Script Content Display (Safe) - [x] T010 Hide script content behind a Show/Hide button (collapsed by default). - [x] T011 Highlight script content in Normalized Diff view (From/To). - [x] T012 Enable Torchlight highlighting in Diff + Before/After views. +- [x] T013 Add “Fullscreen” overlay for script diffs (scroll sync). ## Open TODOs (Follow-up) - None yet. diff --git a/tests/Feature/Filament/ScriptPoliciesNormalizedDisplayTest.php b/tests/Feature/Filament/ScriptPoliciesNormalizedDisplayTest.php index f2f9f78..9db3154 100644 --- a/tests/Feature/Filament/ScriptPoliciesNormalizedDisplayTest.php +++ b/tests/Feature/Filament/ScriptPoliciesNormalizedDisplayTest.php @@ -116,6 +116,7 @@ $this->get($url.'?tab=diff') ->assertSuccessful() + ->assertSeeText('Fullscreen') ->assertSeeText("- Write-Host 'one'") ->assertSeeText("+ Write-Host 'two'") ->assertSee('bg-danger-50', false)