, 3 min read

Mixing PHP into Markdown

Markdown is a simple language to write documents, which are finally converted to HTML. There are many conversion programs to convert from Markdown to HTML. This blog uses MD4C for this.

The CommonMark specification says:

An HTML block is a group of lines that is treated as raw HTML (and will not be escaped in HTML output).

Start condition: line begins with the string <?.

End condition: line contains the string ?>.

So it is possible to embed PHP in Markdown. Unfortunately, not every construct in Markdown passes PHP through undisturbed. For example, links and images, i.e., [reftext](ref) and ![](/imgref) destroy the PHP start- and endtags <? and ?>. Luckily, these small glitches can be cured with some string-replacements.

1. Examples. Embedding PHP code in Markdown allows us to write something like this, below is Markdown:

<?php
    $pkgList = explode("\n",`pacman -Q`);
    $pkg = array();
    foreach ($pkgList as $e) { $f=explode(' ',$e); $pkg[$f[0]??'x'] = $f[1]??''; }
?>

Using neovim version <?=$pkg['neovim']?>.

That's exactly what is done in /uses.

Another example is adding information based on time:

On <?=date('d-M-Y')?> this blog has <?= `find ~klm/php/sndsaaze/content -name \*.md | wc -l` ?> entries.

Above code is used in Blog Anniversary: 500 posts.

Below code also shows the use of PHP within Markdown:

<?php $chap=0; $subchap=0; ?>

# <?=++$chap?>. First chapter
# <?=++$chap?>. Second chapter
## <?=$chap.'.'.(++$subchap)?> Subchapter

This produces:

<h1>1. First chapter</h1>
<h1>2. Second chapter</h1>
<h2>2.1 Subchapter</h2>

When PHP code is included in HTML code, which is legal in Markdown, then no "escaping" with a star (*) is required.

PHP code in HTML code can be included verbatim. For example:

<p>2021-04-02 <a href="<?=$rbase?>/pkg/jpilot_2.0.1-1_amd64.deb">jpilot_2.0.1-1_amd64.deb</a>

Here is an example of PHP code in the URL part in Markdown:

The Markdown for _Simplified Saaze_ can also [contain PHP code](*<?=$rbase?>*/blog/2023/08-27-mixing-php-into-markdown)!

Embedding PHP in ordinary text is also no problem. No escaping with a star (*) is required.

2. Implementation. Within ordinary paragraph text it is easy to just embed PHP, which is passed through to HTML unchanged. In references I now use this character combination to later string-replace any glitches introduced by the Markdown-to-HTML conversion.

[reference text](*<?=$rbase?>*/htmlRef)

With these added asterisks I then later replace any conversion errors. Previously I just used below code to include HTML in Simplified Saaze's templates:

<?= $entry['content'] ?>

Now I use (please mentally uppercase 3c and 3e):

$s = str_replace('*%3c?','<?',$entry['content']);
$s = str_replace('?%3e*','?>',$s);
require 'data:text/plain;base64,'.base64_encode($s);

When using require with data:text then you have to activate this in php.ini:

allow_url_include = On

See allow_url_include.

More information on data-wrappers is here: data:// and the comment by brainbox. Furthermore see PHP include and the comment by sPlayer. RFC 2397 details data:[<mediatype>][;base64],<data>.