diff --git a/.travis.yml b/.travis.yml index 7a8ba35..6ac8a30 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ matrix: - php: 7.1 - php: 7.2 - php: 7.3 + - php: 7.4 - php: nightly fast_finish: true allow_failures: diff --git a/Parsedown.php b/Parsedown.php index a34b44f..f4249bb 100644 --- a/Parsedown.php +++ b/Parsedown.php @@ -17,7 +17,7 @@ class Parsedown { # ~ - const version = '1.7.3'; + const version = '1.7.4-dev'; # ~ @@ -1489,22 +1489,41 @@ class Parsedown } } + $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'].'>'; diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php index c28cedf..284f5e9 100644 --- a/test/ParsedownTest.php +++ b/test/ParsedownTest.php @@ -1,5 +1,7 @@ assertEquals($expectedMarkup, $actualMarkup); } + function testRawHtml() + { + $markdown = "```php\nfoobar\n```"; + $expectedMarkup = '
foobar
';
+ $expectedSafeMarkup = '<p>foobar</p>
';
+
+ $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 = 'foobar
';
+ $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();
diff --git a/test/SampleExtensions.php b/test/SampleExtensions.php
new file mode 100644
index 0000000..1889146
--- /dev/null
+++ b/test/SampleExtensions.php
@@ -0,0 +1,39 @@
+$text";
+
+ 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'] = "$text
"; + $Block['element']['text']['allowRawHtmlInSafeMode'] = true; + + return $Block; + } +}