Skip to content

Commit

Permalink
Merge pull request #745 from aidantwoods/dev-1.7.x/opt-in-rawHtml
Browse files Browse the repository at this point in the history
Opt in raw html
  • Loading branch information
aidantwoods committed Dec 30, 2019
2 parents 3d2b25b + 791faca commit 21f99b1
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 4 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -14,6 +14,7 @@ matrix:
- php: 7.1
- php: 7.2
- php: 7.3
- php: 7.4
- php: nightly
fast_finish: true
allow_failures:
Expand Down
27 changes: 23 additions & 4 deletions Parsedown.php
Expand Up @@ -17,7 +17,7 @@ class Parsedown
{
# ~

const version = '1.7.3';
const version = '1.7.4-dev';

# ~

Expand Down Expand Up @@ -1489,22 +1489,41 @@ protected function element(array $Element)
}
}

$permitRawHtml = false;

if (isset($Element['text']))
{
$text = $Element['text'];
}
// very strongly consider an alternative if you're writing an
// extension
elseif (isset($Element['rawHtml']))
{
$text = $Element['rawHtml'];
$allowRawHtmlInSafeMode = isset($Element['allowRawHtmlInSafeMode']) && $Element['allowRawHtmlInSafeMode'];
$permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode;
}

if (isset($text))
{
$markup .= '>';

if (!isset($Element['nonNestables']))
if (!isset($Element['nonNestables']))
{
$Element['nonNestables'] = array();
}

if (isset($Element['handler']))
{
$markup .= $this->{$Element['handler']}($Element['text'], $Element['nonNestables']);
$markup .= $this->{$Element['handler']}($text, $Element['nonNestables']);
}
elseif (!$permitRawHtml)
{
$markup .= self::escape($text, true);
}
else
{
$markup .= self::escape($Element['text'], true);
$markup .= $text;
}

$markup .= '</'.$Element['name'].'>';
Expand Down
36 changes: 36 additions & 0 deletions test/ParsedownTest.php
@@ -1,5 +1,7 @@
<?php

require 'SampleExtensions.php';

use PHPUnit\Framework\TestCase;

class ParsedownTest extends TestCase
Expand Down Expand Up @@ -55,6 +57,40 @@ function test_($test, $dir)
$this->assertEquals($expectedMarkup, $actualMarkup);
}

function testRawHtml()
{
$markdown = "```php\nfoobar\n```";
$expectedMarkup = '<pre><code class="language-php"><p>foobar</p></code></pre>';
$expectedSafeMarkup = '<pre><code class="language-php">&lt;p&gt;foobar&lt;/p&gt;</code></pre>';

$unsafeExtension = new UnsafeExtension;
$actualMarkup = $unsafeExtension->text($markdown);

$this->assertEquals($expectedMarkup, $actualMarkup);

$unsafeExtension->setSafeMode(true);
$actualSafeMarkup = $unsafeExtension->text($markdown);

$this->assertEquals($expectedSafeMarkup, $actualSafeMarkup);
}

function testTrustDelegatedRawHtml()
{
$markdown = "```php\nfoobar\n```";
$expectedMarkup = '<pre><code class="language-php"><p>foobar</p></code></pre>';
$expectedSafeMarkup = $expectedMarkup;

$unsafeExtension = new TrustDelegatedExtension;
$actualMarkup = $unsafeExtension->text($markdown);

$this->assertEquals($expectedMarkup, $actualMarkup);

$unsafeExtension->setSafeMode(true);
$actualSafeMarkup = $unsafeExtension->text($markdown);

$this->assertEquals($expectedSafeMarkup, $actualSafeMarkup);
}

function data()
{
$data = array();
Expand Down
39 changes: 39 additions & 0 deletions test/SampleExtensions.php
@@ -0,0 +1,39 @@
<?php

class UnsafeExtension extends Parsedown
{
protected function blockFencedCodeComplete($Block)
{
$text = $Block['element']['text']['text'];
unset($Block['element']['text']['text']);

// WARNING: There is almost always a better way of doing things!
//
// This example is one of them, unsafe behaviour is NOT needed here.
// Only use this if you trust the input and have no idea what
// the output HTML will look like (e.g. using an external parser).
$Block['element']['text']['rawHtml'] = "<p>$text</p>";

return $Block;
}
}

class TrustDelegatedExtension extends Parsedown
{
protected function blockFencedCodeComplete($Block)
{
$text = $Block['element']['text']['text'];
unset($Block['element']['text']['text']);

// WARNING: There is almost always a better way of doing things!
//
// This behaviour is NOT needed in the demonstrated case.
// Only use this if you are sure that the result being added into
// rawHtml is safe.
// (e.g. using an external parser with escaping capabilities).
$Block['element']['text']['rawHtml'] = "<p>$text</p>";
$Block['element']['text']['allowRawHtmlInSafeMode'] = true;

return $Block;
}
}

0 comments on commit 21f99b1

Please sign in to comment.