feat: highlight changed lines in script diffs
This commit is contained in:
parent
2c1ee814ee
commit
f165bd059e
@ -104,6 +104,94 @@
|
|||||||
return null;
|
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
|
@endphp
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
@ -159,8 +247,7 @@
|
|||||||
$toText = $stringify($to);
|
$toText = $stringify($to);
|
||||||
|
|
||||||
$isScriptContent = $canHighlightScripts($policyType) && $isScriptKey($name);
|
$isScriptContent = $canHighlightScripts($policyType) && $isScriptKey($name);
|
||||||
$fromHighlight = $isScriptContent ? $highlight($policyType, (string) $fromText) : null;
|
$ops = $isScriptContent ? $scriptLineDiff((string) $fromText, (string) $toText) : [];
|
||||||
$toHighlight = $isScriptContent ? $highlight($policyType, (string) $toText) : null;
|
|
||||||
@endphp
|
@endphp
|
||||||
<div class="grid grid-cols-1 gap-2 sm:grid-cols-3">
|
<div class="grid grid-cols-1 gap-2 sm:grid-cols-3">
|
||||||
<div class="text-sm font-medium text-gray-900 dark:text-white">
|
<div class="text-sm font-medium text-gray-900 dark:text-white">
|
||||||
@ -168,17 +255,21 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="text-sm text-gray-600 dark:text-gray-300">
|
<div class="text-sm text-gray-600 dark:text-gray-300">
|
||||||
<span class="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">From</span>
|
<span class="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">From</span>
|
||||||
@if ($isExpandable($from))
|
@if ($isScriptContent || $isExpandable($from))
|
||||||
<details class="mt-1">
|
<details class="mt-1">
|
||||||
<summary class="cursor-pointer text-sm text-gray-700 dark:text-gray-200">
|
<summary class="cursor-pointer text-sm text-gray-700 dark:text-gray-200">
|
||||||
View
|
View
|
||||||
</summary>
|
</summary>
|
||||||
@if (is_string($fromHighlight) && $fromHighlight !== '')
|
@if ($isScriptContent)
|
||||||
@once
|
<pre class="mt-2 overflow-x-auto text-xs text-gray-800 dark:text-gray-200 whitespace-pre">
|
||||||
@include('filament.partials.torchlight-dark-overrides')
|
@foreach ($ops as $op)
|
||||||
@endonce
|
@if ($op['type'] === 'equal')
|
||||||
|
{{ $op['line'] }}
|
||||||
<div class="mt-2 overflow-x-auto">{!! $fromHighlight !!}</div>
|
@elseif ($op['type'] === 'delete')
|
||||||
|
<span class="block bg-danger-50 text-danger-700 dark:bg-danger-950/40 dark:text-danger-200">- {{ $op['line'] }}</span>
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
|
</pre>
|
||||||
@else
|
@else
|
||||||
<pre class="mt-2 overflow-x-auto text-xs text-gray-800 dark:text-gray-200">{{ $fromText }}</pre>
|
<pre class="mt-2 overflow-x-auto text-xs text-gray-800 dark:text-gray-200">{{ $fromText }}</pre>
|
||||||
@endif
|
@endif
|
||||||
@ -189,17 +280,21 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="text-sm text-gray-600 dark:text-gray-300">
|
<div class="text-sm text-gray-600 dark:text-gray-300">
|
||||||
<span class="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">To</span>
|
<span class="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">To</span>
|
||||||
@if ($isExpandable($to))
|
@if ($isScriptContent || $isExpandable($to))
|
||||||
<details class="mt-1">
|
<details class="mt-1">
|
||||||
<summary class="cursor-pointer text-sm text-gray-700 dark:text-gray-200">
|
<summary class="cursor-pointer text-sm text-gray-700 dark:text-gray-200">
|
||||||
View
|
View
|
||||||
</summary>
|
</summary>
|
||||||
@if (is_string($toHighlight) && $toHighlight !== '')
|
@if ($isScriptContent)
|
||||||
@once
|
<pre class="mt-2 overflow-x-auto text-xs text-gray-800 dark:text-gray-200 whitespace-pre">
|
||||||
@include('filament.partials.torchlight-dark-overrides')
|
@foreach ($ops as $op)
|
||||||
@endonce
|
@if ($op['type'] === 'equal')
|
||||||
|
{{ $op['line'] }}
|
||||||
<div class="mt-2 overflow-x-auto">{!! $toHighlight !!}</div>
|
@elseif ($op['type'] === 'insert')
|
||||||
|
<span class="block bg-success-50 text-success-700 dark:bg-success-950/40 dark:text-success-200">+ {{ $op['line'] }}</span>
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
|
</pre>
|
||||||
@else
|
@else
|
||||||
<pre class="mt-2 overflow-x-auto text-xs text-gray-800 dark:text-gray-200">{{ $toText }}</pre>
|
<pre class="mt-2 overflow-x-auto text-xs text-gray-800 dark:text-gray-200">{{ $toText }}</pre>
|
||||||
@endif
|
@endif
|
||||||
|
|||||||
@ -116,7 +116,10 @@
|
|||||||
|
|
||||||
$this->get($url.'?tab=diff')
|
$this->get($url.'?tab=diff')
|
||||||
->assertSuccessful()
|
->assertSuccessful()
|
||||||
->assertSee('torchlight', false);
|
->assertSeeText("- Write-Host 'one'")
|
||||||
|
->assertSeeText("+ Write-Host 'two'")
|
||||||
|
->assertSee('bg-danger-50', false)
|
||||||
|
->assertSee('bg-success-50', false);
|
||||||
|
|
||||||
$originalEnv !== false
|
$originalEnv !== false
|
||||||
? putenv("INTUNE_TENANT_ID={$originalEnv}")
|
? putenv("INTUNE_TENANT_ID={$originalEnv}")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user