Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Finediff Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require cogpowered/finediff
    

    (Note: The package is archived; use d4h/php-finediff for active maintenance.)

  2. 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>).

  3. First Use Case:

    • Inline Text Edits: Highlight changes in user-generated content (e.g., CMS edits, comments).
    • Version Comparison: Display diffs between database records or API responses.

Implementation Patterns

Core Workflows

  1. Granularity Control:

    • Character-level (default): Fine-grained inline edits.
      $diff = new Diff(); // Default: Character granularity
      
    • Word-level: Whole-word replacements.
      $granularity = new \cogpowered\FineDiff\Granularity\Word();
      $diff = new Diff($granularity);
      
    • Line-level: For multi-line text blocks (extend Granularity trait).
  2. Opcodes for Programmatic Use:

    • Generate diff instructions (e.g., c7d3i3:new = copy 7 chars, delete 3, insert 3).
      $opcodes = $diff->getOpcodes('old', 'new');
      
    • Replay opcodes to transform text:
      $render = new \cogpowered\FineDiff\Render\Text();
      $transformed = $render->process('old', $opcodes);
      
  3. Integration with Laravel:

    • Blade Templates: Render diffs in views:
      {{ $diff->render(old('content'), $request->input('content')) }}
      
    • Form Requests: Validate changes via opcodes:
      $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.)
  4. API Responses:

    • Return structured diffs as JSON:
      return response()->json([
          'old' => $oldText,
          'new' => $newText,
          'diff' => $diff->getOpcodes($oldText, $newText),
      ]);
      

Gotchas and Tips

Pitfalls

  1. Backward Incompatibility:

    • Version 0.3.x changed opcode encoding. Avoid upgrading if storing opcodes in a database.
    • Workaround: Use d4h/php-finediff (fork) for active development.
  2. Performance with Large Texts:

    • Opcodes grow linearly with text length. For >10KB texts:
      • Use line-level granularity to reduce opcode size.
      • Cache opcodes if regenerating frequently.
  3. HTML Output Quirks:

    • Nested tags (e.g., <ins><del>) may break styling. Sanitize output:
      $html = $diff->render($old, $new);
      $cleanHtml = Str::of($html)->replaceMatches('/<ins><del>/', '<span class="conflict">');
      
  4. Edge Cases:

    • Empty Strings: getOpcodes('', '') returns "" (valid but empty).
    • Unicode: Works but may produce unexpected opcodes for multi-byte chars. Normalize text first:
      $normalizedOld = mb_strtolower($old, 'UTF-8');
      $normalizedNew = mb_strtolower($new, 'UTF-8');
      

Debugging Tips

  1. Inspect Opcodes:

    • Decode opcodes manually to verify logic:
      function decodeOpcodes(string $opcodes): array {
          preg_match_all('/(\d+)([cdi])/', $opcodes, $matches);
          return array_map(null, $matches[1], $matches[2]);
      }
      
  2. Logging:

    • Log opcodes for complex diffs to debug:
      \Log::debug('Diff Opcodes', ['opcodes' => $diff->getOpcodes($old, $new)]);
      
  3. Testing:

    • Test with edge cases:
      $this->assertEquals('c0i5:hello', $diff->getOpcodes('', 'hello'));
      $this->assertEquals('', $diff->getOpcodes('abc', 'abc'));
      

Extension Points

  1. Custom Granularity:

    • Extend \cogpowered\FineDiff\Granularity\Base for sentence/paragraph-level diffs:
      class SentenceGranularity extends Base {
          protected function split(string $text): array {
              return preg_split('/[.!?]+/', $text);
          }
      }
      
  2. Renderers:

    • Create custom renderers (e.g., Markdown, JSON):
      class JsonRenderer implements \cogpowered\FineDiff\Render\RendererInterface {
          public function process(string $original, string $opcodes): string {
              return json_encode($this->parseOpcodes($opcodes));
          }
      }
      
  3. Laravel Service Provider:

    • Bind the diff engine for dependency injection:
      $this->app->singleton(Diff::class, function ($app) {
          return new Diff(new WordGranularity());
      });
      
    • Use in controllers:
      public function update(Request $request) {
          $diff = app(Diff::class);
          // ...
      }
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
aimeos/prisma
besmartand-pro/php-quality-config
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor
spatie/laravel-javascript-views