MageWork

Back to home

Write content in Markdown

The Magedown library

MageWork ships with Magedown, a lightweight Markdown to HTML converter in a single file: core/lib/Magedown.php. No Composer dependency is required.

It supports headings (with slug id attributes), paragraphs, emphasis, inline code, links, images, fenced code blocks, blockquotes, ordered and unordered nested lists, horizontal rules and pipe tables. Any raw HTML in the source is escaped.

<?php

$html = (new Magedown())->parse('# Hello World!');
MethodDescription
setBreaksEnabledConvert a single line break into a <br /> tag
setHeadingIdsAdd a slug id attribute on every heading (enabled by default)
setHighlightEnabledColorize php and phtml fenced code blocks with highlight_string()
setBaseUrlPrefix relative link and image URLs with the given base URL
setAttributesEnabledEnable the optional {name="value"} custom attribute syntax
setAllowedAttributesReplace the list of attribute names accepted by the syntax
<?php

$html = (new Magedown())
    ->setBreaksEnabled(true)
    ->parse($content);

Custom attributes

When setAttributesEnabled() is called, a {name="value"} block adds HTML attributes to the element it follows. Only the name="value" form is recognised, with double quotes: {.class}, {#id} or {lazy} are ignored and left as plain text. Add ` before the brace ({`) to keep a literal block.

ElementWhere to place the blockExample
Linkglued to the closing )[label](url){target="_blank" rel="noreferrer" class="link blue"}
Imageglued to the closing )![alt](/media/banner.jpg){loading="lazy"}
Headingend of the line (an id replaces the auto slug)## Configuration {id="config"}
Paragraphend of the last lineThis is a note{class="message warning"}
List itemend of the first line* Element 1{id="e1"}
Blockquote, list, table, code blockalone on the line right below the block{class="callout"}

Values are always HTML escaped. Only allow-listed names are kept: id, class, title, target, rel, loading, width, height, align, alt, hidden, plus any data-* and aria-* name. Use setAllowedAttributes() to provide a different list.

<?php

$html = (new Magedown())
    ->setAttributesEnabled()
    ->parse($content);

Page override

To write a page content in Markdown, override the include method of the default Core_Page class (see object override).

packages > Acme > Page.php

<?php

declare(strict_types=1);

class Acme_Page extends Core_Page
{
    public function include(?string $template): string
    {
        $markdown = App::getPackagePath('template' . DS . $template . '.md');

        if (!is_file($markdown)) {
            return parent::include($template);
        }

        return (new Magedown())->parse(file_get_contents($markdown));
    }
}

The content template is now loaded from a .md file when it exists, and falls back to the .phtml file otherwise.

Page configuration

Add a new page with the content path (see create a page).

packages > Acme > etc > pages.php

<?php

$config = [
    Core_Page::TYPE => [
        /* ... */
        '/markdown.html' => [
            'content' => 'content/my-markdown-content',
            'meta_title' => 'Markdown Content',
            'meta_description' => 'The content of this page is written in Markdown',
        ],
        /* ... */
    ],
];

Markdown file

packages > Acme > template > content > my-markdown-content.md

# Hello World!

Welcome to my website.