cogpowered/finediff
FineDiff (archived; see d4h/php-finediff) is a PHP library for generating and applying fine-grained diffs between strings. Render changes as HTML or text, choose character/word granularity, and work with compact opcode instructions to transform content.
Installation:
composer require cogpowered/finediff
(Note: The package is archived; use d4h/php-finediff for active maintenance.)
Basic Usage:
use cogpowered\FineDiff\Diff;
$diff = new Diff();
echo $diff->render('old text', 'new text');
Outputs HTML-wrapped diffs (e.g., <ins>new</ins><del>old</del>).
First Use Case:
Granularity Control:
$diff = new Diff(); // Default: Character granularity
$granularity = new \cogpowered\FineDiff\Granularity\Word();
$diff = new Diff($granularity);
Granularity trait).Opcodes for Programmatic Use:
c7d3i3:new = copy 7 chars, delete 3, insert 3).
$opcodes = $diff->getOpcodes('old', 'new');
$render = new \cogpowered\FineDiff\Render\Text();
$transformed = $render->process('old', $opcodes);
Integration with Laravel:
{{ $diff->render(old('content'), $request->input('content')) }}
$opcodes = $diff->getOpcodes($model->content, $request->content);
$this->validate(['content' => ['required', 'diff_valid', 'rule:max_opcodes:50']]);
(Extend Validator with a custom rule for opcode constraints.)API Responses:
return response()->json([
'old' => $oldText,
'new' => $newText,
'diff' => $diff->getOpcodes($oldText, $newText),
]);
Backward Incompatibility:
0.3.x changed opcode encoding. Avoid upgrading if storing opcodes in a database.d4h/php-finediff (fork) for active development.Performance with Large Texts:
HTML Output Quirks:
<ins><del>) may break styling. Sanitize output:
$html = $diff->render($old, $new);
$cleanHtml = Str::of($html)->replaceMatches('/<ins><del>/', '<span class="conflict">');
Edge Cases:
getOpcodes('', '') returns "" (valid but empty).$normalizedOld = mb_strtolower($old, 'UTF-8');
$normalizedNew = mb_strtolower($new, 'UTF-8');
Inspect Opcodes:
function decodeOpcodes(string $opcodes): array {
preg_match_all('/(\d+)([cdi])/', $opcodes, $matches);
return array_map(null, $matches[1], $matches[2]);
}
Logging:
\Log::debug('Diff Opcodes', ['opcodes' => $diff->getOpcodes($old, $new)]);
Testing:
$this->assertEquals('c0i5:hello', $diff->getOpcodes('', 'hello'));
$this->assertEquals('', $diff->getOpcodes('abc', 'abc'));
Custom Granularity:
\cogpowered\FineDiff\Granularity\Base for sentence/paragraph-level diffs:
class SentenceGranularity extends Base {
protected function split(string $text): array {
return preg_split('/[.!?]+/', $text);
}
}
Renderers:
class JsonRenderer implements \cogpowered\FineDiff\Render\RendererInterface {
public function process(string $original, string $opcodes): string {
return json_encode($this->parseOpcodes($opcodes));
}
}
Laravel Service Provider:
$this->app->singleton(Diff::class, function ($app) {
return new Diff(new WordGranularity());
});
public function update(Request $request) {
$diff = app(Diff::class);
// ...
}
How can I help you explore Laravel packages today?