Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

kwaanonline's avatar

GrahamCampbell/Laravel-Markdown Extensions problem

I've added GrahamCampbell/Laravel-Markdown to a small community site that I'm building so that non-technical users can publish updates using Markdown. To prevent formatting issues, I need to add CSS classes to all image tags so I've created an extension (CustomImageRenderer.php) and registered it in the config file

'extensions' => ['App\Commonmark\CustomImageRenderer'],

That's working fine because it initially threw a lot of syntax issues that needed fixing. It's also listed as an extension in Environment, but not as an inlineRenderer.

I cannot, for the life of me, figure out where to put the call to add it correctly as an inlineRenderer - (from http://commonmark.thephpleague.com/customization/inline-rendering/)

$environment = Environment::createCommonMarkEnvironment();
$environment->addInlineRenderer('League\CommonMark\Inline\Element\Image', new CustomImageRenderer());

This creates a new Environment instance - I need to access the already instantiated Environment instance. I feel like I'm missing something really simple, but this has stumped me for far too long.

0 likes
1 reply
kwaanonline's avatar

Ok - no responses so I left it and came back. The short answer is you need to extend MarkdownServiceProvider and register the custom renderer at the end of the register() function:

CustomInlineRenderer.php - which replaces default rendering and (in this case) adds two Bootstrap classes to image tags:

<?php

namespace App\Commonmark;
use League\CommonMark\Extension\Extension;
use League\CommonMark\Inline\Renderer\InlineRendererInterface;
use League\CommonMark\ElementRendererInterface;
use League\CommonMark\HtmlElement;
use League\CommonMark\Inline\Element\AbstractInline;
use League\CommonMark\Environment;

class CustomImageRenderer extends Extension implements InlineRendererInterface {
      
    public function render( AbstractInline $inline, ElementRendererInterface $htmlRenderer) {
        
        if (!($inline instanceof \League\CommonMark\Inline\Element\Image)) {
            throw new \InvalidArgumentException('Incompatible inline type: ' . get_class($inline));
        }

        $attrs = [];
        foreach ($inline->getData('attributes', []) as $key => $value) {
            $attrs[$key] = $htmlRenderer->escape($value, true);
        }
        
        // Add on the class we need:
        //$attrs['class'] = $htmlRenderer->escape('image-rounded col-xs-12 col-lg-10 col-lg-offset-1', true);
        $attrs['class'] = $htmlRenderer->escape('image-rounded img-responsive', true);

        $attrs['src'] = $htmlRenderer->escape($inline->getUrl(), true);

        $alt = $htmlRenderer->renderInlines($inline->children());
        $alt = preg_replace('/\<[^>]*alt="([^"]*)"[^>]*\>/', '$1', $alt);
        $attrs['alt'] = preg_replace('/\<[^>]*\>/', '', $alt);

        if (isset($inline->data['title'])) {
            $attrs['title'] = $htmlRenderer->escape($inline->data['title'], true);
        }

        return new HtmlElement('img', $attrs, '', true);
        
    }
    
}

MdServiceProvider.php - which extends MarkdownServicerProvider and simply registers your custom renderer:

<?php

namespace App\Providers;

use GrahamCampbell\Markdown\MarkdownServiceProvider;

class MdServiceProvider extends MarkdownServiceProvider {
    
    public function boot() {
        
        parent::boot();
        
    }
    
    public function register() {
        
        parent::register();
        
        
        // Add in our custom renderer:
        $env = $this->app['markdown.environment'];
        $env->addInlineRenderer('League\CommonMark\Inline\Element\Image', new \App\Commonmark\CustomImageRenderer());
        
    }
    
}

And that's it. Now any and all markdown text that includes an image tag will automatically have "class='image-rounded image-responsive'" added to it and will therefore work with Bootstrap responsive sites.

2 likes

Please or to participate in this conversation.