ryangjchandler/downmark

A speedy Markdown parser for PHP applications.

v0.0.6 2022-05-13 13:36 UTC

This package is auto-updated.

Last update: 2022-09-04 18:36:59 UTC


README

Latest Version on Packagist Tests Total Downloads

This is a super lightweight Markdown parser for PHP projects and applications. It has a rather verbose but powerful extension API for adding custom blocks and inline elements.

Features

At the moment, Downmark has support for the following Markdown blocks:

  • Headings (h1 - h6)
  • Blockquotes (multi-line support)
  • Single-level unordered and ordered lists
  • Backtick-delimited code blocks

It also has support for the following inline elements:

  • Links
  • Images
  • Bold, italic and strikethrough
  • Inline code

Installation

You can install the package via Composer:

composer require ryangjchandler/downmark

Usage

To parse a string of Markdown and compile it to HTML, do the following:

use Downmark\Downmark;

$parser = Downmark::create();

$html = $parser->parse('**Hello!**');

Block extensions

To create a custom block-level extensions, you first need to register it with the parser:

use Downmark\Blocks\Block;

Downmark::create()
    ->block("/::: (.*)/", function (array $matches): Block {

    });

The Downmark::block() methods accepts 2 arguments. The first is a regular expression, used by the parser to find the start of your block. The second is a Closure that should return an instance of Downmark\Blocks\Block.

You can create an object that extends the Downmark\Blocks\Block class. This class only requires you to implement a single public toHtml(): string method.

use Downmark\Blocks\Block;

class NoticeBlock extends Block
{
    public function __construct(
        protected ?string $content = '',
    ) {}

    public function toHtml(): string
    {
        return '<div class="notice">' . $this->content . '</div>';
    }
}

Inside of the extension callback, you can return an instance of NoticeBlock.

Downmark::create()
    ->block("/::: (.*)/", function (array $matches): Block {
        return new NoticeBlock($matches[1]);
    });

When the parser compiles your Markdown, it will check if this block matches and execute the callback function.

Note: Documentation on building multi-line blocks coming soon... If you're super eager, source-dive the tests to find out how it works.

Inline extensions

Downmark also provides an API for extending Markdown with custom inline elements. The example below extends Downmark to support a "mention" syntax that generates links to Twitter profiles.

Downmark::create()
    // Look for any inline text that matches a single `@` character followed by 1 to 15 alphanumeric (incl. underscore) characters.
    ->inline("/@([A-Za-z0-9_]{1,15})(?!\w)/", function (array $matches): string {
        return sprintf('<a href="https://twitter.com/%s" target="_blank">%s</a>', $matches[1], $matches[0]);
    });

The callback function should return a string. This will be used to replace the regular-expression match.

Preprocessors

A preprocessor is any class that implements the Downmark\Interfaces\Preprocessor interface.

use Downmark\Interfaces\Preprocessor;
use Downmark\Blocks\Block;
use Downmark\Blocks\Paragraph;

class RickRoller implements Preprocessor
{
    public function preprocess(Block $block): Block
    {
        if (! $block instanceof Paragraph) {
            return $block;
        }

        $block->content = 'Rick rolled!';

        return $block;
    }
}

The RickRoller class above will receive each Block in the document. It can then modify the block, return a new block or leave it as it is. This preprocessor will replace the content inside of all paragraph blocks with Rick rolled!.

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.