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

Rich Text Laravel Package

contentful/rich-text

PHP library for parsing and rendering Contentful Rich Text fields. Parses localized rich text JSON into node objects, resolves linked assets/entries via a link resolver, and renders nodes to output with a simple Renderer API. Requires PHP 7.2+ / 8.0+.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require contentful/rich-text

Requires PHP 7.2+ or PHP 8.0+.

  1. Basic Parsing:

    use Contentful\RichText\Parser;
    use Contentful\RichText\LinkResolver\LinkResolverInterface;
    
    // Create a link resolver (e.g., for resolving Contentful entries/assets)
    $linkResolver = new MyCustomLinkResolver();
    
    // Parse rich text data (e.g., from a Contentful entry)
    $parser = new Parser($linkResolver);
    $node = $parser->parseLocalized($richTextData, 'en-US'); // Always use parseLocalized()
    
  2. Basic Rendering:

    use Contentful\RichText\Renderer;
    
    $renderer = new Renderer();
    $html = $renderer->render($node);
    

First Use Case: Rendering a Contentful Entry's Rich Text Field

// In a Laravel controller or service
public function showEntry(Entry $entry)
{
    $richTextData = $entry->getField('body'); // Assume 'body' is a rich text field
    $linkResolver = new ContentfulLinkResolver($entry->getSpaceId());

    $parser = new Parser($linkResolver);
    $node = $parser->parseLocalized($richTextData, app()->getLocale());

    $renderer = new Renderer();
    $html = $renderer->render($node);

    return view('entry.show', ['content' => $html]);
}

Implementation Patterns

1. Link Resolution

  • Pattern: Always use parseLocalized() with a custom LinkResolverInterface to resolve embedded entries/assets.
  • Laravel Integration:
    // Example: Resolve links using Laravel's service container
    $linkResolver = app()->make(ContentfulLinkResolver::class);
    $parser = new Parser($linkResolver);
    
  • Caching: Cache resolved nodes if performance is critical (e.g., via Laravel's cache system).

2. Custom Node Rendering

  • Pattern: Extend default renderers for specific needs (e.g., adding classes, custom markup).
    // Example: Custom renderer for headings
    class CustomHeadingRenderer implements NodeRendererInterface
    {
        public function supports(NodeInterface $node): bool
        {
            return $node instanceof Heading1 || $node instanceof Heading2;
        }
    
        public function render(RendererInterface $renderer, NodeInterface $node, array $context = []): string
        {
            $tag = $node instanceof Heading1 ? 'h1' : 'h2';
            return "<{$tag} class=\"content-heading\">" . $renderer->renderCollection($node->getContent()) . "</{$tag}>";
        }
    }
    
    // Register with the renderer
    $renderer->pushNodeRenderer(new CustomHeadingRenderer());
    

3. Twig/Blade Integration

  • Pattern: Use the TwigExtension or PlatesExtension for templating.
    // Twig example
    $renderer = new Renderer();
    $twig->addExtension(new \Contentful\RichText\Bridge\TwigExtension($renderer));
    
    // Blade example (via Plates)
    $plates = new Plates();
    $plates->loadExtension(new \Contentful\RichText\Bridge\PlatesExtension($renderer));
    
  • Template Usage:
    {# Twig #}
    {{ rich_text_render(node) }}
    
    {# Blade (via Plates) #}
    {!! $this->richTextRender($node) !!}
    

4. Handling Embedded Content

  • Pattern: Enable embedded asset/image rendering explicitly:
    $renderer->enableEmbeddedImageRenderer(true);
    
  • Laravel Example:
    // Resolve embedded assets using Laravel's Storage or Filesystem
    $linkResolver = new ContentfulLinkResolver(
        app('filesystem'),
        config('contentful.space_id')
    );
    

5. Batch Processing

  • Pattern: Parse and render collections efficiently:
    $nodes = $parser->parseCollectionLocalized($richTextData, 'en-US');
    $html = $renderer->renderCollection($nodes);
    

6. Service Provider Integration

  • Pattern: Register the package in Laravel's service provider:
    // app/Providers/ContentfulServiceProvider.php
    public function register()
    {
        $this->app->singleton(Parser::class, function ($app) {
            return new Parser($app->make(LinkResolverInterface::class));
        });
    
        $this->app->singleton(Renderer::class, function ($app) {
            $renderer = new Renderer();
            $renderer->pushNodeRenderer(new CustomHeadingRenderer());
            return $renderer;
        });
    }
    

Gotchas and Tips

Pitfalls

  1. Locale Mismatch:

    • Issue: Forgetting to use parseLocalized() can cause embedded entries/assets to resolve in the wrong locale.
    • Fix: Always pass the correct locale:
      $node = $parser->parseLocalized($data, app()->getLocale());
      
  2. Missing CatchAll Renderer:

    • Issue: The default renderer throws exceptions for unsupported nodes. If you want to ignore unsupported nodes, add:
      $renderer->appendNodeRenderer(new \Contentful\RichText\NodeRenderer\CatchAll());
      
    • Gotcha: Use appendNodeRenderer() (not pushNodeRenderer()) to ensure CatchAll has the lowest priority.
  3. Embedded Asset Rendering:

    • Issue: Embedded assets (e.g., images) require explicit enabling:
      $renderer->enableEmbeddedImageRenderer(true);
      
    • Fix: Configure this in your service provider or renderer initialization.
  4. PHP Version Compatibility:

    • Issue: The package drops support for PHP 7.x in v4.0.0+. Ensure your Laravel app uses PHP 7.2+ or 8.0+.
    • Fix: Update your Laravel version if needed (e.g., Laravel 8+ for PHP 8.0+).
  5. Nested Node Rendering:

    • Issue: Custom renderers must delegate to $renderer->renderCollection() for nested nodes:
      // Wrong: Skipping nested nodes
      return "<div>{$node->getContent()}</div>";
      
      // Correct: Delegating to the renderer
      return "<div>" . $renderer->renderCollection($node->getContent()) . "</div>";
      
  6. Breaking Changes in v4.0.0:

    • Issue: parse() and parseCollection() are deprecated. Use parseLocalized() and parseCollectionLocalized() instead.
    • Fix: Update all parsing calls in your codebase.

Debugging Tips

  1. Inspect Nodes:

    • Use var_dump($node) or dd($node) to inspect the parsed node structure. Each node type (e.g., Heading1, EmbeddedEntryBlock) has specific methods like getContent(), getNodeType(), etc.
  2. Check Renderer Order:

    • If a node isn't rendering as expected, verify the order of registered renderers. Use pushNodeRenderer() for high-priority overrides and appendNodeRenderer() for low-priority fallbacks.
  3. Locale-Specific Issues:

    • If embedded content (e.g., entries/assets) isn't resolving correctly, ensure:
      • The LinkResolver is correctly configured.
      • The locale passed to parseLocalized() matches the content's locale.
  4. Performance:

    • For large rich text fields, cache parsed nodes or renderer outputs:
      $cacheKey = 'rich_text_' . md5(serialize($data) . $locale);
      return Cache::remember($cacheKey, now()->addHours(1), function () use ($parser, $data, $locale) {
          return $parser->parseLocalized($data, $locale);
      });
      

Extension Points

  1. Custom Node Types:

    • Extend the library to support custom Contentful node types (e.g., CustomBlock) by:
      1. Creating a new node class implementing NodeInterface.
      2. Implementing a NodeRendererInterface for it.
      3. Registering the renderer with the Renderer.
  2. Link Resolver:

    • Implement LinkResolverInterface to customize how embedded entries/assets are resolved. Example:
      class ContentfulLinkResolver implements LinkResolverInterface
      {
          public function resolve(string $id, string $locale, string $type): ?array
          {
              // Fetch from Contentful API or cache
              return $this->contentfulClient->getEntry($id, $locale);
          }
      }
      
  3. Templating Engines:

    • The package supports Twig and Plates out-of-the-box. For other engines (e.g., Laravel Blade), create a custom extension:
      class BladeExtension
      {
          public function __construct(private Renderer $renderer) {}
      
          public function render(Node
      
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
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