Get "PHP 8 in a Nuthshell" (Soon includes PHP 8.4)
Amit Merchant

Amit Merchant

A blog on PHP, JavaScript, and more

Advanced Markdown using Extensions in Laravel

Markdown has become a widely adopted standard for formatting text on the web due to its simplicity and readability. It allows users to write using an easy-to-read, easy-to-write plain text format, which is then converted to structurally valid HTML.

Luckily, for Laravel developers, support for Markdown comes out of the box in the form of a helper function called Str::markdown().

The Markdown Helper

Here’s how the Markdown helper works.

use Illuminate\Support\Str;

$markdown = Str::markdown('**Hello World**');

echo $markdown; // <p><strong>Hello World</strong></p>

As you can tell, the function takes a string written in Markdown as its argument and returns a string containing the HTML representation of the Markdown content.

There’s a second parameter in the function that takes configuration options as an array.

For instance, if you want to remove risky links and image URLs, you can pass the following configuration options to the function.

use Illuminate\Support\Str;

$markdown = Str::markdown(
    'Inject: <script>alert("Hello XSS!");</script>', 
    [
        'allow_unsafe_links' => false
    ]
);

echo $markdown; 
// <p>Inject: alert(&quot;Hello XSS!&quot;);</p>

This is already gold if you want to parse Markdown content in your Laravel application. But if you need more advanced features, there are extensions to let you do that.

Markdown Extensions

Essentially, the Markdown helper in Laravel uses the awesome League/CommonMark package to parse Markdown content under the hood. So, every configuration the package comes with is available to you including the extensions to add more features to the CommonMark parser.

Laravel now can use these extensions using the markdown helper function. There’s a third parameter in the function that can be used to pass the extensions you want to use.

You can start using these extensions right away without installing any additional packages.

For instance, if you want to make heading elements likable, you can pass the instance of HeadingPermalinkExtension to the function as shown below.

use Illuminate\Support\Str;
use League\CommonMark\Extension\HeadingPermalink\HeadingPermalinkExtension;

$markdown = Str::markdown(
    '## Heading 1',
    [
        'allow_unsafe_links' => false
    ],
    [
        new HeadingPermalinkExtension()
    ]
);

/*
<h2>
    <a 
        id="content-heading-1" 
        href="#content-heading-1" 
        class="heading-permalink" 
        aria-hidden="true" 
        title="Permalink"
    >
        ¶
    </a>
    Heading 1
</h2>
*/

As you can tell, this will generate an HTML layout where there will be a permalink icon next to the heading element that can be used to link to the heading (with the fragment identifier #content-heading-1).

Now, you can customize the behavior of the extension as well. For instance, if we want to change the permalink icon to a simple # symbol instead of the default and add a custom class to the permalink icon, we can do that as shown below.

use Illuminate\Support\Str;
use League\CommonMark\Extension\HeadingPermalink\HeadingPermalinkExtension;

$markdown = Str::markdown(
    '## Heading 1',
    [
        'allow_unsafe_links' => false,
        'heading_permalink' => [
            'html_class' => 'custom-permalink',
            'symbol' => '#'
        ],
    ],
    [
        new HeadingPermalinkExtension()
    ]
);

/*
<h2>
    <a 
        id="content-heading-1" 
        href="#content-heading-1" 
        class="custom-permalink" 
        aria-hidden="true" 
        title="Permalink"
    >
        #
    </a>
    Heading 1
</h2>
*/

Learn more: Heading Permalink Extension

Table of Contents Extension

There’s another related extension called TableOfContentsExtension that can be used to generate a table of contents for the Markdown content.

Here’s how we can generate a table of contents for the previous example.

use Illuminate\Support\Str;
use League\CommonMark\Extension\TableOfContents\TableOfContentsExtension;
use League\CommonMark\Extension\HeadingPermalink\HeadingPermalinkExtension;

$markdown = Str::markdown(
    '## Heading 1',
    [
        'allow_unsafe_links' => false,
        'heading_permalink' => [
            'html_class' => 'custom-permalink',
            'symbol' => '#'
        ],
    ],
    [
        new HeadingPermalinkExtension(),
        new TableOfContentsExtension()
    ]
);

/*
<ul class="table-of-contents">
  <li>
    <a href="#content-heading-1">Heading 1</a>
  </li>
</ul>

<h2>
    <a 
        id="content-heading-1" 
        href="#content-heading-1" 
        class="custom-permalink" 
        aria-hidden="true" 
        title="Permalink"
    >
        #
    </a>
    Heading 1
</h2>
*/

Same as the Heading Permalink extension, you can customize the behavior of the extension using the configuration options as well.

Keep in mind that, for this extension to work, the Heading Permalink extension must be enabled as well since it builds the TOC on top of the heading permalinks.

Learn more: Table of Contents Extension

In closing

These are only two Markdown extensions of many that are available in the League CommonMark package. There are a lot more helpful extensions that you can use to enhance your Markdown experience in Laravel.

For instance, there’s an extension to parse Front Matter in Markdown content and consume it as an array in your application or a Tables extension that can be used to generate tables in Markdown content. The possibilities are endless.

Check all the extensions you can use today!

PS:- There’s a video by Laracasts that covers Markdown Extensions nicely if you’re a visual learner.

Learn the fundamentals of PHP 8 (including 8.1, 8.2, and 8.3), the latest version of PHP, and how to use it today with my new book PHP 8 in a Nutshell. It's a no-fluff and easy-to-digest guide to the latest features and nitty-gritty details of PHP 8. So, if you're looking for a quick and easy way to PHP 8, this is the book for you.

Like this article?

Buy me a coffee

👋 Hi there! I'm Amit. I write articles about all things web development. You can become a sponsor on my blog to help me continue my writing journey and get your brand in front of thousands of eyes.

Comments?