In this guide, we explore the process of converting Markdown to HTML using PHP. Specifically, we’ll see how to perform the conversion with the three most popular Markdown libraries and a custom Markdown to HTML parser.

When a Markdown to HTML Conversion Is Needed

Markdown to HTML parsers are commonly used to allow users to write content in Markdown format and automatically display this content as HTML on the site’s front end. Here are a few scenarios where you might use a Markdown to HTML parsers in PHP:

  • Content Management Systems (CMS): Many CMS platforms, such as WordPress, use Markdown as an alternative markup language. In this context, Markdown-related features like editors and conversion tools are usually available in dedicated plugins.
  • Blogs and Forums: If you’re building a blog or a forum where users can contribute content, allowing them to write in Markdown provides a more straightforward and cleaner way to format their text.
  • Documentation: Developers and technical writers might prefer writing in Markdown due to its simplicity.
  • Custom Applications: In any PHP application where you want to support user-generated content with Markdown formatting.

Explore the Existing Libraries

Let’s take a look at the available PHP libraries for converting Markdown to HTML.

Parsedown

With 14.5k stars on GitHub, Parsedown is by far the most popular Markdown parser built with PHP. This parser uses a particular “line-based” parsing approach, and based on the benchmark documented on the GitHub page, it’s very fast.

To start, you can install the Parsedown package via Composer using this command.

composer require erusev/parsedown

If, instead, you prefer to use this library without Composer, download the project from GitHub and load the Parsedown.php file at the beginning of the PHP script.

include 'Parsedown.php';

Once Parsedown is available, create an instance and run the text() method with the Markdown text as the first function argument.

$Parsedown = new Parsedown();

echo $Parsedown->text('A paragraph with **Bold text** converted with Parsedown.');

// Output: <p>A paragraph with <em>Bold text</em> converted with Parsedown.</p>

In the example that follows, the user can submit Markdown text from a form; the submitted data are then retrieved, converted to HTML with Parsedown, and printed.

You should note that here, I enabled the safe mode of Parsedown by passing true to the setSafeMode() method. For more information on using Parsedown with user-generated content, please see the Security and Escaping HTML sections of the Parsedown documentation.

include 'Parsedown.php';

?>

<!-- A basic form where the user can submit a comment using Markdown text -->
<form action="form.php" method="post">
	<textarea name="comment" cols="60" rows="10"></textarea>
	<input type="submit" value="Submit Comment">
</form>

<?php

// Process the form
if (isset($_POST['comment'])) {

	$Parsedown = new Parsedown();

        // Enable the safe mode of Parsedown.
	$Parsedown->setSafeMode(true);

	// Echo the HTML from the Markdown text submitted by the user. Note: Additional escaping functions should be implemented based on the context.
	echo $Parsedown->text($_POST['comment']);

}

When you convert Markdown text provided by the users, for example, in the context of a forum or blog comments, consider applying additional sanitization, validation, and escaping functions.

While the correct way to handle the submitted Markdown text depends on the context, here are some recommended operations:

  • Use the security features of the Markdown parser in use. Specifically, with ParseDown, consider enabling the Security and Escaping HTML feature
  • Use the built-in sanitization and escaping features if your application is built with a framework or a CMS.
  • Limit the Markdown content length
  • Limit the number of links
  • Restrict the domains that can be linked; for example, you might want to allow only links to your domain.

Using Parsedown Extra

With the Parsedown Extra package, you can use the Markdown Extra flavor of Markdown. This variant is based on the original Markdown syntax but adds useful features such as tables, fenced code blocks, footnotes, and more.

To start, get the ParsedownExtra.php file from GitHub or install it using Composer, then instantiate the ParsedownExtra class and call the text() method to convert Markdown to HTML.

$Extra = new ParsedownExtra();

echo $Extra->text('# The post title {.main-heading}');

// Output: <h1 class="main-heading">The post title</h1>

League\CommonMark

League/CommonMark is a Markdown parser developed by The PHP League.

Below is a basic implementation of this parser that uses the Composer autoloader.

// Load the composer autoloader.
require_once 'vendor/autoload.php';

use League\CommonMark\CommonMarkConverter;

$converter = new CommonMarkConverter();

echo $converter->convert('A simple paragraph with a [link](https://example.com).');

// Output: <p>A simple paragraph with a <a href="https://example.com">link</a>.</h1>

Extensions are used to add new features to the parser. This example demonstrates how to use the Front Matter extension to parse and use YAML key-value pairs included in the HTML document.

$config = [];

// Configure the environment and add the extensions.
$env = new Environment($config);
$env->addExtension(new CommonMarkCoreExtension());
$env->addExtension(new FrontMatterExtension());

// Create an instance of the converter.
$converter = new MarkdownConverter($env);

// Markdown file with Front Matter key-value pairs.
$markdown = <<<MD
---
layout: layout-1
title: Example article
tags:
  - Tag 1
  - Tag 2
---

# Hello World!
MD;

$result = $converter->convert($markdown);

// Get the Front Matter data.
if ($result instanceof RenderedContentWithFrontMatter) {
    $frontMatter = $result->getFrontMatter();
}

// Display the resulting HTML.
echo $result;

To modify the Markdown to HTML conversion performed by this library you can pass a configuration object to the constructor using the options described on the configuration page.

The example below demonstrates how to remove unsafe links using a dedicated configuration option named allow_unsafe_links.

<?php

// load composer autoloader
require_once 'vendor/autoload.php';

use League\CommonMark\CommonMarkConverter;

$configuration = $config = [
	'allow_unsafe_links' => true,
];

$converter = new CommonMarkConverter($configuration);

echo $converter->convert('Paragraph with a [link](https://example.com).');

// Output: <p>Paragraph with a</p>

In this last example, I changed the configuration of specific CommonMark features using the commonmark configuration options.

<?php

// load composer autoloader
require_once 'vendor/autoload.php';

use League\CommonMark\CommonMarkConverter;

$configuration = $config = [
	'commonmark' => [
		'enable_em' => false,
		'enable_strong' => false,
		'use_asterisk' => true,
		'use_underscore' => false,
		'unordered_list_markers' => ['+', '+', '+'],
	],
];

$converter = new CommonMarkConverter($configuration);

echo $converter->convert('Content parsed with a custom **CommonMark** configuration.');

// Output: <p>Content parsed with a custom <strong>CommonMark</strong> configuration.</p>

PHP Markdown

PHP Markdown is another popular Markdown library for PHP created by Michel Fortin. This library supports the Markdown and the Markdown Extra syntax.

You can get the library with Composer:

composer require michelf/php-markdown

Then, use the defaultTransform() method to perform the conversion.

require 'vendor/autoload.php';

use Michelf\MarkdownExtra;
$html = MarkdownExtra::defaultTransform($markdown);

It’s easy to enable the Markdown extra syntax by using this command:

use Michelf\MarkdownExtra;
$html = MarkdownExtra::defaultTransform($markdown);

This library has configuration options that allow you to modify the behavior of the parser.

In the example below, I use the empty_element_suffix variable to define a custom string for closing void HTML tags.

use Michelf\Markdown;
$parser = new Markdown;
$parser->empty_element_suffix = ">";
$html = $parser->transform($markdown);

Ciconia

Ciconia is a Markdown parser written in PHP that is no longer in development. The last update was 11 years ago.

Cebe/Markdown

Cebe/Markdown is another abandoned Markdown parser.

Implement a Custom Markdown to HTML Parser in PHP Using Regular Expressions

In this section, you will see examples that can help you start building a simple regex-based Markdown to HTML converter with PHP. I recommend using this solution only if a limited subset of Markdown is needed. For example, if you only need to support headings, links, and bold text. If you need a parser with full Markdown support, using one of the libraries mentioned above is better.

Let’s see a few simple examples of regex patterns that can be used to convert specific Markdown elements to HTML.

The regex below generates the HTML paragraphs by detecting two consecutive new lines in the Markdown document.

$markdown = "First paragraph.\n\nSecond paragraph.\n\nThird paragraph.";

$html = preg_replace('/\n{2,}/', '</p><p>', "<p>{$markdown}</p>");

echo $html;

// Output: <p>First paragraph.</p><p>Second paragraph.</p><p>Third paragraph.</p>

It’s worth noting that this regex matches bold text in the ** and __ formats.

$markdown = "Example of **bold text** and __another bold__ example.";

$html = preg_replace('/\*\*(.*?)\*\*|__(.*?)__/', '<strong>$1$2</strong>', $markdown);

echo $html;

// Output: Example of <strong>bold text</strong> and <strong>another bold</strong> example.

Here, using preg_replace_callback(), the script finds the headings of a Markdown document; then, in the callback, the number of # characters is counted and used to generate the HTML heading with the correct heading level.

$markdown = "## Title of the section";

$html = preg_replace_callback('/^#{1,6} (.+)$/m', function ($matches) {
	$level = strlen($matches[0]) - 1;
	return "<h$level>{$matches[1]}</h$level>";
}, $markdown);

echo $html;

// Output: <h2>Title of the section</h2>

To convert a Markdown link to its corresponding HTML element, we use two capturing groups to extract the content of the square and round brackets.

$markdown = "This is a [sample link](https://example.com) and [another link](https://example.com).";

$html = preg_replace('/\[([^\]]+)\]\(([^)]+)\)/', '<a href="$2">$1</a>', $markdown);

echo $html;

// Output: This is a <a href="https://example.com">sample link</a> and <a href="https://example.com">another link</a>.

Converting Markdown to HTML in Laravel

A simple solution to convert Markdown to HTML in Laravel is to use the Str::markdown() helper method.

Note that this method works for GitHub flavored Markdown (GFM) only. If you want to use a different flavor of Markdown, you can implement a custom solution that uses your favorite Markdown library.

Converting Markdown to HTML in WordPress

WordPress, the popular CMS powered by PHP, has many plugins that allow you to write content in Markdown and convert it to HTML.

For example, you can download Jetpack and use the dedicated Markdown Block. To enable this feature, simply activate the “Write posts or pages in plain-text Markdown syntax” option available under the Composing tab.

If, instead, you prefer a simple uploader of Markdown files, check out the Import Markdown plugin on the WordPress.org repository. This plugin gives you the ability to upload Markdown files and convert them into posts.

For more advanced workflows, you might also consider using Ultimate Markdown. A plugin for power users that gives you the ability to send Markdown files to WordPress using the WordPress REST API.