Better Markdown Parser in PHP

Last update: Jul 31, 2022

Parsedown

Parsedown

Build Status Total Downloads Version License

Better Markdown Parser in PHP - Demo.

Features

Installation

Install the composer package:

composer require erusev/parsedown

Or download the latest release and include Parsedown.php

Example

$Parsedown = new Parsedown();

echo $Parsedown->text('Hello _Parsedown_!'); # prints: <p>Hello <em>Parsedown</em>!</p>

You can also parse inline markdown only:

echo $Parsedown->line('Hello _Parsedown_!'); # prints: Hello <em>Parsedown</em>!

More examples in the wiki and in this video tutorial.

Security

Parsedown is capable of escaping user-input within the HTML that it generates. Additionally Parsedown will apply sanitisation to additional scripting vectors (such as scripting link destinations) that are introduced by the markdown syntax itself.

To tell Parsedown that it is processing untrusted user-input, use the following:

$Parsedown->setSafeMode(true);

If instead, you wish to allow HTML within untrusted user-input, but still want output to be free from XSS it is recommended that you make use of a HTML sanitiser that allows HTML tags to be whitelisted, like HTML Purifier.

In both cases you should strongly consider employing defence-in-depth measures, like deploying a Content-Security-Policy (a browser security feature) so that your page is likely to be safe even if an attacker finds a vulnerability in one of the first lines of defence above.

Security of Parsedown Extensions

Safe mode does not necessarily yield safe results when using extensions to Parsedown. Extensions should be evaluated on their own to determine their specific safety against XSS.

Escaping HTML

WARNING: This method isn't safe from XSS!

If you wish to escape HTML in trusted input, you can use the following:

$Parsedown->setMarkupEscaped(true);

Beware that this still allows users to insert unsafe scripting vectors, such as links like [xss](javascript:alert%281%29).

Questions

How does Parsedown work?

It tries to read Markdown like a human. First, it looks at the lines. It’s interested in how the lines start. This helps it recognise blocks. It knows, for example, that if a line starts with a - then perhaps it belongs to a list. Once it recognises the blocks, it continues to the content. As it reads, it watches out for special characters. This helps it recognise inline elements (or inlines).

We call this approach "line based". We believe that Parsedown is the first Markdown parser to use it. Since the release of Parsedown, other developers have used the same approach to develop other Markdown parsers in PHP and in other languages.

Is it compliant with CommonMark?

It passes most of the CommonMark tests. Most of the tests that don't pass deal with cases that are quite uncommon. Still, as CommonMark matures, compliance should improve.

Who uses it?

Laravel Framework, Bolt CMS, Grav CMS, Herbie CMS, Kirby CMS, October CMS, Pico CMS, Statamic CMS, phpDocumentor, RaspberryPi.org, Symfony Demo and more.

How can I help?

Use it, star it, share it and if you feel generous, donate.

What else should I know?

I also make Nota — a writing app designed for Markdown files :)

GitHub

https://github.com/erusev/parsedown
Comments
  • 1. Prevent various XSS attacks [rebase and update of #276]

    I've picked up on the work started over at https://github.com/erusev/parsedown/pull/276 and rebased on erusev/master.

    Since this is rebased on master, I can't point at PR at naNuke/master without running into the merge conflicts that I've already resolved manually.

    I've implemented what I suggested earlier so that all attributes are properly encoded (and not just the specific ones we remember).

    I've also added some tests, so @erusev's concern here should hopefully now be resolved, albeit a year later 😉 https://github.com/erusev/parsedown/pull/276#issuecomment-178577968

    @malas one reason is the lack of tests

    ~~One thing to note is that all this can be circumvented if you forget to turn on $Parsedown->setMarkupEscaped(true); (which is off by default) as you could just write a script tag manually for xss (even though the attributes and link destinations will be safe). So let's all remember to enable this setting 😉~~

    Attributes are now always escaped properly (this speaks to just outputting things correctly), but link based XSS or XSS from writing plain old script tags will only be prevented only if the new setSafeMode is enabled.

    $Parsedown->setSafeMode(true);
    

    Closes #161 Closes #497 Closes #276 Closes #403 Closes #530


    The following CVE has been assigned to the vulnerability specific to bypassing ->setMarkupEscaped(true): CVE-2018-1000162.

    Reviewed by aidantwoods at 2017-05-01 02:47
  • 2. Safe Mode

    Parsedown offers no safe option for rendering, so, for those of us who allow no HTML content within markdown text, we must sanitize prior to feeding to Parsedown. As a result, Parsedown double encodes HTML entities (see #50).

    Instead, Parsedown should offer a "safe" option.

    function text($text, $safe_mode = false) {
        $this->safe_mode = $safe_mode;
        if ($safe_mode) {
            $text = htmlentities($text, ENT_QUOTES, 'UTF-8');
        }
        ...
    }
    

    Usage:

    $parsedown = new ParseDown();
    $text = "<script>alert('unsafe text');</script>";
    echo $parsedown->text($text, true);
    

    Output:

    &lt;script&gt;alert(&quote;unsafe text&quote;);&lt/script&gt;
    
    Reviewed by clphillips at 2014-04-29 16:30
  • 3. Extra empty lines not showing up in preview using parsedown and codeigniter

    Previewing parsedown not displaying correct newlines in preview

    demo

    With <br/> manually entered texarea I do not want to have to enter <br/> all the time if need to have extra lines

    demo1

    Question: How can I get it to show correct lines amount of lines that are in the textarea to preview?

    Controller How I load the parsedown.php

    if I replace \n with <br> it will effect the code indents I have tried nl2br() also

    <?php
    
    class Example extends CI_Controller {
    
    	public function __construct() {
    		parent::__construct();
                    // application > libraries > Parsedown.php
    		$this->load->library('parsedown'); 
    	}
    
    	public function index()
    	{
    		$this->load->view('example_view');
    	}
    
    	public function preview() {
    		$data['success'] = false;
    		$data['output'] = '';
    
    		if ($this->input->post('html')) {
    			
    			$string = str_replace('\n', '\r\n', $this->input->post('html'));
    			
    			$data['success'] = true;
    			$data['output'] = $this->parsedown->text($string);
    			
    		}
    
    		echo json_encode($data);
    	}
    }
    

    Script

    
    <script type="text/javascript">
    $( document ).ready(function() {
    	$('#editor').on('paste cut mouseup mousedown mouseout keydown keyup', function(){
    		var postData = {
    			'html' : $('#editor').val(),
    		};
    		$.ajax({
    			type: "POST",
    			url: "<?php echo base_url('example/preview');?>",
    			data: postData,
    			dataType: 'json',
    			success: function(json){
    				$('#output').html(json['output']);
    			}
    		});
    	});
    });
    </script>
    

    it's one of the best markdowns this is the only thing I can that need to fix.

    Reviewed by tasmanwebsolutions at 2016-11-25 05:38
  • 4. Prevent various XSS attacks

    Hello, I am back with the safe links issue. As always this is open to discussion :) but together with already existing markupEscaped setting, this is basically a fix for issues #161 and #210, and maybe other im not aware of.

    Reviewed by naNuke at 2015-01-21 03:05
  • 5. Links won't get converted

    Hi,

    thanks for this great and fast MD parser :) When i used it on this MD-File: https://github.com/RexDude/seo42/blob/master/README.md

    I get 6-times (EDIT: due to a REDAME.md update there are now 10) the following PHP-Warning and also all the Links won't get converted.

    Warning: preg_match_all(): Compilation failed: internal error: previously-checked referenced subpattern not found at offset 37 in /home/dude/Projekte/Web/AddonFactory/htdocs/redaxo/include/addons/seo42/classes/class.parsedown.inc.php on line 494
    

    Is this something with my MD-File or with the Parser?

    Reviewed by ghost at 2013-10-02 08:17
  • 6. Add a CLI mode to allow parsing markdown at the command line

    I was writing a lot of tests, and then copy/pasting the HTML from my browser to the appropriate HTML file, which was very time consuming. Then it occurred to me that we could use Parsedown.php as the CLI tool. With this code you can now do:

    php Parsedown.php document.md > document.html
    
    Reviewed by scottchiefbaker at 2014-01-30 16:03
  • 7. Href attribute not being rendered correctly

    When parsing HTML inside my Markdown string, I've been coming across some issues. Most noticeably any href attributes of those HTML bits.

    <a z='/training/schema' href='/training/schema'>Schema</a>
    

    Is rendered as

    <a z="/training/schema" href="%7B%7B%20url%20%7D%7D">Schema</a>
    
    Reviewed by jackmcdade at 2015-01-15 21:28
  • 8. Allow to remove the englobing paragraph

    I would like to remove the <p></p> englobing the html output as it has not specifically been asked.

    Just make an optional parameter to remove it in parse

    $parser = new Parsedown();
    $output = $parser->parse($input,false);//Without <p></p>
    $output = $parser->parse($input,true);//With <p></p>
    $output = $parser->parse($input);//With <p></p>
    

    Thanks

    Reviewed by Hypoaristerolactotherapist at 2013-12-04 23:25
  • 9. Add "id" attribute to headings

    This is more or less how GitHub Flavored Markdown works.

    See an example: https://github.com/henriquemoody/parsedown/blob/titles/test/data/atx_heading.md

    Reviewed by henriquemoody at 2015-02-08 20:19
  • 10. Problems with line break

    Best regards...

    The problem I have is the following: When creating paragraphs with appointments, the next paragraph that does not belong to the appointment is added. In this way:

    image

    Reviewed by rdgonzalez2017 at 2018-07-13 20:02
  • 11. Formatting already sanitized inputs

    Well I am using this lib in my chat app and the problem I am facing is formatting sanitized inputs.

    For ex: If the user sends > text it doesn't change to blockquote but shows up as > text where > is the html entity code in the html inspector and also in the db.

    Is there any way it could be done to get it to work as expected?

    Reviewed by whimsicaldreamer at 2016-08-24 17:11
  • 12. [Bug] Code block splitted (1.7.4, 2.0.0 Beta 1)

    Description

    Parsedown splits a code block in multiple parts when having a markdown file like the following:

    * Source
    ```bash
    $ ls
    
    # Comment in code
    $ ls
    ```
    

    The issue is present in the latest stable release and the latest public beta.

    Expected Behavior

    <ul>
    <li>Source</li>
    </ul>
    <pre><code class="language-bash">$ ls
    # Comment in code</span>
    
    $ ls
    </code></pre>
    

    Actual Behavior

    <ul>
    <li>Source
    <pre><code class="language-bash">$ ls
    </code></pre>
    </li>
    </ul>
    <h1>Comment in code</h1>
    <p>$ ls</p>
    <pre><code></code></pre>
    

    Steps to reproduce

    Reproduce with Parsedown 1.7.4

    • Go to Parsedown Demo
    • Add markdown example from the description
    • Click parse

    Reproduce with Parsedown 2.0.0 Beta 1

    Setup

    $ sudo apt install php8.1
    $ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
    $ php composer-setup.php
    $ php -r "unlink('composer-setup.php');"
    # Dependencies
    $ sudo apt-get install php8.1-mbstring
    $ php ../composer.phar require erusev/parsedown:v2.0.0-beta-1
    $ php demo.php
    

    demo.php

    <?php
    
    require __DIR__ . '/vendor/autoload.php';
    
    use Erusev\Parsedown\Configurables\Breaks;
    use Erusev\Parsedown\Configurables\SafeMode;
    use Erusev\Parsedown\Configurables\StrictMode;
    use Erusev\Parsedown\State;
    use Erusev\Parsedown\Parsedown;
    
    
    $markdown = <<<EOD
    * Source
    ```bash
    $ ls
    
    # Comment in code
    $ ls
    ```
    EOD;
    
    
    $state = new State([
        new Breaks(true),
        new SafeMode(true),
        new StrictMode(false)
    ]);
    
    $Parsedown = new Parsedown($state);
    echo $Parsedown->toHtml($markdown);
    ?>
    
    Reviewed by Tooa at 2022-06-29 21:55
  • 13. [Bug] Element h1 inside list element when having no newline (1.7.4, 2.0.0 Beta 1)

    Description

    Parsedown places the h1 element inside the list element when having a markdown file like the following:

    * element1
    * element2
    # Troubleshooting
    

    The issue is present for the latest stable release and the latest public beta. The problem does not occur with Markdown PHP 1.3 featured in the Parsedown Demo though.

    Let me know how I can further assist @erusev @aidantwoods.

    Expected Behavior

    <ul>
    <li>element1</li>
    <li>element2</li>
    </ul>
    
    <h1>Troubleshooting</h1>
    

    Actual Behavior

    <ul>
    <li>element1</li>
    <li>element2
    <h1>Troubleshooting</h1></li>
    </ul>
    

    Steps to reproduce

    Reproduce with Parsedown 1.7.4

    • Go to Parsedown Demo
    • Add markdown example from the description
    • Click parse

    indent-issue-demo

    Reproduce with Parsedown 2.0.0 Beta 1

    Setup

    $ sudo apt install php8.1
    $ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
    $ php composer-setup.php
    $ php -r "unlink('composer-setup.php');"
    # Dependencies
    $ sudo apt-get install php8.1-mbstring
    $ php ../composer.phar require erusev/parsedown:v2.0.0-beta-1
    $ php demo.php
    

    demo.php

    <?php
    
    require __DIR__ . '/vendor/autoload.php';
    
    use Erusev\Parsedown\Configurables\Breaks;
    use Erusev\Parsedown\Configurables\SafeMode;
    use Erusev\Parsedown\Configurables\StrictMode;
    use Erusev\Parsedown\State;
    use Erusev\Parsedown\Parsedown;
    
    
    $markdown = <<<EOD
    * element1
    * element2
    # Troubleshooting
    EOD;
    
    
    $state = new State([
        new Breaks(true),
        new SafeMode(true),
        new StrictMode(false)
    ]);
    
    $Parsedown = new Parsedown($state);
    echo $Parsedown->toHtml($markdown);
    ?>
    

    indent-issue-beta

    Reviewed by Tooa at 2022-06-28 07:26
  • 14. Add Option minHeaderLevel

    Add a new option to define the minimal Header level to be used e.g. if the option ->minHeaderLevel(3) a header defined with a single hash # heading will be parsed as <h3>heading</h3>

    Reviewed by nyphis at 2022-06-15 20:08
  • 15. emojis support

    Is it possible to add emojis support. : https://github.com/markdown-templates/markdown-emojis

    so that markdown emojiis can be converted to html

    i think it will be easy to implement , like download all emojis png/svg from that page and put them in one folder , then ship this folder with parsedown pkg and then add initialize emoji option to parsdown pkg where user will define path where these emojis images are stored and then parsedown can create hotlinks to it like like : https://mywebsite.com/assets/parsedown_emojee_pkg/unicode/1f608.png

    thanks

    Reviewed by darkworks at 2022-06-13 04:40
  • 16. Allow excluding certain elements

    I haven't found a way at the moment to do this. What i would like is to be able to pass a rule to the class to not render headers.

    I can take them out of the raw string, but if there was a way to apply a setting to not render the ## for example as a header, that would be more efficient.

    Also, if there was a way to replace the headers with just bold text, that would be even better.

    Reviewed by userofit123 at 2022-05-20 10:27
  • 17. Parsedown not counting linebreaks properly? Images also wrapped in

    tags.

    My current usage:

    $markdown = file_get_contents($filepath); 
    new Parsedown(); ?>
    
    echo Parsedown::instance()
       ->setBreaksEnabled(true) # enables automatic line breaks
       ->text($markdown);
    

    My file:

    Blah blah blah
    Blah.
    ![alt text](https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png "Logo Title Text 1")
    

    This outputs:

    <p>Blah blah blah</p>
    <p>Blah.</p>
    <p><img src="https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png" alt="alt text" title="Logo Title Text 1" /></p>
    

    How comes it's not counting the line breaks and why is it added p tags to the image?

    Many thanks!

    Reviewed by scottynorris at 2022-04-27 14:13
Highly-extensible PHP Markdown parser which fully supports the CommonMark and GFM specs.
Highly-extensible PHP Markdown parser which fully supports the CommonMark and GFM specs.

league/commonmark league/commonmark is a highly-extensible PHP Markdown parser created by Colin O'Dell which supports the full CommonMark spec and Git

Jul 27, 2022
A simple regex-based Markdown parser in PHP

Slimdown A simple regex-based Markdown parser in PHP. Supports the following elements (and can be extended via Slimdown::add_rule()): Headers Links Bo

Jul 27, 2022
A super lightweight Markdown parser for PHP projects and applications.

A speedy Markdown parser for PHP applications. This is a super lightweight Markdown parser for PHP projects and applications. It has a rather verbose

May 31, 2022
Convert HTML to Markdown with PHP

HTML To Markdown for PHP Library which converts HTML to Markdown for your sanity and convenience. Requires: PHP 7.2+ Lead Developer: @colinodell Origi

Aug 1, 2022
A PHP tool to generate templateable markdown documentation from the docblocks or type-hints of your codebase.

Roster Installation To install, simply require the package using composer: composer require

Sep 8, 2021
PHP Markdown Engine Support

PHP Markdown Version v1.x support all PHP version >=5.4 v2.x support all PHP version >=7.0 Cài đặt thư viện Thư viện này được cài đặt thông qua Compos

Jul 1, 2022
Rendering markdown from PHP code

JBZoo / Markdown Installing composer require jbzoo/markdown Usage Rendering Table <?php declare(strict_types=1); use JBZoo\Markdown\Table; echo (new

Dec 26, 2021
PHP Markdown & Extra

PHP Markdown & Extra An updated and stripped version of the original PHP Markdown by Michel Fortin. Works quite well with PSR-0 autoloaders and is Com

Jan 18, 2022
PHP based Markdown documentation viewer

PHP based viewer for Markdown files, to view them with fenced code highlighting and navigation.

Mar 31, 2022
A highly configurable markdown renderer and Blade component for Laravel
A highly configurable markdown renderer and Blade component for Laravel

A highly configurable markdown renderer and Blade component for Laravel This package contains: a Blade component that can render markdown a highly con

Jul 29, 2022
Easily add routes to your Laravel app by creating Markdown or Blade files

Laravel Pages This package lets you create pages using Markdown or Blade without having to worry about creating routes or controllers yourself. Essent

Jul 6, 2022
Render colored Markdown contents on console terminal
Render colored  Markdown contents on console terminal

cli-markdown Render colored markdown contents on console terminal Preview run demo by php example/demo.php Features support auto render color on termi

Jan 27, 2022
Generate pseudo-static pages from markdown and HTML files for Flarum

Flarum Pages Generator This is not a Flarum extension. This package provides a Flarum extender that you can use in the local extend.php to define cust

Feb 21, 2022
markdown wiki/blog
markdown wiki/blog

Kwiki markdown wiki/blog Usage Place your markdown files in the /wiki directory. Categories are directories and subcategories are subdirectories. If y

May 29, 2022
Symfony 5 bundle to easily create dynamic subpages with Markdown. Useful for help sections and wikis.

MarkdownWikiBundle This bundle allows you to create rich subpages in a Symfony project using Markdown. Pages are stored in a file cache and sourced fr

Apr 26, 2022
Gruik ! An open-source markdown note-taking web app. [ABANDONED PROJECT]

What is Gruik ? It's a free & open-source note-taking service. A space where you can store notes, tutorials, code snippets... by writing them in markd

Mar 31, 2022
Docbook Tool for static documentation generation from Markdown files

Roave Docbook Tool Static HTML and PDF generator tool for generating documentation from Markdown files. Generates a deployable HTML file from Markdown

Jul 21, 2022
PHP Documentation system.

PHP Documentation system Simple but powerful Markdown docs. Features Search within Markdown files Customizable Twig templates (Note: default design is

Jun 8, 2022
Parser for Markdown and Markdown Extra derived from the original Markdown.pl by John Gruber.

PHP Markdown PHP Markdown Lib 1.9.0 - 1 Dec 2019 by Michel Fortin https://michelf.ca/ based on Markdown by John Gruber https://daringfireball.net/ Int

Jul 28, 2022
YCOM Impersonate. Login as selected YCOM user 🧙‍♂️in frontend.

YCOM Impersonate Login as selected YCOM user in frontend. Features: Backend users with admin rights or YCOM[] rights, can be automatically logged in v

Jan 19, 2022