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

Dindent Laravel Package

schleuse/dindent

Dindent is a regex-based HTML indenter/beautifier for development and testing. It formats template-generated markup with readable indentation without sanitizing, fixing, or rebuilding the document like DOM/Tidy—useful for debugging messy HTML output.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation (PHP 8.2+ required):

    composer require schleuse/dindent:^3.0
    

    No additional configuration is required—just autoload via Composer.

  2. First Use Case (New: One-line mode):

    use Schleuse\Dindent\Dindent;
    
    $dirtyHtml = '<div><span>Hello</span></div><p>World</p>';
    
    // Standard indentation
    $indented = Dindent::indent($dirtyHtml);
    // Outputs:
    // <div>
    //   <span>
    //     Hello
    //   </span>
    // </div>
    // <p>
    //   World
    // </p>
    
    // New: One-line mode (compact output)
    $oneLine = Dindent::indent($dirtyHtml, ['oneLine' => true]);
    // Outputs:
    // <div><span>Hello</span></div><p>World</p>
    
  3. Where to Look First:

    • Updated Source Code (check v3.0.0 branch for new features).
    • Dindent::indent() method docs (now supports oneLine, skipScripts, and handles <style> tags).
    • New Test Cases for edge cases (e.g., <pre>, multi-line comments).

Implementation Patterns

Workflows

  1. Debugging HTML Responses (New: One-line mode for APIs):

    // In a controller or middleware (compact for APIs)
    $responseHtml = $response->getContent();
    $indentedHtml = Dindent::indent($responseHtml, ['oneLine' => $request->wantsJson()]);
    Log::debug('Indented HTML:', ['html' => $indentedHtml]);
    
  2. Testing Views (New: Handle <style> and <pre> tags):

    // In a PHPUnit test (assert style tags are preserved)
    $viewOutput = $this->get('/some-route')->getContent();
    $indented = Dindent::indent($viewOutput);
    $this->assertStringContainsString('<style>', $indented);
    $this->assertStringContainsString('  <pre>', $indented); // Indented but not broken
    
  3. Pre-commit Hooks (New: Optimized for speed):

    // In app/Console/Kernel.php (faster with one-line mode)
    Artisan::command('dindent:fix', function () {
        $files = $this->argument('paths');
        foreach ($files as $file) {
            $html = file_get_contents($file);
            file_put_contents($file, Dindent::indent($html, ['oneLine' => true]));
        }
    });
    

Integration Tips

  • Blade Directives (New: Support for <style> and one-line mode):

    Blade::directive('indent', function ($expression) {
        return "<?php echo \\Schleuse\\Dindent\\Dindent::indent({$expression}, ['oneLine' => false]); ?>";
    });
    

    Usage in Blade:

    @indent($unformattedHtml) <!-- Standard indentation -->
    @php echo \Schleuse\Dindent\Dindent::indent($html, ['oneLine' => true]); @endphp <!-- Compact -->
    
  • API Responses (New: Dynamic indentation based on request):

    public function handle($request, Closure $next)
    {
        $response = $next($request);
        if ($response->headers->get('Content-Type') === 'text/html') {
            $options = $request->wantsJson() ? ['oneLine' => true] : [];
            $response->setContent(Dindent::indent($response->getContent(), $options));
        }
        return $response;
    }
    
  • Artisan Commands (New: Extract <pre> and <textarea>):

    Artisan::command('dindent:fix', function () {
        $files = $this->argument('paths');
        foreach ($files as $file) {
            $html = file_get_contents($file);
            $indented = Dindent::indent($html, [
                'oneLine' => false,
                'extractPre' => true, // Preserve <pre> content
            ]);
            file_put_contents($file, $indented);
        }
    });
    

Gotchas and Tips

Pitfalls

  1. PHP 8.2 Requirement (⚠️ Breaking):

    • Update php.ini or use a PHP 8.2+ runtime (e.g., Laravel Valet, Docker, or php@8.2).
    • Check CI/CD pipelines (e.g., GitHub Actions, GitLab CI) for PHP version compatibility.
  2. Self-Closing Tags in One-Line Mode: Dindent now preserves self-closing tags (e.g., <img/>) even in compact mode:

    $html = '<div><img src="x" /><span>Text</span></div>';
    Dindent::indent($html, ['oneLine' => true]);
    // Outputs: <div><img src="x" /><span>Text</span></div>
    
  3. <style> and <script> Handling:

    • Fixed: <style> tags are now properly indented (previously ignored).
    • Warning: Complex CSS/JS may break if indented. Use skipScripts to opt-out:
      Dindent::indent($html, ['skipScripts' => true]);
      
  4. <pre> and <textarea> Extraction:

    • New: Content inside <pre> or <textarea> is preserved as-is (not indented).
    • Gotcha: If you want to indent <pre> content, use extractPre: false:
      Dindent::indent($html, ['extractPre' => false]);
      
  5. Performance in One-Line Mode:

    • Optimized: One-line mode is ~30% faster for large HTML strings (benchmarked in v3.0.0).
    • Caveat: Still avoid processing >5MB files in loops.

Debugging

  • Edge Cases (New: Multi-line comments and <pre>): Test with:

    $html = <<<HTML
    <div>
      <!--
        Multi-line
        comment
      -->
      <pre>  Preserve this indentation!
      </pre>
    </div>
    HTML;
    $indented = Dindent::indent($html);
    // Multi-line comments and <pre> content remain intact.
    
  • Logging Differences: Compare oneLine vs. standard output:

    $original = '<div>Test</div>';
    $standard = Dindent::indent($original);
    $compact = Dindent::indent($original, ['oneLine' => true]);
    $this->assertNotEquals($standard, $compact, 'Modes produce different outputs!');
    

Config Quirks

  • Custom Indentation with One-Line Mode: Override the class to combine custom indentation with new features:

    class CustomDindent extends Dindent {
        public static function indent($html, array $options = []) {
            $options['indent'] = '    '; // 4 spaces
            $options['oneLine'] = false;
            return parent::indent($html, $options);
        }
    }
    
  • Extension Points (New: extractPre and skipScripts): Use flags to control extraction behavior:

    Dindent::indent($html, [
        'extractPre' => true,   // Default: preserve <pre> content
        'skipScripts' => false, // Default: indent <script> and <style>
    ]);
    

Pro Tips

  1. Visual Diffs for One-Line Mode: Compare compact vs. standard output:

    echo "Standard:"; echo "$standardHtml" | diff -u - <(echo "$compactHtml")
    
  2. CI Integration (New: Test both modes):

    public function test_indentation_modes()
    {
        $html = '<div><p>Test</p></div>';
        $standard = Dindent::indent($html);
        $compact = Dindent::indent($html, ['oneLine' => true]);
        $this->assertStringContainsString("\n  <p>", $standard);
        $this->assertStringNotContainsString("\n", $compact);
    }
    
  3. Partial Indentation with <pre>: Indent everything except <pre> blocks:

    preg_match_all('/<pre>(.*?)<\/pre>/s', $html, $preBlocks);
    $indented = Dindent::indent($html, ['extractPre' => true]);
    foreach ($preBlocks[1] as $i => $block) {
        $indented =
    
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.
amashukov/lnd-client-php
althinect/enum-permission
andydefer/laravel-actions
aimeos/prisma
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