From b5951e08c6886d71087c44398be22f7afba91ff6 Mon Sep 17 00:00:00 2001
From: Adrien Loison
Date: Fri, 24 Jun 2016 14:18:01 +0200
Subject: [PATCH 001/106] Create .gitattributes
When using this library, all the files related to tests can be ignored. Tests are only useful when working on the library itself.
---
.gitattributes | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .gitattributes
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..001c45c
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,5 @@
+# Ignore all tests for archive
+/test export-ignore
+/.gitattributes export-ignore
+/.travis.yml export-ignore
+/phpunit.xml.dist export-ignore
From e1bcc1c47279a945af7e04e7f5c1f3615b01a825 Mon Sep 17 00:00:00 2001
From: Daniel Rudolf
Date: Mon, 5 Sep 2016 04:51:28 +0200
Subject: [PATCH 002/106] Fix test/CommonMarkTest.php
---
test/CommonMarkTest.php | 82 ++++++++++++++++++-----------------------
1 file changed, 36 insertions(+), 46 deletions(-)
diff --git a/test/CommonMarkTest.php b/test/CommonMarkTest.php
index 9b8d116..680201b 100644
--- a/test/CommonMarkTest.php
+++ b/test/CommonMarkTest.php
@@ -1,74 +1,64 @@
parsedown = new Parsedown();
+ $this->parsedown->setUrlsLinked(false);
+ }
+
/**
* @dataProvider data
* @param $section
* @param $markdown
* @param $expectedHtml
*/
- function test_($section, $markdown, $expectedHtml)
+ public function testExample($section, $markdown, $expectedHtml)
{
- $Parsedown = new Parsedown();
- $Parsedown->setUrlsLinked(false);
-
- $actualHtml = $Parsedown->text($markdown);
- $actualHtml = $this->normalizeMarkup($actualHtml);
-
+ $actualHtml = $this->parsedown->text($markdown);
$this->assertEquals($expectedHtml, $actualHtml);
}
- function data()
+ /**
+ * @return array
+ */
+ public function data()
{
$spec = file_get_contents(self::SPEC_URL);
+ if ($spec === false) {
+ $this->fail('Unable to load CommonMark spec from ' . self::SPEC_URL);
+ }
+
+ $spec = str_replace("\r\n", "\n", $spec);
$spec = strstr($spec, '', true);
- $tests = array();
+ $matches = array();
+ preg_match_all('/^(?s)`{32} example\n(.*?)\n\.\n(.*?)\n`{32}$|^#{1,6} *(.*?)$/m', $spec, $matches, PREG_SET_ORDER);
+
+ $data = array();
$currentSection = '';
+ foreach ($matches as $match) {
+ if (isset($match[3])) {
+ $currentSection = $match[3];
+ } else {
+ $data[] = array(
+ 'section' => $currentSection,
+ 'markdown' => str_replace('→', "\t", $match[1]),
+ 'expectedHtml' => str_replace('→', "\t", $match[2])
+ );
+ }
+ }
- preg_replace_callback(
- '/^\.\n([\s\S]*?)^\.\n([\s\S]*?)^\.$|^#{1,6} *(.*)$/m',
- function($matches) use ( & $tests, & $currentSection, & $testCount) {
- if (isset($matches[3]) and $matches[3]) {
- $currentSection = $matches[3];
- } else {
- $testCount++;
- $markdown = $matches[1];
- $markdown = preg_replace('/→/', "\t", $markdown);
- $expectedHtml = $matches[2];
- $expectedHtml = $this->normalizeMarkup($expectedHtml);
- $tests []= array(
- $currentSection, # section
- $markdown, # markdown
- $expectedHtml, # html
- );
- }
- },
- $spec
- );
-
- return $tests;
- }
-
- private function normalizeMarkup($markup)
- {
- $markup = preg_replace("/\n+/", "\n", $markup);
- $markup = preg_replace('/^\s+/m', '', $markup);
- $markup = preg_replace('/^((?:<[\w]+>)+)\n/m', '$1', $markup);
- $markup = preg_replace('/\n((?:<\/[\w]+>)+)$/m', '$1', $markup);
- $markup = trim($markup);
-
- return $markup;
+ return $data;
}
}
From 3a46a31e09e5c54f02dc170af83221e0a4b9fef3 Mon Sep 17 00:00:00 2001
From: Daniel Rudolf
Date: Mon, 5 Sep 2016 14:37:34 +0200
Subject: [PATCH 003/106] Fix test/CommonMarkTest.php example regex
---
test/CommonMarkTest.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/CommonMarkTest.php b/test/CommonMarkTest.php
index 680201b..fd07a49 100644
--- a/test/CommonMarkTest.php
+++ b/test/CommonMarkTest.php
@@ -43,7 +43,7 @@ class CommonMarkTest extends PHPUnit_Framework_TestCase
$spec = strstr($spec, '', true);
$matches = array();
- preg_match_all('/^(?s)`{32} example\n(.*?)\n\.\n(.*?)\n`{32}$|^#{1,6} *(.*?)$/m', $spec, $matches, PREG_SET_ORDER);
+ preg_match_all('/^`{32} example\n((?s).*?)\n\.\n((?s).*?)\n`{32}$|^#{1,6} *(.*?)$/m', $spec, $matches, PREG_SET_ORDER);
$data = array();
$currentSection = '';
From d33e736fa32cbab800936c2e910d986b9b32781e Mon Sep 17 00:00:00 2001
From: Daniel Rudolf
Date: Mon, 5 Sep 2016 14:38:47 +0200
Subject: [PATCH 004/106] Add test/CommonMarkTestWeak.php
---
test/CommonMarkTest.php | 4 ++-
test/CommonMarkTestWeak.php | 61 +++++++++++++++++++++++++++++++++++++
test/TestParsedown.php | 4 +++
3 files changed, 68 insertions(+), 1 deletion(-)
create mode 100644 test/CommonMarkTestWeak.php
diff --git a/test/CommonMarkTest.php b/test/CommonMarkTest.php
index fd07a49..c7a1d52 100644
--- a/test/CommonMarkTest.php
+++ b/test/CommonMarkTest.php
@@ -13,7 +13,9 @@ class CommonMarkTest extends PHPUnit_Framework_TestCase
protected function setUp()
{
- $this->parsedown = new Parsedown();
+ require_once(__DIR__ . '/TestParsedown.php');
+
+ $this->parsedown = new TestParsedown();
$this->parsedown->setUrlsLinked(false);
}
diff --git a/test/CommonMarkTestWeak.php b/test/CommonMarkTestWeak.php
new file mode 100644
index 0000000..9b0b730
--- /dev/null
+++ b/test/CommonMarkTestWeak.php
@@ -0,0 +1,61 @@
+parsedown->getTextLevelElements();
+
+ array_walk($textLevelElements, function (&$element) {
+ $element = preg_quote($element, '/');
+ });
+ $this->textLevelElementRegex = '\b(?:' . implode('|', $textLevelElements) . ')\b';
+ }
+
+ /**
+ * @dataProvider data
+ * @param $section
+ * @param $markdown
+ * @param $expectedHtml
+ */
+ public function testExample($section, $markdown, $expectedHtml)
+ {
+ $expectedHtml = $this->cleanupHtml($expectedHtml);
+
+ $actualHtml = $this->parsedown->text($markdown);
+ $actualHtml = $this->cleanupHtml($actualHtml);
+
+ $this->assertEquals($expectedHtml, $actualHtml);
+ }
+
+ protected function cleanupHtml($markup)
+ {
+ // invisible whitespaces at the beginning and end of block elements
+ // however, whitespaces at the beginning of elements do matter
+ $markup = preg_replace(
+ array(
+ '/(<(?!(?:' . $this->textLevelElementRegex . '|\bpre\b))\w+\b[^>]*>(?:<' . $this->textLevelElementRegex . '[^>]*>)?)\s+/s',
+ '/\s+((?:<\/' . $this->textLevelElementRegex . '>)?<\/(?!' . $this->textLevelElementRegex . ')\w+\b>)/s'
+ ),
+ '$1',
+ $markup
+ );
+
+ return $markup;
+ }
+}
diff --git a/test/TestParsedown.php b/test/TestParsedown.php
index 7024dfb..2faa0ab 100644
--- a/test/TestParsedown.php
+++ b/test/TestParsedown.php
@@ -2,4 +2,8 @@
class TestParsedown extends Parsedown
{
+ public function getTextLevelElements()
+ {
+ return $this->textLevelElements;
+ }
}
From 2cacfb8da4d81e8a417e17da20e52e99d5a0e98e Mon Sep 17 00:00:00 2001
From: Daniel Rudolf
Date: Mon, 5 Sep 2016 15:17:52 +0200
Subject: [PATCH 005/106] Improve test/CommonMarkTestWeak.php
---
test/CommonMarkTestWeak.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/CommonMarkTestWeak.php b/test/CommonMarkTestWeak.php
index 9b0b730..751cad5 100644
--- a/test/CommonMarkTestWeak.php
+++ b/test/CommonMarkTestWeak.php
@@ -49,8 +49,8 @@ class CommonMarkTestWeak extends CommonMarkTest
// however, whitespaces at the beginning of elements do matter
$markup = preg_replace(
array(
- '/(<(?!(?:' . $this->textLevelElementRegex . '|\bpre\b))\w+\b[^>]*>(?:<' . $this->textLevelElementRegex . '[^>]*>)?)\s+/s',
- '/\s+((?:<\/' . $this->textLevelElementRegex . '>)?<\/(?!' . $this->textLevelElementRegex . ')\w+\b>)/s'
+ '/(<(?!(?:' . $this->textLevelElementRegex . '|\bpre\b))\w+\b[^>]*>(?:<' . $this->textLevelElementRegex . '[^>]*>)*)\s+/s',
+ '/\s+((?:<\/' . $this->textLevelElementRegex . '>)*<\/(?!' . $this->textLevelElementRegex . ')\w+\b>)/s'
),
'$1',
$markup
From 228d5f4754fbd5e2f2e12437cab121c2f05004d8 Mon Sep 17 00:00:00 2001
From: Daniel Rudolf
Date: Mon, 5 Sep 2016 15:31:07 +0200
Subject: [PATCH 006/106] Improve test/CommonMarkTestWeak.php
---
test/CommonMarkTestWeak.php | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/test/CommonMarkTestWeak.php b/test/CommonMarkTestWeak.php
index 751cad5..e467201 100644
--- a/test/CommonMarkTestWeak.php
+++ b/test/CommonMarkTestWeak.php
@@ -15,12 +15,13 @@ require_once(__DIR__ . '/CommonMarkTest.php');
*/
class CommonMarkTestWeak extends CommonMarkTest
{
+ protected $textLevelElementRegex;
+
protected function setUp()
{
parent::setUp();
$textLevelElements = $this->parsedown->getTextLevelElements();
-
array_walk($textLevelElements, function (&$element) {
$element = preg_quote($element, '/');
});
From 33a23fbfb22902e6268b8459af2784803aec8848 Mon Sep 17 00:00:00 2001
From: Daniel Rudolf
Date: Mon, 5 Sep 2016 21:10:23 +0200
Subject: [PATCH 007/106] Refactor PHPUnit bootstrap
This allows Parsedown extensions (like Parsedown Extra) to reuse existing Parsedown tests. See erusev/parsedown-extra#96 for details.
---
test/CommonMarkTest.php | 2 --
test/ParsedownTest.php | 7 +++----
test/bootstrap.php | 16 +++++++++++++++-
3 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/test/CommonMarkTest.php b/test/CommonMarkTest.php
index c7a1d52..18bca8b 100644
--- a/test/CommonMarkTest.php
+++ b/test/CommonMarkTest.php
@@ -13,8 +13,6 @@ class CommonMarkTest extends PHPUnit_Framework_TestCase
protected function setUp()
{
- require_once(__DIR__ . '/TestParsedown.php');
-
$this->parsedown = new TestParsedown();
$this->parsedown->setUrlsLinked(false);
}
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index c922ab1..7d07183 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -27,7 +27,7 @@ class ParsedownTest extends PHPUnit_Framework_TestCase
*/
protected function initParsedown()
{
- $Parsedown = new Parsedown();
+ $Parsedown = new TestParsedown();
return $Parsedown;
}
@@ -132,15 +132,14 @@ color: red;
comment
<!-- html comment -->
EXPECTED_HTML;
- $parsedownWithNoMarkup = new Parsedown();
+
+ $parsedownWithNoMarkup = new TestParsedown();
$parsedownWithNoMarkup->setMarkupEscaped(true);
$this->assertEquals($expectedHtml, $parsedownWithNoMarkup->text($markdownWithHtml));
}
public function testLateStaticBinding()
{
- include 'test/TestParsedown.php';
-
$parsedown = Parsedown::instance();
$this->assertInstanceOf('Parsedown', $parsedown);
diff --git a/test/bootstrap.php b/test/bootstrap.php
index 5f264d2..76011c9 100644
--- a/test/bootstrap.php
+++ b/test/bootstrap.php
@@ -1,3 +1,17 @@
Date: Mon, 5 Sep 2016 22:04:46 +0200
Subject: [PATCH 008/106] Remove PHPUnit bootstrap in favour of composer
---
.travis.yml | 3 +++
composer.json | 8 ++++++++
phpunit.xml.dist | 4 ++--
test/bootstrap.php | 17 -----------------
4 files changed, 13 insertions(+), 19 deletions(-)
delete mode 100644 test/bootstrap.php
diff --git a/.travis.yml b/.travis.yml
index 256dcf1..5d420e1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,3 +13,6 @@ matrix:
fast_finish: true
allow_failures:
- php: hhvm-nightly
+
+install:
+ - composer install
diff --git a/composer.json b/composer.json
index 28145af..b6a376d 100644
--- a/composer.json
+++ b/composer.json
@@ -17,5 +17,13 @@
},
"autoload": {
"psr-0": {"Parsedown": ""}
+ },
+ "autoload-dev": {
+ "psr-0": {
+ "TestParsedown": "test/",
+ "ParsedownTest": "test/",
+ "CommonMarkTest": "test/",
+ "CommonMarkTestWeak": "test/"
+ }
}
}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index b2d5e9d..4fe3177 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,8 +1,8 @@
-
+
test/ParsedownTest.php
-
\ No newline at end of file
+
diff --git a/test/bootstrap.php b/test/bootstrap.php
deleted file mode 100644
index 76011c9..0000000
--- a/test/bootstrap.php
+++ /dev/null
@@ -1,17 +0,0 @@
-
Date: Thu, 22 Sep 2016 12:21:39 +0200
Subject: [PATCH 009/106] Update Parsedown.php
Made parsedown compatible with html-tags containing dashes.
see https://github.com/erusev/parsedown/issues/407#issuecomment-248833563
---
Parsedown.php | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 646af86..6425b49 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -673,7 +673,7 @@ class Parsedown
return;
}
- if (preg_match('/^<(\w*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches))
+ if (preg_match('/^<(\w[\w-]*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches))
{
$element = strtolower($matches[1]);
@@ -1258,7 +1258,7 @@ class Parsedown
return;
}
- if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w*[ ]*>/s', $Excerpt['text'], $matches))
+ if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w[\w-]*[ ]*>/s', $Excerpt['text'], $matches))
{
return array(
'markup' => $matches[0],
@@ -1274,7 +1274,7 @@ class Parsedown
);
}
- if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches))
+ if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w[\w-]*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches))
{
return array(
'markup' => $matches[0],
From d6d5f53ff4dfd221596e15536ee9a5956133a29f Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sat, 1 Oct 2016 15:56:14 +0100
Subject: [PATCH 010/106] =?UTF-8?q?Fix=20Issue=20#358=20=E2=80=93=20preven?=
=?UTF-8?q?ting=20double=20nested=20links?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
1. Add the ability for a parsed element to enforce that the line handler not parse any (immediate) child elements of a specified type.
2. Use 1. to allow parsed Url elements to tell the line handler not to parse any child Links or Urls where they are immediate children.
---
Parsedown.php | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 646af86..e34efe8 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -987,7 +987,7 @@ class Parsedown
# ~
#
- public function line($text)
+ public function line($text, $non_nestables=array())
{
$markup = '';
@@ -1003,6 +1003,12 @@ class Parsedown
foreach ($this->InlineTypes[$marker] as $inlineType)
{
+
+ if(in_array($inlineType, $non_nestables))
+ {
+ continue;
+ }
+
$Inline = $this->{'inline'.$inlineType}($Excerpt);
if ( ! isset($Inline))
@@ -1183,6 +1189,7 @@ class Parsedown
$Element = array(
'name' => 'a',
'handler' => 'line',
+ 'non_nestables' => array('Url', 'Link'),
'text' => null,
'attributes' => array(
'href' => null,
@@ -1410,9 +1417,11 @@ class Parsedown
{
$markup .= '>';
+ if(!isset($Element['non_nestables'])) $Element['non_nestables'] = array();
+
if (isset($Element['handler']))
{
- $markup .= $this->{$Element['handler']}($Element['text']);
+ $markup .= $this->{$Element['handler']}($Element['text'], $Element['non_nestables']);
}
else
{
From 4d3600f273cc3613cf420408c9016635216c15ea Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sun, 2 Oct 2016 17:37:08 +0100
Subject: [PATCH 011/106] Extend disallowed assertion depth capabilities
I've built on the functionality of feature 1. in the previous commit to allow non nestables to be asserted indefinitely, or to a specified depth.
---
Parsedown.php | 39 ++++++++++++++++++++++++++++++++++++---
1 file changed, 36 insertions(+), 3 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index e34efe8..b708236 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1003,10 +1003,23 @@ class Parsedown
foreach ($this->InlineTypes[$marker] as $inlineType)
{
-
- if(in_array($inlineType, $non_nestables))
+ foreach ($non_nestables as $key => $non_nestable)
{
- continue;
+ if (is_array($non_nestable))
+ {
+
+ if ($non_nestable[0] === $inlineType)
+ {
+ continue 2;
+ }
+ }
+ else
+ {
+ if ($non_nestable === $inlineType)
+ {
+ continue 2;
+ }
+ }
}
$Inline = $this->{'inline'.$inlineType}($Excerpt);
@@ -1030,6 +1043,26 @@ class Parsedown
$Inline['position'] = $markerPosition;
}
+ foreach ($non_nestables as $key => $non_nestable)
+ {
+ if (is_array($non_nestable) && isset($non_nestable[1]) && is_int($non_nestable[1])){
+ if($non_nestable[1] > 1)
+ {
+ $Inline['element']['non_nestables'][] = array($non_nestable[0], $non_nestable[1] -1);
+ }
+
+ }
+ elseif (is_array($non_nestable) && ! isset($non_nestable[1]))
+ {
+ $Inline['element']['non_nestables'][] = array($non_nestable[0]);
+ }
+ elseif ( ! is_array($non_nestable))
+ {
+ $Inline['element']['non_nestables'][] = $non_nestable;
+ }
+ }
+
+
# the text that comes before the inline
$unmarkedText = substr($text, 0, $Inline['position']);
From 50952b3243cbc4585b2e3f6f609445d34bc4d794 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sun, 2 Oct 2016 18:26:13 +0100
Subject: [PATCH 012/106] Line handler may prevent specified element nesting
This commit serves to add comments detailing parts of the new functionality, and to adjust syntax preferences to match that of the surrounding document. The commit title also now reflects the most significant change made.
---
Parsedown.php | 42 ++++++++++++++++++++++--------------------
1 file changed, 22 insertions(+), 20 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index b708236..6b6df9c 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1003,22 +1003,19 @@ class Parsedown
foreach ($this->InlineTypes[$marker] as $inlineType)
{
+ # check to see if the current inline type is nestable in the current context
+
foreach ($non_nestables as $key => $non_nestable)
{
- if (is_array($non_nestable))
+ # case that we used array syntax
+ if (is_array($non_nestable) and $non_nestable[0] === $inlineType)
{
-
- if ($non_nestable[0] === $inlineType)
- {
- continue 2;
- }
+ continue 2;
}
- else
+ # case that we used plain string syntax
+ elseif ( ! is_array($non_nestable) and $non_nestable === $inlineType)
{
- if ($non_nestable === $inlineType)
- {
- continue 2;
- }
+ continue 2;
}
}
@@ -1043,25 +1040,27 @@ class Parsedown
$Inline['position'] = $markerPosition;
}
+ # cause the new element to 'inherit' our non nestables, if appropriate
+
foreach ($non_nestables as $key => $non_nestable)
{
- if (is_array($non_nestable) && isset($non_nestable[1]) && is_int($non_nestable[1])){
- if($non_nestable[1] > 1)
- {
- $Inline['element']['non_nestables'][] = array($non_nestable[0], $non_nestable[1] -1);
- }
-
+ # array syntax, and depth is sufficient to pass on
+ if (is_array($non_nestable) and isset($non_nestable[1]) and
+ is_int($non_nestable[1]) and $non_nestable[1] > 1)
+ {
+ $Inline['element']['non_nestables'][] = array($non_nestable[0], $non_nestable[1] -1);
}
- elseif (is_array($non_nestable) && ! isset($non_nestable[1]))
+ # array syntax, and depth is indefinite
+ elseif (is_array($non_nestable) and ! isset($non_nestable[1]))
{
$Inline['element']['non_nestables'][] = array($non_nestable[0]);
}
+ # string syntax, so depth is indefinite
elseif ( ! is_array($non_nestable))
{
$Inline['element']['non_nestables'][] = $non_nestable;
}
}
-
# the text that comes before the inline
$unmarkedText = substr($text, 0, $Inline['position']);
@@ -1450,7 +1449,10 @@ class Parsedown
{
$markup .= '>';
- if(!isset($Element['non_nestables'])) $Element['non_nestables'] = array();
+ if (!isset($Element['non_nestables']))
+ {
+ $Element['non_nestables'] = array();
+ }
if (isset($Element['handler']))
{
From a81aedeb109ed16270bbf6aaead7b41e5593caeb Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Tue, 4 Oct 2016 15:27:11 +0100
Subject: [PATCH 013/106] Line handler may prevent specified element nesting
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Removed granularity controls – elements are assumed to be non nestable indefinitely once declared.
---
Parsedown.php | 34 +++++-----------------------------
1 file changed, 5 insertions(+), 29 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 6b6df9c..f1e09d9 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1005,18 +1005,9 @@ class Parsedown
{
# check to see if the current inline type is nestable in the current context
- foreach ($non_nestables as $key => $non_nestable)
+ if (in_array($inlineType, $non_nestables))
{
- # case that we used array syntax
- if (is_array($non_nestable) and $non_nestable[0] === $inlineType)
- {
- continue 2;
- }
- # case that we used plain string syntax
- elseif ( ! is_array($non_nestable) and $non_nestable === $inlineType)
- {
- continue 2;
- }
+ continue;
}
$Inline = $this->{'inline'.$inlineType}($Excerpt);
@@ -1040,26 +1031,11 @@ class Parsedown
$Inline['position'] = $markerPosition;
}
- # cause the new element to 'inherit' our non nestables, if appropriate
+ # cause the new element to 'inherit' our non nestables
- foreach ($non_nestables as $key => $non_nestable)
+ foreach ($non_nestables as $non_nestable)
{
- # array syntax, and depth is sufficient to pass on
- if (is_array($non_nestable) and isset($non_nestable[1]) and
- is_int($non_nestable[1]) and $non_nestable[1] > 1)
- {
- $Inline['element']['non_nestables'][] = array($non_nestable[0], $non_nestable[1] -1);
- }
- # array syntax, and depth is indefinite
- elseif (is_array($non_nestable) and ! isset($non_nestable[1]))
- {
- $Inline['element']['non_nestables'][] = array($non_nestable[0]);
- }
- # string syntax, so depth is indefinite
- elseif ( ! is_array($non_nestable))
- {
- $Inline['element']['non_nestables'][] = $non_nestable;
- }
+ $Inline['element']['non_nestables'][] = $non_nestable;
}
# the text that comes before the inline
From 543a6c4175a1debd148e933fb271f5b8f088b199 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Tue, 4 Oct 2016 18:59:36 +0100
Subject: [PATCH 014/106] Line handler may prevent specified element nesting
Check if array is empty to shave some performance hits in the case than no non nestables are present.
---
Parsedown.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Parsedown.php b/Parsedown.php
index f1e09d9..fc2158f 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1005,7 +1005,7 @@ class Parsedown
{
# check to see if the current inline type is nestable in the current context
- if (in_array($inlineType, $non_nestables))
+ if ( ! empty($non_nestables) and in_array($inlineType, $non_nestables))
{
continue;
}
From 3aef89b3994d942d4eb85d6df0c8c43a157ac5d7 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sat, 8 Oct 2016 17:54:04 +0100
Subject: [PATCH 015/106] Line handler may prevent specified element nesting
Swap `under_scores` for `camelCasing`
---
Parsedown.php | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index fc2158f..e2b9d60 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -987,7 +987,7 @@ class Parsedown
# ~
#
- public function line($text, $non_nestables=array())
+ public function line($text, $nonNestables=array())
{
$markup = '';
@@ -1005,7 +1005,7 @@ class Parsedown
{
# check to see if the current inline type is nestable in the current context
- if ( ! empty($non_nestables) and in_array($inlineType, $non_nestables))
+ if ( ! empty($nonNestables) and in_array($inlineType, $nonNestables))
{
continue;
}
@@ -1033,9 +1033,9 @@ class Parsedown
# cause the new element to 'inherit' our non nestables
- foreach ($non_nestables as $non_nestable)
+ foreach ($nonNestables as $non_nestable)
{
- $Inline['element']['non_nestables'][] = $non_nestable;
+ $Inline['element']['nonNestables'][] = $non_nestable;
}
# the text that comes before the inline
@@ -1197,7 +1197,7 @@ class Parsedown
$Element = array(
'name' => 'a',
'handler' => 'line',
- 'non_nestables' => array('Url', 'Link'),
+ 'nonNestables' => array('Url', 'Link'),
'text' => null,
'attributes' => array(
'href' => null,
@@ -1425,14 +1425,14 @@ class Parsedown
{
$markup .= '>';
- if (!isset($Element['non_nestables']))
+ if (!isset($Element['nonNestables']))
{
- $Element['non_nestables'] = array();
+ $Element['nonNestables'] = array();
}
if (isset($Element['handler']))
{
- $markup .= $this->{$Element['handler']}($Element['text'], $Element['non_nestables']);
+ $markup .= $this->{$Element['handler']}($Element['text'], $Element['nonNestables']);
}
else
{
From f0587d41a9783e4c3ad817e74909744d072d2874 Mon Sep 17 00:00:00 2001
From: Daniel Rudolf
Date: Sun, 9 Oct 2016 14:17:03 +0200
Subject: [PATCH 016/106] Add test/CommonMarkTestWeak.php to .travis.yml
Failing tests don't break builds on purpose, Parsedown doesn't fully comply with the CommonMark specs at the moment. We should switch to test/CommonMarkTest.php later, see #423 for details.
---
.travis.yml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.travis.yml b/.travis.yml
index 5d420e1..09c8e2b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -16,3 +16,6 @@ matrix:
install:
- composer install
+
+script:
+ - phpunit test/CommonMarkTestWeak.php || true
From be671e72a39484ff9354cd7f1177d5901e1bdf9b Mon Sep 17 00:00:00 2001
From: Daniel Rudolf
Date: Sun, 9 Oct 2016 14:21:17 +0200
Subject: [PATCH 017/106] Don't let Travis skip Parsedown's phpunit tests
---
.travis.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.travis.yml b/.travis.yml
index 09c8e2b..3320963 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,4 +18,5 @@ install:
- composer install
script:
+ - phpunit
- phpunit test/CommonMarkTestWeak.php || true
From 2423644d728075dfd55199e6314d4ad3b24d9072 Mon Sep 17 00:00:00 2001
From: Daniel Rudolf
Date: Wed, 12 Oct 2016 02:01:40 +0200
Subject: [PATCH 018/106] Move test/CommonMarkTest.php to
test/CommonMarkTestStrict.php
Add parameter `$id` to CommonMark tests
---
test/{CommonMarkTest.php => CommonMarkTestStrict.php} | 7 +++++--
test/CommonMarkTestWeak.php | 7 ++++---
2 files changed, 9 insertions(+), 5 deletions(-)
rename test/{CommonMarkTest.php => CommonMarkTestStrict.php} (88%)
diff --git a/test/CommonMarkTest.php b/test/CommonMarkTestStrict.php
similarity index 88%
rename from test/CommonMarkTest.php
rename to test/CommonMarkTestStrict.php
index 18bca8b..bd16ffa 100644
--- a/test/CommonMarkTest.php
+++ b/test/CommonMarkTestStrict.php
@@ -5,7 +5,7 @@
*
* @link http://commonmark.org/ CommonMark
*/
-class CommonMarkTest extends PHPUnit_Framework_TestCase
+class CommonMarkTestStrict extends PHPUnit_Framework_TestCase
{
const SPEC_URL = 'https://raw.githubusercontent.com/jgm/stmd/master/spec.txt';
@@ -19,11 +19,12 @@ class CommonMarkTest extends PHPUnit_Framework_TestCase
/**
* @dataProvider data
+ * @param $id
* @param $section
* @param $markdown
* @param $expectedHtml
*/
- public function testExample($section, $markdown, $expectedHtml)
+ public function testExample($id, $section, $markdown, $expectedHtml)
{
$actualHtml = $this->parsedown->text($markdown);
$this->assertEquals($expectedHtml, $actualHtml);
@@ -46,12 +47,14 @@ class CommonMarkTest extends PHPUnit_Framework_TestCase
preg_match_all('/^`{32} example\n((?s).*?)\n\.\n((?s).*?)\n`{32}$|^#{1,6} *(.*?)$/m', $spec, $matches, PREG_SET_ORDER);
$data = array();
+ $currentId = 0;
$currentSection = '';
foreach ($matches as $match) {
if (isset($match[3])) {
$currentSection = $match[3];
} else {
$data[] = array(
+ 'id' => ++$currentId,
'section' => $currentSection,
'markdown' => str_replace('→', "\t", $match[1]),
'expectedHtml' => str_replace('→', "\t", $match[2])
diff --git a/test/CommonMarkTestWeak.php b/test/CommonMarkTestWeak.php
index e467201..ef4081a 100644
--- a/test/CommonMarkTestWeak.php
+++ b/test/CommonMarkTestWeak.php
@@ -1,5 +1,5 @@
cleanupHtml($expectedHtml);
From a9f696f7bb413cbf7b14b744806fce504353e072 Mon Sep 17 00:00:00 2001
From: Daniel Rudolf
Date: Thu, 13 Oct 2016 22:16:46 +0200
Subject: [PATCH 019/106] Improve CommonMark spec example regex
CommonMark spec example [#170](http://spec.commonmark.org/0.26/#example-170) has a empty HTML result.
---
test/CommonMarkTestStrict.php | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/test/CommonMarkTestStrict.php b/test/CommonMarkTestStrict.php
index bd16ffa..3837738 100644
--- a/test/CommonMarkTestStrict.php
+++ b/test/CommonMarkTestStrict.php
@@ -7,7 +7,7 @@
*/
class CommonMarkTestStrict extends PHPUnit_Framework_TestCase
{
- const SPEC_URL = 'https://raw.githubusercontent.com/jgm/stmd/master/spec.txt';
+ const SPEC_URL = 'https://raw.githubusercontent.com/jgm/CommonMark/master/spec.txt';
protected $parsedown;
@@ -44,7 +44,7 @@ class CommonMarkTestStrict extends PHPUnit_Framework_TestCase
$spec = strstr($spec, '', true);
$matches = array();
- preg_match_all('/^`{32} example\n((?s).*?)\n\.\n((?s).*?)\n`{32}$|^#{1,6} *(.*?)$/m', $spec, $matches, PREG_SET_ORDER);
+ preg_match_all('/^`{32} example\n((?s).*?)\n\.\n(?:|((?s).*?)\n)`{32}$|^#{1,6} *(.*?)$/m', $spec, $matches, PREG_SET_ORDER);
$data = array();
$currentId = 0;
@@ -53,11 +53,15 @@ class CommonMarkTestStrict extends PHPUnit_Framework_TestCase
if (isset($match[3])) {
$currentSection = $match[3];
} else {
- $data[] = array(
- 'id' => ++$currentId,
+ $currentId++;
+ $markdown = str_replace('→', "\t", $match[1]);
+ $expectedHtml = isset($match[2]) ? str_replace('→', "\t", $match[2]) : '';
+
+ $data[$currentId] = array(
+ 'id' => $currentId,
'section' => $currentSection,
- 'markdown' => str_replace('→', "\t", $match[1]),
- 'expectedHtml' => str_replace('→', "\t", $match[2])
+ 'markdown' => $markdown,
+ 'expectedHtml' => $expectedHtml
);
}
}
From ae0211a84c92a1eab7892a7c1876b5a5f7402f28 Mon Sep 17 00:00:00 2001
From: Daniel Rudolf
Date: Thu, 13 Oct 2016 22:17:03 +0200
Subject: [PATCH 020/106] Travis: Add PHP nightly
---
.travis.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.travis.yml b/.travis.yml
index 3320963..3259ca8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,12 +6,14 @@ php:
- 5.5
- 5.4
- 5.3
+ - nightly
- hhvm
- hhvm-nightly
matrix:
fast_finish: true
allow_failures:
+ - php: nightly
- php: hhvm-nightly
install:
From 8876c0984e64ace957f3e38abfc3b3961bc40b88 Mon Sep 17 00:00:00 2001
From: James Vickery
Date: Tue, 25 Oct 2016 15:10:22 +0100
Subject: [PATCH 021/106] Tiny grammar correction
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 7ef230f..4ce37c5 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [t
**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 start with a `-` then it perhaps belong 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).
+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 start with a `-` then it perhaps 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.
From 7a92a31739be3401e6cd961d548398dcc67bc064 Mon Sep 17 00:00:00 2001
From: James Vickery
Date: Tue, 25 Oct 2016 15:22:17 +0100
Subject: [PATCH 022/106] Grammar update
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 4ce37c5..7907787 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [t
**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 start with a `-` then it perhaps 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).
+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.
From bc21988fe5e6cca8aae6928c0374779fd82710ed Mon Sep 17 00:00:00 2001
From: Yoan Blanc
Date: Tue, 1 Nov 2016 18:27:37 +0100
Subject: [PATCH 023/106] Fix include from ParsedownTest
I wasn't able to run all the tests from ParsedownExtra because of it.
---
test/ParsedownTest.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index c922ab1..323dace 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -139,7 +139,7 @@ EXPECTED_HTML;
public function testLateStaticBinding()
{
- include 'test/TestParsedown.php';
+ include __DIR__ . '/TestParsedown.php';
$parsedown = Parsedown::instance();
$this->assertInstanceOf('Parsedown', $parsedown);
From 48351504deb0336e265a9453cf9acab04fadae6d Mon Sep 17 00:00:00 2001
From: gene_sis
Date: Fri, 6 Jan 2017 20:40:19 +0100
Subject: [PATCH 024/106] adjust two regex pattern within inlineLink() to
reduce backtracking add test with base64 image
---
Parsedown.php | 4 ++--
test/data/inline_link.html | 3 ++-
test/data/inline_link.md | 4 +++-
3 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 4737eee..d7b5537 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1204,7 +1204,7 @@ class Parsedown
$remainder = $Excerpt['text'];
- if (preg_match('/\[((?:[^][]|(?R))*)\]/', $remainder, $matches))
+ if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches))
{
$Element['text'] = $matches[1];
@@ -1217,7 +1217,7 @@ class Parsedown
return;
}
- if (preg_match('/^[(]((?:[^ ()]|[(][^ )]+[)])+)(?:[ ]+("[^"]*"|\'[^\']*\'))?[)]/', $remainder, $matches))
+ if (preg_match('/^[(]((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?[)]/', $remainder, $matches))
{
$Element['attributes']['href'] = $matches[1];
diff --git a/test/data/inline_link.html b/test/data/inline_link.html
index 5ad564a..cef29cf 100644
--- a/test/data/inline_link.html
+++ b/test/data/inline_link.html
@@ -3,4 +3,5 @@
(link) in parentheses
link
- and text
\ No newline at end of file
+ and text
+ and text
\ No newline at end of file
diff --git a/test/data/inline_link.md b/test/data/inline_link.md
index 6bac0b3..1ba24b7 100644
--- a/test/data/inline_link.md
+++ b/test/data/inline_link.md
@@ -8,4 +8,6 @@
[![MD Logo](http://parsedown.org/md.png)](http://example.com)
-[![MD Logo](http://parsedown.org/md.png) and text](http://example.com)
\ No newline at end of file
+[![MD Logo](http://parsedown.org/md.png) and text](http://example.com)
+
+[![MD Logo](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAUCAYAAADskT9PAAAKQWlDQ1BJQ0MgUHJvZmlsZQAASA2dlndUU9kWh8+9N73QEiIgJfQaegkg0jtIFQRRiUmAUAKGhCZ2RAVGFBEpVmRUwAFHhyJjRRQLg4Ji1wnyEFDGwVFEReXdjGsJ7601896a/cdZ39nnt9fZZ+9917oAUPyCBMJ0WAGANKFYFO7rwVwSE8vE9wIYEAEOWAHA4WZmBEf4RALU/L09mZmoSMaz9u4ugGS72yy/UCZz1v9/kSI3QyQGAApF1TY8fiYX5QKUU7PFGTL/BMr0lSkyhjEyFqEJoqwi48SvbPan5iu7yZiXJuShGlnOGbw0noy7UN6aJeGjjAShXJgl4GejfAdlvVRJmgDl9yjT0/icTAAwFJlfzOcmoWyJMkUUGe6J8gIACJTEObxyDov5OWieAHimZ+SKBIlJYqYR15hp5ejIZvrxs1P5YjErlMNN4Yh4TM/0tAyOMBeAr2+WRQElWW2ZaJHtrRzt7VnW5mj5v9nfHn5T/T3IevtV8Sbsz55BjJ5Z32zsrC+9FgD2JFqbHbO+lVUAtG0GQOXhrE/vIADyBQC03pzzHoZsXpLE4gwnC4vs7GxzAZ9rLivoN/ufgm/Kv4Y595nL7vtWO6YXP4EjSRUzZUXlpqemS0TMzAwOl89k/fcQ/+PAOWnNycMsnJ/AF/GF6FVR6JQJhIlou4U8gViQLmQKhH/V4X8YNicHGX6daxRodV8AfYU5ULhJB8hvPQBDIwMkbj96An3rWxAxCsi+vGitka9zjzJ6/uf6Hwtcim7hTEEiU+b2DI9kciWiLBmj34RswQISkAd0oAo0gS4wAixgDRyAM3AD3iAAhIBIEAOWAy5IAmlABLJBPtgACkEx2AF2g2pwANSBetAEToI2cAZcBFfADXALDIBHQAqGwUswAd6BaQiC8BAVokGqkBakD5lC1hAbWgh5Q0FQOBQDxUOJkBCSQPnQJqgYKoOqoUNQPfQjdBq6CF2D+qAH0CA0Bv0BfYQRmALTYQ3YALaA2bA7HAhHwsvgRHgVnAcXwNvhSrgWPg63whfhG/AALIVfwpMIQMgIA9FGWAgb8URCkFgkAREha5EipAKpRZqQDqQbuY1IkXHkAwaHoWGYGBbGGeOHWYzhYlZh1mJKMNWYY5hWTBfmNmYQM4H5gqVi1bGmWCesP3YJNhGbjS3EVmCPYFuwl7ED2GHsOxwOx8AZ4hxwfrgYXDJuNa4Etw/XjLuA68MN4SbxeLwq3hTvgg/Bc/BifCG+Cn8cfx7fjx/GvyeQCVoEa4IPIZYgJGwkVBAaCOcI/YQRwjRRgahPdCKGEHnEXGIpsY7YQbxJHCZOkxRJhiQXUiQpmbSBVElqIl0mPSa9IZPJOmRHchhZQF5PriSfIF8lD5I/UJQoJhRPShxFQtlOOUq5QHlAeUOlUg2obtRYqpi6nVpPvUR9Sn0vR5Mzl/OX48mtk6uRa5Xrl3slT5TXl3eXXy6fJ18hf0r+pvy4AlHBQMFTgaOwVqFG4bTCPYVJRZqilWKIYppiiWKD4jXFUSW8koGStxJPqUDpsNIlpSEaQtOledK4tE20Otpl2jAdRzek+9OT6cX0H+i99AllJWVb5SjlHOUa5bPKUgbCMGD4M1IZpYyTjLuMj/M05rnP48/bNq9pXv+8KZX5Km4qfJUilWaVAZWPqkxVb9UU1Z2qbapP1DBqJmphatlq+9Uuq43Pp893ns+dXzT/5PyH6rC6iXq4+mr1w+o96pMamhq+GhkaVRqXNMY1GZpumsma5ZrnNMe0aFoLtQRa5VrntV4wlZnuzFRmJbOLOaGtru2nLdE+pN2rPa1jqLNYZ6NOs84TXZIuWzdBt1y3U3dCT0svWC9fr1HvoT5Rn62fpL9Hv1t/ysDQINpgi0GbwaihiqG/YZ5ho+FjI6qRq9Eqo1qjO8Y4Y7ZxivE+41smsImdSZJJjclNU9jU3lRgus+0zwxr5mgmNKs1u8eisNxZWaxG1qA5wzzIfKN5m/krCz2LWIudFt0WXyztLFMt6ywfWSlZBVhttOqw+sPaxJprXWN9x4Zq42Ozzqbd5rWtqS3fdr/tfTuaXbDdFrtOu8/2DvYi+yb7MQc9h3iHvQ732HR2KLuEfdUR6+jhuM7xjOMHJ3snsdNJp9+dWc4pzg3OowsMF/AX1C0YctFx4bgccpEuZC6MX3hwodRV25XjWuv6zE3Xjed2xG3E3dg92f24+ysPSw+RR4vHlKeT5xrPC16Il69XkVevt5L3Yu9q76c+Oj6JPo0+E752vqt9L/hh/QL9dvrd89fw5/rX+08EOASsCegKpARGBFYHPgsyCRIFdQTDwQHBu4IfL9JfJFzUFgJC/EN2hTwJNQxdFfpzGC4sNKwm7Hm4VXh+eHcELWJFREPEu0iPyNLIR4uNFksWd0bJR8VF1UdNRXtFl0VLl1gsWbPkRoxajCCmPRYfGxV7JHZyqffS3UuH4+ziCuPuLjNclrPs2nK15anLz66QX8FZcSoeGx8d3xD/iRPCqeVMrvRfuXflBNeTu4f7kufGK+eN8V34ZfyRBJeEsoTRRJfEXYljSa5JFUnjAk9BteB1sl/ygeSplJCUoykzqdGpzWmEtPi000IlYYqwK10zPSe9L8M0ozBDuspp1e5VE6JA0ZFMKHNZZruYjv5M9UiMJJslg1kLs2qy3mdHZZ/KUcwR5vTkmuRuyx3J88n7fjVmNXd1Z752/ob8wTXuaw6thdauXNu5Tnddwbrh9b7rj20gbUjZ8MtGy41lG99uit7UUaBRsL5gaLPv5sZCuUJR4b0tzlsObMVsFWzt3WazrWrblyJe0fViy+KK4k8l3JLr31l9V/ndzPaE7b2l9qX7d+B2CHfc3em681iZYlle2dCu4F2t5czyovK3u1fsvlZhW3FgD2mPZI+0MqiyvUqvakfVp+qk6oEaj5rmvep7t+2d2sfb17/fbX/TAY0DxQc+HhQcvH/I91BrrUFtxWHc4azDz+ui6rq/Z39ff0TtSPGRz0eFR6XHwo911TvU1zeoN5Q2wo2SxrHjccdv/eD1Q3sTq+lQM6O5+AQ4ITnx4sf4H++eDDzZeYp9qukn/Z/2ttBailqh1tzWibakNml7THvf6YDTnR3OHS0/m/989Iz2mZqzymdLz5HOFZybOZ93fvJCxoXxi4kXhzpXdD66tOTSna6wrt7LgZevXvG5cqnbvfv8VZerZ645XTt9nX297Yb9jdYeu56WX+x+aem172296XCz/ZbjrY6+BX3n+l37L972un3ljv+dGwOLBvruLr57/17cPel93v3RB6kPXj/Mejj9aP1j7OOiJwpPKp6qP6391fjXZqm99Oyg12DPs4hnj4a4Qy//lfmvT8MFz6nPK0a0RupHrUfPjPmM3Xqx9MXwy4yX0+OFvyn+tveV0auffnf7vWdiycTwa9HrmT9K3qi+OfrW9m3nZOjk03dp76anit6rvj/2gf2h+2P0x5Hp7E/4T5WfjT93fAn88ngmbWbm3/eE8/syOll+AAAACXBIWXMAAAsTAAALEwEAmpwYAAAEImlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MTwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6Q29tcHJlc3Npb24+NTwvdGlmZjpDb21wcmVzc2lvbj4KICAgICAgICAgPHRpZmY6WFJlc29sdXRpb24+NzI8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjcyPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MzI8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxZRGltZW5zaW9uPjIwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6QmFnLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxNS0wNi0xNFQxOTowNjo1OTwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjI8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+Ch7v5WoAAAGgSURBVEgNYywtLbVnYmLqYmBgMANieoJT//79K2MBWr4CaKsEPW2G2mUGspsFZnlnZycjPR1RXl7+H2Q3Ez0txWbXgDsAFAUYABo8YPH////HdXV1LUZWVFZWFsvIyLgIJoYt+pDNwCYP00swBIAWzaysrNSCaQCxgWLTYHxKaawhgGYoJzC7rC4sLDQBiYPYQIoHTQ3ZXGIcADJci42NDeZreGiQbSuSRmKiABb/CUB9IMwAjAKYGIhLESAYAj9//kwH+t4YaAvM59c4ODiyvn//HotuMzDh9QLFirCIg/I8CPQBE2QxhAkhCYZAf3//d2CJFQpU/h2EQeyGhoYvyIbA2FDDl8H4aPQydMtB8gQdAFLU3t5+DRjsWSAMYoPEcAFOTs5EoNw+NPl9UHE0YQYGglEA09HR0bEAxsZHA0PnFzAqgoBq9gIxKOrOAnEQSBxIYwCiQgBDFwEBYFB/BEaVJ7AQ2wGiQXxcWhhhJRZQ0UBURsSlAVyup4Y4TaKAFIeBouAJUIM0KZqoqPYpEzBrpQANfEFFQ4k16gXIbgCggnKoJ5DJdwAAAABJRU5ErkJggg==) and text](http://example.com)
\ No newline at end of file
From 0172d779d73d8d7ad94f9c486f8560a77d184389 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sat, 21 Jan 2017 11:06:41 +0000
Subject: [PATCH 025/106] Trim surrounding whitespace from URL in inlineLink
Fixes https://github.com/erusev/parsedown-extra/issues/103
---
Parsedown.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Parsedown.php b/Parsedown.php
index d7b5537..3e25b0d 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1217,7 +1217,7 @@ class Parsedown
return;
}
- if (preg_match('/^[(]((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?[)]/', $remainder, $matches))
+ if (preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?\s*[)]/', $remainder, $matches))
{
$Element['attributes']['href'] = $matches[1];
From 7081afe8cbf4081b49839c6789f45b2ef508ce5b Mon Sep 17 00:00:00 2001
From: Marek Skiba
Date: Thu, 2 Mar 2017 12:43:51 +0100
Subject: [PATCH 026/106] Removed double semicolon
---
Parsedown.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Parsedown.php b/Parsedown.php
index 3e25b0d..20863a7 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -448,7 +448,7 @@ class Parsedown
return $Block;
}
- $Block['element']['text']['text'] .= "\n".$Line['body'];;
+ $Block['element']['text']['text'] .= "\n".$Line['body'];
return $Block;
}
From bd0e31a7ddfa3c45744599077b4c6b97ca2fbeb7 Mon Sep 17 00:00:00 2001
From: Haralan Dobrev
Date: Fri, 10 Mar 2017 01:04:53 +0200
Subject: [PATCH 027/106] Add Symfony demo to "Who uses it?"
https://github.com/symfony/symfony-demo/blob/409a65b373cb47bc346742c452af5c7b1424f5cd/composer.json#L24
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 7907787..4e5659a 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,7 @@ It passes most of the CommonMark tests. Most of the tests that don't pass deal w
**Who uses it?**
-[phpDocumentor](http://www.phpdoc.org/), [October CMS](http://octobercms.com/), [Bolt CMS](http://bolt.cm/), [Kirby CMS](http://getkirby.com/), [Grav CMS](http://getgrav.org/), [Statamic CMS](http://www.statamic.com/), [Herbie CMS](http://www.getherbie.org/), [RaspberryPi.org](http://www.raspberrypi.org/) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
+[phpDocumentor](http://www.phpdoc.org/), [October CMS](http://octobercms.com/), [Bolt CMS](http://bolt.cm/), [Kirby CMS](http://getkirby.com/), [Grav CMS](http://getgrav.org/), [Statamic CMS](http://www.statamic.com/), [Herbie CMS](http://www.getherbie.org/), [RaspberryPi.org](http://www.raspberrypi.org/), [Symfony demo](https://github.com/symfony/symfony-demo) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
**How can I help?**
From 0a09d5ad45b0f077f67493131e4e3f3ccde14389 Mon Sep 17 00:00:00 2001
From: Emanuil Rusev
Date: Thu, 23 Mar 2017 20:21:05 +0200
Subject: [PATCH 028/106] update tests to reflect changes in phpunit 6.0
---
test/CommonMarkTest.php | 2 +-
test/ParsedownTest.php | 2 +-
test/bootstrap.php | 6 +++++-
3 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/test/CommonMarkTest.php b/test/CommonMarkTest.php
index 9b8d116..37ed9fe 100644
--- a/test/CommonMarkTest.php
+++ b/test/CommonMarkTest.php
@@ -8,7 +8,7 @@
* @link http://commonmark.org/ CommonMark
* @link http://git.io/8WtRvQ JavaScript test runner
*/
-class CommonMarkTest extends PHPUnit_Framework_TestCase
+class CommonMarkTest extends \PHPUnit\Framework\TestCase
{
const SPEC_URL = 'https://raw.githubusercontent.com/jgm/stmd/master/spec.txt';
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index 323dace..7e552e8 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -1,6 +1,6 @@
Date: Wed, 29 Mar 2017 19:04:15 +0300
Subject: [PATCH 029/106] add kbd to text-level elements
---
Parsedown.php | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 20863a7..f5dd0fa 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1539,10 +1539,10 @@ class Parsedown
'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing',
'i', 'rp', 'del', 'code', 'strike', 'marquee',
'q', 'rt', 'ins', 'font', 'strong',
- 's', 'tt', 'sub', 'mark',
- 'u', 'xm', 'sup', 'nobr',
- 'var', 'ruby',
- 'wbr', 'span',
- 'time',
+ 's', 'tt', 'kbd', 'mark',
+ 'u', 'xm', 'sub', 'nobr',
+ 'sup', 'ruby',
+ 'var', 'span',
+ 'wbr', 'time',
);
}
From 4367f89a74ecd7414d01f0411a8be6dba7071b08 Mon Sep 17 00:00:00 2001
From: Emanuil Rusev
Date: Wed, 29 Mar 2017 19:30:24 +0300
Subject: [PATCH 030/106] attempt to fix failing builds on 5.3
---
test/CommonMarkTest.php | 2 +-
test/ParsedownTest.php | 2 +-
test/bootstrap.php | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/test/CommonMarkTest.php b/test/CommonMarkTest.php
index 37ed9fe..9b8d116 100644
--- a/test/CommonMarkTest.php
+++ b/test/CommonMarkTest.php
@@ -8,7 +8,7 @@
* @link http://commonmark.org/ CommonMark
* @link http://git.io/8WtRvQ JavaScript test runner
*/
-class CommonMarkTest extends \PHPUnit\Framework\TestCase
+class CommonMarkTest extends PHPUnit_Framework_TestCase
{
const SPEC_URL = 'https://raw.githubusercontent.com/jgm/stmd/master/spec.txt';
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index 7e552e8..323dace 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -1,6 +1,6 @@
Date: Sat, 25 Mar 2017 14:28:43 +0000
Subject: [PATCH 031/106] blockmarkup ends on interrupt by newline (CommonMark
compliance)
---
Parsedown.php | 29 ++---------------------------
1 file changed, 2 insertions(+), 27 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index f5dd0fa..e516f6b 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -683,7 +683,7 @@ class Parsedown
return;
}
- if (preg_match('/^<(\w*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches))
+ if (preg_match('/^<[\/]?+(\w*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\/)?>/', $Line['text'], $matches))
{
$element = strtolower($matches[1]);
@@ -694,7 +694,6 @@ class Parsedown
$Block = array(
'name' => $matches[1],
- 'depth' => 0,
'markup' => $Line['text'],
);
@@ -730,35 +729,11 @@ class Parsedown
protected function blockMarkupContinue($Line, array $Block)
{
- if (isset($Block['closed']))
+ if (isset($Block['closed']) or isset($Block['interrupted']))
{
return;
}
- if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open
- {
- $Block['depth'] ++;
- }
-
- if (preg_match('/(.*?)<\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close
- {
- if ($Block['depth'] > 0)
- {
- $Block['depth'] --;
- }
- else
- {
- $Block['closed'] = true;
- }
- }
-
- if (isset($Block['interrupted']))
- {
- $Block['markup'] .= "\n";
-
- unset($Block['interrupted']);
- }
-
$Block['markup'] .= "\n".$Line['body'];
return $Block;
From 1d0af35f10ed6b7e2a5841d032ac6a1de5b6f939 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sat, 25 Mar 2017 14:47:36 +0000
Subject: [PATCH 032/106] update test to result generated by CommonMark
reference parser
---
test/data/sparse_html.html | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/test/data/sparse_html.html b/test/data/sparse_html.html
index 9e89627..6e0213f 100644
--- a/test/data/sparse_html.html
+++ b/test/data/sparse_html.html
@@ -1,8 +1,6 @@
line 1
-
-line 2
-line 3
-
-line 4
+
line 2
+line 3
+
line 4
\ No newline at end of file
From 1140613fc7aa1393a6274812deab253b90027ae7 Mon Sep 17 00:00:00 2001
From: naNuke
Date: Wed, 21 Jan 2015 03:50:36 +0100
Subject: [PATCH 033/106] Prevent various XSS attacks
---
Parsedown.php | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/Parsedown.php b/Parsedown.php
index f5dd0fa..5d810de 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -75,6 +75,15 @@ class Parsedown
protected $urlsLinked = true;
+ function setSafeLinksEnabled($safeLinksEnabled)
+ {
+ $this->safeLinksEnabled = $safeLinksEnabled;
+
+ return $this;
+ }
+
+ protected $safeLinksEnabled = true;
+
#
# Lines
#
@@ -1253,7 +1262,13 @@ class Parsedown
$Element['attributes']['title'] = $Definition['title'];
}
- $Element['attributes']['href'] = str_replace(array('&', '<'), array('&', '<'), $Element['attributes']['href']);
+ if ( $this->safeLinksEnabled && stripos($Element['attributes']['href'], 'javascript:') === 0 )
+ {
+ return;
+ }
+
+ $Element['attributes']['href'] = htmlspecialchars($Element['attributes']['href']);
+ $Element['text'] = htmlspecialchars($Element['text']);
return array(
'extent' => $extent,
From bf5105cb1a7a2656d134ab35456a727959574e7d Mon Sep 17 00:00:00 2001
From: naNuke
Date: Sat, 24 Jan 2015 22:37:14 +0100
Subject: [PATCH 034/106] Improve safeLinks with whitelist.
---
Parsedown.php | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 5d810de..94dbe20 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1262,13 +1262,18 @@ class Parsedown
$Element['attributes']['title'] = $Definition['title'];
}
- if ( $this->safeLinksEnabled && stripos($Element['attributes']['href'], 'javascript:') === 0 )
+ if ( $this->safeLinksEnabled && preg_match("/^(\/|https?:\/\/|ftps?:\/\/)/ui", $Element['attributes']['href']) === 0 )
{
return;
}
- $Element['attributes']['href'] = htmlspecialchars($Element['attributes']['href']);
- $Element['text'] = htmlspecialchars($Element['text']);
+ $Element['attributes']['href'] = htmlspecialchars($Element['attributes']['href'], ENT_QUOTES);
+ $Element['text'] = htmlspecialchars($Element['text'], ENT_QUOTES);
+
+ if ( $Element['attributes']['title'] !== null )
+ {
+ $Element['attributes']['title'] = htmlspecialchars($Element['attributes']['title'], ENT_QUOTES);
+ }
return array(
'extent' => $extent,
From 1d4296f34d938758ff88755e4ac44ae1d3fc6857 Mon Sep 17 00:00:00 2001
From: naNuke
Date: Sun, 25 Jan 2015 19:47:32 +0100
Subject: [PATCH 035/106] Customizable whitelist of schemas for safeLinks
---
Parsedown.php | 25 +++++++++++++++++++++++--
1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 94dbe20..9882810 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -84,6 +84,14 @@ class Parsedown
protected $safeLinksEnabled = true;
+ protected $safeLinksWhitelist = array(
+ 'http://',
+ 'https://',
+ '/',
+ 'ftp://',
+ 'ftps://'
+ );
+
#
# Lines
#
@@ -1262,9 +1270,22 @@ class Parsedown
$Element['attributes']['title'] = $Definition['title'];
}
- if ( $this->safeLinksEnabled && preg_match("/^(\/|https?:\/\/|ftps?:\/\/)/ui", $Element['attributes']['href']) === 0 )
+ if ( $this->safeLinksEnabled )
{
- return;
+ $matched = false;
+ foreach ( $this->safeLinksWhitelist as $scheme )
+ {
+ if ( stripos($Element['attributes']['href'], $scheme) === 0 )
+ {
+ $matched = true;
+ break;
+ }
+ }
+
+ if ( ! $matched )
+ {
+ return;
+ }
}
$Element['attributes']['href'] = htmlspecialchars($Element['attributes']['href'], ENT_QUOTES);
From b3d45c4bb9bc798e4b297da38c4b015ac8bb44c6 Mon Sep 17 00:00:00 2001
From: naNuke
Date: Mon, 26 Jan 2015 18:49:17 +0100
Subject: [PATCH 036/106] Add html escaping to all attributes capable of
holding user input.
---
Parsedown.php | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 9882810..b162d8e 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -422,7 +422,7 @@ class Parsedown
if (isset($matches[1]))
{
- $class = 'language-'.$matches[1];
+ $class = 'language-'.htmlspecialchars($matches[1], ENT_QUOTES, 'UTF-8');
$Element['attributes'] = array(
'class' => $class,
@@ -532,10 +532,10 @@ class Parsedown
),
);
- if($name === 'ol')
+ if($name === 'ol')
{
$listStart = stristr($matches[0], '.', true);
-
+
if($listStart !== '1')
{
$Block['element']['attributes'] = array('start' => $listStart);
@@ -1108,7 +1108,7 @@ class Parsedown
{
if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches))
{
- $url = $matches[1];
+ $url = htmlspecialchars($matches[1], ENT_QUOTES, 'UTF-8');
if ( ! isset($matches[2]))
{
@@ -1288,12 +1288,12 @@ class Parsedown
}
}
- $Element['attributes']['href'] = htmlspecialchars($Element['attributes']['href'], ENT_QUOTES);
- $Element['text'] = htmlspecialchars($Element['text'], ENT_QUOTES);
+ $Element['attributes']['href'] = htmlspecialchars($Element['attributes']['href'], ENT_QUOTES, 'UTF-8');
+ $Element['text'] = htmlspecialchars($Element['text'], ENT_QUOTES, 'UTF-8');
if ( $Element['attributes']['title'] !== null )
{
- $Element['attributes']['title'] = htmlspecialchars($Element['attributes']['title'], ENT_QUOTES);
+ $Element['attributes']['title'] = htmlspecialchars($Element['attributes']['title'], ENT_QUOTES, 'UTF-8');
}
return array(
@@ -1384,14 +1384,16 @@ class Parsedown
if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE))
{
+ $url = htmlspecialchars($matches[0][0], ENT_QUOTES, 'UTF-8');
+
$Inline = array(
'extent' => strlen($matches[0][0]),
'position' => $matches[0][1],
'element' => array(
'name' => 'a',
- 'text' => $matches[0][0],
+ 'text' => $url,
'attributes' => array(
- 'href' => $matches[0][0],
+ 'href' => $url,
),
),
);
@@ -1404,7 +1406,7 @@ class Parsedown
{
if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches))
{
- $url = str_replace(array('&', '<'), array('&', '<'), $matches[1]);
+ $url = htmlspecialchars($matches[1], ENT_QUOTES, 'UTF-8');
return array(
'extent' => strlen($matches[0]),
From 6bb66db00f7faf29932f96b47fc4ac60a4333e8e Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Mon, 1 May 2017 03:24:40 +0100
Subject: [PATCH 037/106] anti-xss
protect all attributes and content from xss via element method
filter special attributes (a href, img src)
expand url whitelist slightly to permit data images and mailto links
---
Parsedown.php | 94 ++++++++++++++++++++++++++++++---------------------
1 file changed, 56 insertions(+), 38 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index b162d8e..8571cd7 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -89,7 +89,9 @@ class Parsedown
'https://',
'/',
'ftp://',
- 'ftps://'
+ 'ftps://',
+ 'mailto:',
+ 'data:image/png;',
);
#
@@ -359,8 +361,6 @@ class Parsedown
{
$text = $Block['element']['text']['text'];
- $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
-
$Block['element']['text']['text'] = $text;
return $Block;
@@ -422,7 +422,7 @@ class Parsedown
if (isset($matches[1]))
{
- $class = 'language-'.htmlspecialchars($matches[1], ENT_QUOTES, 'UTF-8');
+ $class = 'language-'.$matches[1];
$Element['attributes'] = array(
'class' => $class,
@@ -474,8 +474,6 @@ class Parsedown
{
$text = $Block['element']['text']['text'];
- $text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
-
$Block['element']['text']['text'] = $text;
return $Block;
@@ -1091,7 +1089,6 @@ class Parsedown
if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(?') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches))
{
- $url = htmlspecialchars($matches[1], ENT_QUOTES, 'UTF-8');
+ $url = $matches[1];
if ( ! isset($matches[2]))
{
@@ -1270,32 +1267,6 @@ class Parsedown
$Element['attributes']['title'] = $Definition['title'];
}
- if ( $this->safeLinksEnabled )
- {
- $matched = false;
- foreach ( $this->safeLinksWhitelist as $scheme )
- {
- if ( stripos($Element['attributes']['href'], $scheme) === 0 )
- {
- $matched = true;
- break;
- }
- }
-
- if ( ! $matched )
- {
- return;
- }
- }
-
- $Element['attributes']['href'] = htmlspecialchars($Element['attributes']['href'], ENT_QUOTES, 'UTF-8');
- $Element['text'] = htmlspecialchars($Element['text'], ENT_QUOTES, 'UTF-8');
-
- if ( $Element['attributes']['title'] !== null )
- {
- $Element['attributes']['title'] = htmlspecialchars($Element['attributes']['title'], ENT_QUOTES, 'UTF-8');
- }
-
return array(
'extent' => $extent,
'element' => $Element,
@@ -1384,7 +1355,7 @@ class Parsedown
if (preg_match('/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE))
{
- $url = htmlspecialchars($matches[0][0], ENT_QUOTES, 'UTF-8');
+ $url = $matches[0][0];
$Inline = array(
'extent' => strlen($matches[0][0]),
@@ -1406,7 +1377,7 @@ class Parsedown
{
if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w+:\/{2}[^ >]+)>/i', $Excerpt['text'], $matches))
{
- $url = htmlspecialchars($matches[1], ENT_QUOTES, 'UTF-8');
+ $url = $matches[1];
return array(
'extent' => strlen($matches[0]),
@@ -1444,6 +1415,8 @@ class Parsedown
protected function element(array $Element)
{
+ $Element = $this->sanitiseElement($Element);
+
$markup = '<'.$Element['name'];
if (isset($Element['attributes']))
@@ -1455,7 +1428,7 @@ class Parsedown
continue;
}
- $markup .= ' '.$name.'="'.$value.'"';
+ $markup .= ' '.$name.'="'.self::escape($value).'"';
}
}
@@ -1469,7 +1442,7 @@ class Parsedown
}
else
{
- $markup .= $Element['text'];
+ $markup .= self::escape($Element['text'], true);
}
$markup .= ''.$Element['name'].'>';
@@ -1528,10 +1501,55 @@ class Parsedown
return $markup;
}
+ protected function sanitiseElement(array $Element)
+ {
+ $safeUrlNameToAtt = array(
+ 'a' => 'href',
+ 'img' => 'src',
+ );
+
+ if (isset($safeUrlNameToAtt[$Element['name']]))
+ {
+ $Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]);
+ }
+
+ return $Element;
+ }
+
+ protected function filterUnsafeUrlInAttribute(array $Element, $attribute)
+ {
+ if ($this->safeLinksEnabled)
+ {
+ $safe = false;
+
+ foreach ($this->safeLinksWhitelist as $scheme)
+ {
+ if (stripos($Element['attributes'][$attribute], $scheme) === 0)
+ {
+ $safe = true;
+
+ break;
+ }
+ }
+
+ if ( ! $safe)
+ {
+ unset($Element['attributes'][$attribute]);
+ }
+ }
+
+ return $Element;
+ }
+
#
# Static Methods
#
+ protected static function escape($text, $allowQuotes = false)
+ {
+ return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8');
+ }
+
static function instance($name = 'default')
{
if (isset(self::$instances[$name]))
From af04ac92e2ff852309891ebc767fa5a6bf179f39 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Mon, 1 May 2017 03:33:49 +0100
Subject: [PATCH 038/106] add xss tests
---
test/ParsedownTest.php | 2 ++
test/data/xss_attribute_encoding.html | 6 ++++++
test/data/xss_attribute_encoding.md | 11 ++++++++++
test/data/xss_bad_url.html | 16 ++++++++++++++
test/data/xss_bad_url.md | 31 +++++++++++++++++++++++++++
test/data/xss_text_encoding.html | 7 ++++++
test/data/xss_text_encoding.md | 12 +++++++++++
7 files changed, 85 insertions(+)
create mode 100644 test/data/xss_attribute_encoding.html
create mode 100644 test/data/xss_attribute_encoding.md
create mode 100644 test/data/xss_bad_url.html
create mode 100644 test/data/xss_bad_url.md
create mode 100644 test/data/xss_text_encoding.html
create mode 100644 test/data/xss_text_encoding.md
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index 323dace..5fbf7f1 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -46,6 +46,8 @@ class ParsedownTest extends PHPUnit_Framework_TestCase
$expectedMarkup = str_replace("\r\n", "\n", $expectedMarkup);
$expectedMarkup = str_replace("\r", "\n", $expectedMarkup);
+ $this->Parsedown->setMarkupEscaped($test === 'xss_text_encoding');
+
$actualMarkup = $this->Parsedown->text($markdown);
$this->assertEquals($expectedMarkup, $actualMarkup);
diff --git a/test/data/xss_attribute_encoding.html b/test/data/xss_attribute_encoding.html
new file mode 100644
index 0000000..287ff51
--- /dev/null
+++ b/test/data/xss_attribute_encoding.html
@@ -0,0 +1,6 @@
+xss
+
+xss
+
+
+
\ No newline at end of file
diff --git a/test/data/xss_attribute_encoding.md b/test/data/xss_attribute_encoding.md
new file mode 100644
index 0000000..3d8e0c8
--- /dev/null
+++ b/test/data/xss_attribute_encoding.md
@@ -0,0 +1,11 @@
+[xss](https://www.example.com")
+
+![xss](https://www.example.com")
+
+[xss](https://www.example.com')
+
+![xss](https://www.example.com')
+
+![xss"](https://www.example.com)
+
+![xss'](https://www.example.com)
\ No newline at end of file
diff --git a/test/data/xss_bad_url.html b/test/data/xss_bad_url.html
new file mode 100644
index 0000000..93dd0d8
--- /dev/null
+++ b/test/data/xss_bad_url.html
@@ -0,0 +1,16 @@
+xss
+xss
+xss
+xss
+
+
+
+
+xss
+xss
+xss
+xss
+
+
+
+
\ No newline at end of file
diff --git a/test/data/xss_bad_url.md b/test/data/xss_bad_url.md
new file mode 100644
index 0000000..a730952
--- /dev/null
+++ b/test/data/xss_bad_url.md
@@ -0,0 +1,31 @@
+[xss](javascript:alert(1))
+
+[xss]( javascript:alert(1))
+
+[xss](javascript://alert(1))
+
+[xss](javascript:alert(1))
+
+![xss](javascript:alert(1))
+
+![xss]( javascript:alert(1))
+
+![xss](javascript://alert(1))
+
+![xss](javascript:alert(1))
+
+[xss](data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==)
+
+[xss]( data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==)
+
+[xss](data://text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==)
+
+[xss](data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==)
+
+![xss](data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==)
+
+![xss]( data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==)
+
+![xss](data://text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==)
+
+![xss](data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==)
\ No newline at end of file
diff --git a/test/data/xss_text_encoding.html b/test/data/xss_text_encoding.html
new file mode 100644
index 0000000..e6b3fc5
--- /dev/null
+++ b/test/data/xss_text_encoding.html
@@ -0,0 +1,7 @@
+<script>alert(1)</script>
+<script>
+alert(1)
+</script>
+<script>
+alert(1)
+</script>
\ No newline at end of file
diff --git a/test/data/xss_text_encoding.md b/test/data/xss_text_encoding.md
new file mode 100644
index 0000000..b1051a2
--- /dev/null
+++ b/test/data/xss_text_encoding.md
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
From 924b26e16c3af33f152f95ecb7b0a19ebdc086cd Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Mon, 1 May 2017 03:53:29 +0100
Subject: [PATCH 039/106] replace hhvm nightly with nightly
---
.travis.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index fa5ca98..e5f1603 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,9 +8,9 @@ php:
- 5.4
- 5.3
- hhvm
- - hhvm-nightly
+ - nightly
matrix:
fast_finish: true
allow_failures:
- - php: hhvm-nightly
+ - php: nightly
From 131ba758514c5e905663bd82fc7c1c8271c7edc5 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Mon, 1 May 2017 15:44:04 +0100
Subject: [PATCH 040/106] filter onevent attributes
---
Parsedown.php | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/Parsedown.php b/Parsedown.php
index 8571cd7..2fadec0 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1513,6 +1513,22 @@ class Parsedown
$Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]);
}
+ if ( ! empty($Element['attributes']))
+ {
+ # clear out nulls
+ $Element['attributes'] = array_filter(
+ $Element['attributes'],
+ function ($v) {return $v !== null;}
+ );
+
+ $onEventAttributes = preg_grep('/^\s*+on/i', array_flip($Element['attributes']));
+
+ foreach ($onEventAttributes as $att)
+ {
+ unset($Element['attributes'][$att]);
+ }
+ }
+
return $Element;
}
From 6d0156d70714fcd89c1b9c9eb573adade13bfb27 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Tue, 2 May 2017 00:30:04 +0100
Subject: [PATCH 041/106] dump attributes that contain characters that are
impossible for validity, or very unlikely
---
Parsedown.php | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 2fadec0..488af4b 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1503,7 +1503,8 @@ class Parsedown
protected function sanitiseElement(array $Element)
{
- $safeUrlNameToAtt = array(
+ static $badAttributeChars = "\"'= \t\n\r\0\x0B";
+ static $safeUrlNameToAtt = array(
'a' => 'href',
'img' => 'src',
);
@@ -1515,13 +1516,21 @@ class Parsedown
if ( ! empty($Element['attributes']))
{
- # clear out nulls
- $Element['attributes'] = array_filter(
- $Element['attributes'],
- function ($v) {return $v !== null;}
- );
+ foreach ($Element['attributes'] as $att => $val)
+ {
+ # clear out nulls
+ if ($val === null)
+ {
+ unset($Element['attributes'][$att]);
+ }
+ # filter out badly parsed attribute
+ elseif (strpbrk($att, $badAttributeChars) !== false)
+ {
+ unset($Element['attributes'][$att]);
+ }
+ }
- $onEventAttributes = preg_grep('/^\s*+on/i', array_flip($Element['attributes']));
+ $onEventAttributes = preg_grep('/^on/i', array_flip($Element['attributes']));
foreach ($onEventAttributes as $att)
{
From e4bb12329e8b895bfef4564296624cd47057d2be Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Tue, 2 May 2017 01:25:33 +0100
Subject: [PATCH 042/106] array_keys is probably faster
---
Parsedown.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 488af4b..d42e4f5 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1530,9 +1530,9 @@ class Parsedown
}
}
- $onEventAttributes = preg_grep('/^on/i', array_flip($Element['attributes']));
+ $onEventAttributeKeys = preg_grep('/^on/i', array_keys($Element['attributes']));
- foreach ($onEventAttributes as $att)
+ foreach ($onEventAttributeKeys as $att)
{
unset($Element['attributes'][$att]);
}
From 4dc98b635d18527000e74a0eb4cd400db2bf5af3 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Tue, 2 May 2017 19:48:08 +0100
Subject: [PATCH 043/106] whitelist changes: * add gif and jpg as allowed data
images * ensure that user controlled content fall only in the "data section"
of the data URI (and does not intersect content-type definition in any way
(best to be safe than sorry ;-))) "data section" as defined in:
https://tools.ietf.org/html/rfc2397#section-3
---
Parsedown.php | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/Parsedown.php b/Parsedown.php
index d42e4f5..7e72d69 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -91,7 +91,9 @@ class Parsedown
'ftp://',
'ftps://',
'mailto:',
- 'data:image/png;',
+ 'data:image/png;base64,',
+ 'data:image/gif;base64,',
+ 'data:image/jpg;base64,',
);
#
From aee3963e6b97186b1e5526c118bf5d2d872cd8ee Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Tue, 2 May 2017 19:55:03 +0100
Subject: [PATCH 044/106] jpeg, not jpg
---
Parsedown.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Parsedown.php b/Parsedown.php
index 7e72d69..c319a19 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -93,7 +93,7 @@ class Parsedown
'mailto:',
'data:image/png;base64,',
'data:image/gif;base64,',
- 'data:image/jpg;base64,',
+ 'data:image/jpeg;base64,',
);
#
From 4bae1c9834382d3c7aa900a7cbf77771b3864c56 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Wed, 3 May 2017 00:39:01 +0100
Subject: [PATCH 045/106] whitelist regex for good attribute (no no chars that
could form a delimiter allowed
---
Parsedown.php | 21 +++++++--------------
1 file changed, 7 insertions(+), 14 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index c319a19..0bd81e2 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1505,7 +1505,7 @@ class Parsedown
protected function sanitiseElement(array $Element)
{
- static $badAttributeChars = "\"'= \t\n\r\0\x0B";
+ static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/';
static $safeUrlNameToAtt = array(
'a' => 'href',
'img' => 'src',
@@ -1520,23 +1520,16 @@ class Parsedown
{
foreach ($Element['attributes'] as $att => $val)
{
- # clear out nulls
- if ($val === null)
- {
- unset($Element['attributes'][$att]);
- }
# filter out badly parsed attribute
- elseif (strpbrk($att, $badAttributeChars) !== false)
+ if ( ! preg_match($goodAttribute, $att))
+ {
+ unset($Element['attributes'][$att]);
+ }
+ # dump onevent attribute
+ elseif (preg_match('/^on/i', $att))
{
unset($Element['attributes'][$att]);
}
- }
-
- $onEventAttributeKeys = preg_grep('/^on/i', array_keys($Element['attributes']));
-
- foreach ($onEventAttributeKeys as $att)
- {
- unset($Element['attributes'][$att]);
}
}
From 054ba3c48729036fd8ab1166fb0b1d0b4dd1e465 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Wed, 3 May 2017 17:01:27 +0100
Subject: [PATCH 046/106] urlencode urls that are potentially unsafe:
this should break urls that attempt to include a protocol, or port (these are absolute URLs and should have a whitelisted protocol for use)
but URLs that are relative, or relative from the site root should be preserved (though characters non essential for the URL structure may be urlencoded)
this approach has significant advantages over attempting to locate something like `javascript:alert(1)` or `javascript:alert(1)` (which are both valid) because browsers have been known to ignore ridiculous characters when encountered (meaning something like `jav\ta\0\0script:alert(1)` would be xss :( ). Instead of trying to chase down a way to interpret a URL to decide whether there is a protocol, this approach ensures that two essential characters needed to achieve a colon are encoded `:` (obviously) and `;` (from `:`). If these characters appear in a relative URL then they are equivalent to their URL encoded form and so this change will be non breaking for that case.
---
Parsedown.php | 10 ++++++++--
test/data/inline_link.html | 2 +-
test/data/xss_bad_url.html | 32 ++++++++++++++++----------------
3 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 0bd81e2..702b041 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -87,7 +87,6 @@ class Parsedown
protected $safeLinksWhitelist = array(
'http://',
'https://',
- '/',
'ftp://',
'ftps://',
'mailto:',
@@ -1554,7 +1553,14 @@ class Parsedown
if ( ! $safe)
{
- unset($Element['attributes'][$attribute]);
+ $Element['attributes'][$attribute] = preg_replace_callback(
+ '/[^\/#?&=%]++/',
+ function (array $match)
+ {
+ return urlencode($match[0]);
+ },
+ $Element['attributes'][$attribute]
+ );
}
}
diff --git a/test/data/inline_link.html b/test/data/inline_link.html
index cef29cf..7a3131b 100644
--- a/test/data/inline_link.html
+++ b/test/data/inline_link.html
@@ -1,5 +1,5 @@
link
-link with parentheses in URL
+link with parentheses in URL
(link) in parentheses
link
diff --git a/test/data/xss_bad_url.html b/test/data/xss_bad_url.html
index 93dd0d8..8e43877 100644
--- a/test/data/xss_bad_url.html
+++ b/test/data/xss_bad_url.html
@@ -1,16 +1,16 @@
-xss
-xss
-xss
-xss
-
-
-
-
-xss
-xss
-xss
-xss
-
-
-
-
\ No newline at end of file
+xss
+xss
+xss
+xss
+
+
+
+
+xss
+xss
+xss
+xss
+
+
+
+
\ No newline at end of file
From f76b10aaab9ff23a926323450885d0cd224fd147 Mon Sep 17 00:00:00 2001
From: Emanuil Rusev
Date: Thu, 4 May 2017 10:28:55 +0300
Subject: [PATCH 047/106] update readme
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 4e5659a..ffe3116 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-> You might also like [Caret](http://caret.io?ref=parsedown) - our Markdown editor for Mac / Windows / Linux.
+> You might also like [Caret](https://caret.io?ref=parsedown) - our Markdown editor for Mac / Windows / Linux.
## Parsedown
From dc30cb441c0834357b7f145444f6e53cbe67154e Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Fri, 5 May 2017 21:32:27 +0100
Subject: [PATCH 048/106] add more protocols to the whitelist
---
Parsedown.php | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Parsedown.php b/Parsedown.php
index 702b041..6ef12d3 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -93,6 +93,14 @@ class Parsedown
'data:image/png;base64,',
'data:image/gif;base64,',
'data:image/jpeg;base64,',
+ 'irc:',
+ 'ircs:',
+ 'git:',
+ 'ssh:',
+ 'ftp:',
+ 'ftps:',
+ 'news:',
+ 'steam:',
);
#
From 2e4afde68dae7f410af8c9e3a0664fcf97ce8a3d Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Fri, 5 May 2017 21:55:58 +0100
Subject: [PATCH 049/106] faster check substr at beginning of string
---
Parsedown.php | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 6ef12d3..096c399 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1533,7 +1533,7 @@ class Parsedown
unset($Element['attributes'][$att]);
}
# dump onevent attribute
- elseif (preg_match('/^on/i', $att))
+ elseif (self::striAtStart($att, 'on'))
{
unset($Element['attributes'][$att]);
}
@@ -1551,7 +1551,7 @@ class Parsedown
foreach ($this->safeLinksWhitelist as $scheme)
{
- if (stripos($Element['attributes'][$attribute], $scheme) === 0)
+ if (self::striAtStart($Element['attributes'][$attribute], $scheme))
{
$safe = true;
@@ -1584,6 +1584,20 @@ class Parsedown
return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8');
}
+ protected static function striAtStart($string, $needle)
+ {
+ $len = strlen($needle);
+
+ if ($len > strlen($string))
+ {
+ return false;
+ }
+ else
+ {
+ return strtolower(substr($string, 0, $len)) === strtolower($needle);
+ }
+ }
+
static function instance($name = 'default')
{
if (isset(self::$instances[$name]))
From 226f636360d29060f9d6d15ec47ce5de575a226c Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sun, 7 May 2017 13:45:59 +0100
Subject: [PATCH 050/106] remove $safe flag
---
Parsedown.php | 26 ++++++++++----------------
1 file changed, 10 insertions(+), 16 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 096c399..42b8298 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1547,29 +1547,23 @@ class Parsedown
{
if ($this->safeLinksEnabled)
{
- $safe = false;
-
foreach ($this->safeLinksWhitelist as $scheme)
{
if (self::striAtStart($Element['attributes'][$attribute], $scheme))
{
- $safe = true;
-
- break;
+ return $Element;
}
}
- if ( ! $safe)
- {
- $Element['attributes'][$attribute] = preg_replace_callback(
- '/[^\/#?&=%]++/',
- function (array $match)
- {
- return urlencode($match[0]);
- },
- $Element['attributes'][$attribute]
- );
- }
+ $Element['attributes'][$attribute] = preg_replace_callback(
+ '/[^\/#?&=%]++/',
+ function (array $match)
+ {
+ return urlencode($match[0]);
+ },
+ $Element['attributes'][$attribute]
+ );
+
}
return $Element;
From c63b690a799cb6ae1641d345d33f67ed6efc6fb2 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Tue, 9 May 2017 14:50:15 +0100
Subject: [PATCH 051/106] remove duplicates
---
Parsedown.php | 2 --
1 file changed, 2 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 42b8298..0695c6f 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -97,8 +97,6 @@ class Parsedown
'ircs:',
'git:',
'ssh:',
- 'ftp:',
- 'ftps:',
'news:',
'steam:',
);
From b1e5aebaf6c8162cda482e96a1370155fd2162b5 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Tue, 9 May 2017 19:22:58 +0100
Subject: [PATCH 052/106] add single safeMode option that encompasses
protection from link destination xss and plain markup based xss into a single
on/off switch
---
Parsedown.php | 14 +++++++-------
test/ParsedownTest.php | 2 +-
test/data/inline_link.html | 2 +-
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 0695c6f..0dbf40c 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -75,14 +75,14 @@ class Parsedown
protected $urlsLinked = true;
- function setSafeLinksEnabled($safeLinksEnabled)
+ function setSafeMode($safeMode)
{
- $this->safeLinksEnabled = $safeLinksEnabled;
+ $this->safeMode = (bool) $safeMode;
return $this;
}
- protected $safeLinksEnabled = true;
+ protected $safeMode;
protected $safeLinksWhitelist = array(
'http://',
@@ -378,7 +378,7 @@ class Parsedown
protected function blockComment($Line)
{
- if ($this->markupEscaped)
+ if ($this->markupEscaped or $this->safeMode)
{
return;
}
@@ -700,7 +700,7 @@ class Parsedown
protected function blockMarkup($Line)
{
- if ($this->markupEscaped)
+ if ($this->markupEscaped or $this->safeMode)
{
return;
}
@@ -1282,7 +1282,7 @@ class Parsedown
protected function inlineMarkup($Excerpt)
{
- if ($this->markupEscaped or strpos($Excerpt['text'], '>') === false)
+ if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false)
{
return;
}
@@ -1543,7 +1543,7 @@ class Parsedown
protected function filterUnsafeUrlInAttribute(array $Element, $attribute)
{
- if ($this->safeLinksEnabled)
+ if ($this->safeMode)
{
foreach ($this->safeLinksWhitelist as $scheme)
{
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index 5fbf7f1..c7e3a82 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -46,7 +46,7 @@ class ParsedownTest extends PHPUnit_Framework_TestCase
$expectedMarkup = str_replace("\r\n", "\n", $expectedMarkup);
$expectedMarkup = str_replace("\r", "\n", $expectedMarkup);
- $this->Parsedown->setMarkupEscaped($test === 'xss_text_encoding');
+ $this->Parsedown->setSafeMode(substr($test, 0, 3) === 'xss');
$actualMarkup = $this->Parsedown->text($markdown);
diff --git a/test/data/inline_link.html b/test/data/inline_link.html
index 7a3131b..cef29cf 100644
--- a/test/data/inline_link.html
+++ b/test/data/inline_link.html
@@ -1,5 +1,5 @@
link
-link with parentheses in URL
+link with parentheses in URL
(link) in parentheses
link
From bbb7687f31d6904f3a0e11e97bc61852a62cfe90 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Tue, 9 May 2017 19:31:36 +0100
Subject: [PATCH 053/106] safeMode will either apply all sanitisation
techniques to an element or none (note that encoding HTML entities is done
regardless because it speaks to character context, and that the only
attributes/elements we should permit are the ones we actually mean to create)
---
Parsedown.php | 33 ++++++++++++++++-----------------
1 file changed, 16 insertions(+), 17 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 0dbf40c..c540d12 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1422,7 +1422,10 @@ class Parsedown
protected function element(array $Element)
{
- $Element = $this->sanitiseElement($Element);
+ if ($this->safeMode)
+ {
+ $Element = $this->sanitiseElement($Element);
+ }
$markup = '<'.$Element['name'];
@@ -1543,27 +1546,23 @@ class Parsedown
protected function filterUnsafeUrlInAttribute(array $Element, $attribute)
{
- if ($this->safeMode)
+ foreach ($this->safeLinksWhitelist as $scheme)
{
- foreach ($this->safeLinksWhitelist as $scheme)
+ if (self::striAtStart($Element['attributes'][$attribute], $scheme))
{
- if (self::striAtStart($Element['attributes'][$attribute], $scheme))
- {
- return $Element;
- }
+ return $Element;
}
-
- $Element['attributes'][$attribute] = preg_replace_callback(
- '/[^\/#?&=%]++/',
- function (array $match)
- {
- return urlencode($match[0]);
- },
- $Element['attributes'][$attribute]
- );
-
}
+ $Element['attributes'][$attribute] = preg_replace_callback(
+ '/[^\/#?&=%]++/',
+ function (array $match)
+ {
+ return urlencode($match[0]);
+ },
+ $Element['attributes'][$attribute]
+ );
+
return $Element;
}
From 67c3efbea0d33c4433c6b18ed163b45c01395867 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Tue, 9 May 2017 19:37:13 +0100
Subject: [PATCH 054/106] according to
https://tools.ietf.org/html/rfc3986#section-3 the colon is a required part of
the syntax, other methods of achieving the colon character (as to browser
interpretation) should be taken care of by htmlencoding that is done on all
attribute content
---
Parsedown.php | 9 +--------
test/data/xss_bad_url.html | 32 ++++++++++++++++----------------
2 files changed, 17 insertions(+), 24 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index c540d12..110d6e3 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1554,14 +1554,7 @@ class Parsedown
}
}
- $Element['attributes'][$attribute] = preg_replace_callback(
- '/[^\/#?&=%]++/',
- function (array $match)
- {
- return urlencode($match[0]);
- },
- $Element['attributes'][$attribute]
- );
+ $Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]);
return $Element;
}
diff --git a/test/data/xss_bad_url.html b/test/data/xss_bad_url.html
index 8e43877..0b216d1 100644
--- a/test/data/xss_bad_url.html
+++ b/test/data/xss_bad_url.html
@@ -1,16 +1,16 @@
-xss
-xss
-xss
-xss
-
-
-
-
-xss
-xss
-xss
-xss
-
-
-
-
\ No newline at end of file
+xss
+xss
+xss
+xss
+
+
+
+
+xss
+xss
+xss
+xss
+
+
+
+
\ No newline at end of file
From c82af01bd6e97fb5c39aaf2f6a41b6d55c9d66e4 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sun, 14 May 2017 14:36:55 +0100
Subject: [PATCH 055/106] add sudo false
---
.travis.yml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/.travis.yml b/.travis.yml
index e5f1603..6799ce6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,3 +14,5 @@ matrix:
fast_finish: true
allow_failures:
- php: nightly
+
+sudo: false
\ No newline at end of file
From be963a6531001b7d87083fb3f77b0df525ebc8db Mon Sep 17 00:00:00 2001
From: Daniel Berthereau
Date: Mon, 19 Jun 2017 00:00:00 +0200
Subject: [PATCH 056/106] Added tests for consistency when a markdown follows a
markup without blank line.
---
test/ParsedownTest.php | 3 ++-
test/data/markup_consecutive_one.html | 3 +++
test/data/markup_consecutive_one.md | 4 ++++
test/data/markup_consecutive_one_line.html | 4 ++++
test/data/markup_consecutive_one_line.md | 5 +++++
test/data/markup_consecutive_one_stripped.html | 3 +++
test/data/markup_consecutive_one_stripped.md | 4 ++++
test/data/markup_consecutive_two.html | 3 +++
test/data/markup_consecutive_two.md | 4 ++++
test/data/markup_consecutive_two_lines.html | 4 ++++
test/data/markup_consecutive_two_lines.md | 5 +++++
test/data/markup_consecutive_two_stripped.html | 4 ++++
test/data/markup_consecutive_two_stripped.md | 5 +++++
13 files changed, 50 insertions(+), 1 deletion(-)
create mode 100644 test/data/markup_consecutive_one.html
create mode 100644 test/data/markup_consecutive_one.md
create mode 100644 test/data/markup_consecutive_one_line.html
create mode 100644 test/data/markup_consecutive_one_line.md
create mode 100644 test/data/markup_consecutive_one_stripped.html
create mode 100644 test/data/markup_consecutive_one_stripped.md
create mode 100644 test/data/markup_consecutive_two.html
create mode 100644 test/data/markup_consecutive_two.md
create mode 100644 test/data/markup_consecutive_two_lines.html
create mode 100644 test/data/markup_consecutive_two_lines.md
create mode 100644 test/data/markup_consecutive_two_stripped.html
create mode 100644 test/data/markup_consecutive_two_stripped.md
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index 323dace..bef612b 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -10,7 +10,8 @@ class ParsedownTest extends PHPUnit_Framework_TestCase
parent::__construct($name, $data, $dataName);
}
- private $dirs, $Parsedown;
+ private $dirs;
+ protected $Parsedown;
/**
* @return array
diff --git a/test/data/markup_consecutive_one.html b/test/data/markup_consecutive_one.html
new file mode 100644
index 0000000..a0b1fca
--- /dev/null
+++ b/test/data/markup_consecutive_one.html
@@ -0,0 +1,3 @@
+Markup
+No markdown without blank line if strict compliance, but main processors convert it.
+Markdown
\ No newline at end of file
diff --git a/test/data/markup_consecutive_one.md b/test/data/markup_consecutive_one.md
new file mode 100644
index 0000000..7a00770
--- /dev/null
+++ b/test/data/markup_consecutive_one.md
@@ -0,0 +1,4 @@
+Markup
+_No markdown_ without blank line if strict compliance, but **main** processors convert it.
+
+**Markdown**
\ No newline at end of file
diff --git a/test/data/markup_consecutive_one_line.html b/test/data/markup_consecutive_one_line.html
new file mode 100644
index 0000000..2a301aa
--- /dev/null
+++ b/test/data/markup_consecutive_one_line.html
@@ -0,0 +1,4 @@
+One markup on
+two lines
+Markdown
+Markdown
\ No newline at end of file
diff --git a/test/data/markup_consecutive_one_line.md b/test/data/markup_consecutive_one_line.md
new file mode 100644
index 0000000..d40609a
--- /dev/null
+++ b/test/data/markup_consecutive_one_line.md
@@ -0,0 +1,5 @@
+One markup on
+two lines
+_Markdown_
+
+**Markdown**
\ No newline at end of file
diff --git a/test/data/markup_consecutive_one_stripped.html b/test/data/markup_consecutive_one_stripped.html
new file mode 100644
index 0000000..eb5136b
--- /dev/null
+++ b/test/data/markup_consecutive_one_stripped.html
@@ -0,0 +1,3 @@
+
+Markdown
+Markdown
\ No newline at end of file
diff --git a/test/data/markup_consecutive_one_stripped.md b/test/data/markup_consecutive_one_stripped.md
new file mode 100644
index 0000000..4189580
--- /dev/null
+++ b/test/data/markup_consecutive_one_stripped.md
@@ -0,0 +1,4 @@
+
+_Markdown_
+
+**Markdown**
\ No newline at end of file
diff --git a/test/data/markup_consecutive_two.html b/test/data/markup_consecutive_two.html
new file mode 100644
index 0000000..efcebcd
--- /dev/null
+++ b/test/data/markup_consecutive_two.html
@@ -0,0 +1,3 @@
+First markup
and second markup on the same line.
+Markdown
+Markdown
\ No newline at end of file
diff --git a/test/data/markup_consecutive_two.md b/test/data/markup_consecutive_two.md
new file mode 100644
index 0000000..bd663ac
--- /dev/null
+++ b/test/data/markup_consecutive_two.md
@@ -0,0 +1,4 @@
+First markup
and second markup on the same line.
+_Markdown_
+
+**Markdown**
\ No newline at end of file
diff --git a/test/data/markup_consecutive_two_lines.html b/test/data/markup_consecutive_two_lines.html
new file mode 100644
index 0000000..cfa1463
--- /dev/null
+++ b/test/data/markup_consecutive_two_lines.html
@@ -0,0 +1,4 @@
+First markup
and partial markup
+on two lines.
+Markdown
+Markdown
\ No newline at end of file
diff --git a/test/data/markup_consecutive_two_lines.md b/test/data/markup_consecutive_two_lines.md
new file mode 100644
index 0000000..66318e9
--- /dev/null
+++ b/test/data/markup_consecutive_two_lines.md
@@ -0,0 +1,5 @@
+First markup
and partial markup
+on two lines.
+_Markdown_
+
+**Markdown**
\ No newline at end of file
diff --git a/test/data/markup_consecutive_two_stripped.html b/test/data/markup_consecutive_two_stripped.html
new file mode 100644
index 0000000..1633678
--- /dev/null
+++ b/test/data/markup_consecutive_two_stripped.html
@@ -0,0 +1,4 @@
+Stripped markup
+on two lines
+Markdown
+Markdown
\ No newline at end of file
diff --git a/test/data/markup_consecutive_two_stripped.md b/test/data/markup_consecutive_two_stripped.md
new file mode 100644
index 0000000..8173380
--- /dev/null
+++ b/test/data/markup_consecutive_two_stripped.md
@@ -0,0 +1,5 @@
+Stripped markup
+on two lines
+_Markdown_
+
+**Markdown**
\ No newline at end of file
From 129f807e32104a31134882c9ca32b279350f3db3 Mon Sep 17 00:00:00 2001
From: Daniel Berthereau
Date: Thu, 22 Jun 2017 00:00:00 +0200
Subject: [PATCH 057/106] Inverted checks of consistency for markdown following
markups.
---
test/data/markup_consecutive_one.html | 2 +-
test/data/markup_consecutive_one.md | 2 +-
test/data/markup_consecutive_one_line.html | 2 +-
test/data/markup_consecutive_one_line.md | 2 +-
test/data/markup_consecutive_one_stripped.html | 2 +-
test/data/markup_consecutive_one_stripped.md | 2 +-
test/data/markup_consecutive_two.html | 2 +-
test/data/markup_consecutive_two.md | 2 +-
test/data/markup_consecutive_two_lines.html | 2 +-
test/data/markup_consecutive_two_lines.md | 2 +-
test/data/markup_consecutive_two_stripped.html | 2 +-
test/data/markup_consecutive_two_stripped.md | 2 +-
12 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/test/data/markup_consecutive_one.html b/test/data/markup_consecutive_one.html
index a0b1fca..d4c5005 100644
--- a/test/data/markup_consecutive_one.html
+++ b/test/data/markup_consecutive_one.html
@@ -1,3 +1,3 @@
Markup
-No markdown without blank line if strict compliance, but main processors convert it.
+_No markdown_ without blank line for **strict** compliance with CommonMark.
Markdown
\ No newline at end of file
diff --git a/test/data/markup_consecutive_one.md b/test/data/markup_consecutive_one.md
index 7a00770..18b4dcb 100644
--- a/test/data/markup_consecutive_one.md
+++ b/test/data/markup_consecutive_one.md
@@ -1,4 +1,4 @@
Markup
-_No markdown_ without blank line if strict compliance, but **main** processors convert it.
+_No markdown_ without blank line for **strict** compliance with CommonMark.
**Markdown**
\ No newline at end of file
diff --git a/test/data/markup_consecutive_one_line.html b/test/data/markup_consecutive_one_line.html
index 2a301aa..a89b4fd 100644
--- a/test/data/markup_consecutive_one_line.html
+++ b/test/data/markup_consecutive_one_line.html
@@ -1,4 +1,4 @@
One markup on
two lines
-Markdown
+_No markdown_
Markdown
\ No newline at end of file
diff --git a/test/data/markup_consecutive_one_line.md b/test/data/markup_consecutive_one_line.md
index d40609a..daf945a 100644
--- a/test/data/markup_consecutive_one_line.md
+++ b/test/data/markup_consecutive_one_line.md
@@ -1,5 +1,5 @@
One markup on
two lines
-_Markdown_
+_No markdown_
**Markdown**
\ No newline at end of file
diff --git a/test/data/markup_consecutive_one_stripped.html b/test/data/markup_consecutive_one_stripped.html
index eb5136b..ccc01f1 100644
--- a/test/data/markup_consecutive_one_stripped.html
+++ b/test/data/markup_consecutive_one_stripped.html
@@ -1,3 +1,3 @@
-Markdown
+_No markdown_
Markdown
\ No newline at end of file
diff --git a/test/data/markup_consecutive_one_stripped.md b/test/data/markup_consecutive_one_stripped.md
index 4189580..7f8df0c 100644
--- a/test/data/markup_consecutive_one_stripped.md
+++ b/test/data/markup_consecutive_one_stripped.md
@@ -1,4 +1,4 @@
-_Markdown_
+_No markdown_
**Markdown**
\ No newline at end of file
diff --git a/test/data/markup_consecutive_two.html b/test/data/markup_consecutive_two.html
index efcebcd..f7e71c7 100644
--- a/test/data/markup_consecutive_two.html
+++ b/test/data/markup_consecutive_two.html
@@ -1,3 +1,3 @@
First markup
and second markup on the same line.
-Markdown
+_No markdown_
Markdown
\ No newline at end of file
diff --git a/test/data/markup_consecutive_two.md b/test/data/markup_consecutive_two.md
index bd663ac..83f3af7 100644
--- a/test/data/markup_consecutive_two.md
+++ b/test/data/markup_consecutive_two.md
@@ -1,4 +1,4 @@
First markup
and second markup on the same line.
-_Markdown_
+_No markdown_
**Markdown**
\ No newline at end of file
diff --git a/test/data/markup_consecutive_two_lines.html b/test/data/markup_consecutive_two_lines.html
index cfa1463..ffa4728 100644
--- a/test/data/markup_consecutive_two_lines.html
+++ b/test/data/markup_consecutive_two_lines.html
@@ -1,4 +1,4 @@
First markup
and partial markup
on two lines.
-Markdown
+_No markdown_
Markdown
\ No newline at end of file
diff --git a/test/data/markup_consecutive_two_lines.md b/test/data/markup_consecutive_two_lines.md
index 66318e9..dc70bb7 100644
--- a/test/data/markup_consecutive_two_lines.md
+++ b/test/data/markup_consecutive_two_lines.md
@@ -1,5 +1,5 @@
First markup
and partial markup
on two lines.
-_Markdown_
+_No markdown_
**Markdown**
\ No newline at end of file
diff --git a/test/data/markup_consecutive_two_stripped.html b/test/data/markup_consecutive_two_stripped.html
index 1633678..707d6be 100644
--- a/test/data/markup_consecutive_two_stripped.html
+++ b/test/data/markup_consecutive_two_stripped.html
@@ -1,4 +1,4 @@
Stripped markup
on two lines
-Markdown
+_No markdown_
Markdown
\ No newline at end of file
diff --git a/test/data/markup_consecutive_two_stripped.md b/test/data/markup_consecutive_two_stripped.md
index 8173380..af5b781 100644
--- a/test/data/markup_consecutive_two_stripped.md
+++ b/test/data/markup_consecutive_two_stripped.md
@@ -1,5 +1,5 @@
Stripped markup
on two lines
-_Markdown_
+_No markdown_
**Markdown**
\ No newline at end of file
From 6a4afac0d02218b134b922428e5c659ed9360d36 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 22 Jun 2017 00:02:03 +0100
Subject: [PATCH 058/106] remove ability for htmlblock to allow paragraph after
if it closes on the same line
---
Parsedown.php | 30 ++----------------------------
1 file changed, 2 insertions(+), 28 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index e516f6b..f6daad2 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -515,10 +515,10 @@ class Parsedown
),
);
- if($name === 'ol')
+ if($name === 'ol')
{
$listStart = stristr($matches[0], '.', true);
-
+
if($listStart !== '1')
{
$Block['element']['attributes'] = array('start' => $listStart);
@@ -697,32 +697,6 @@ class Parsedown
'markup' => $Line['text'],
);
- $length = strlen($matches[0]);
-
- $remainder = substr($Line['text'], $length);
-
- if (trim($remainder) === '')
- {
- if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
- {
- $Block['closed'] = true;
-
- $Block['void'] = true;
- }
- }
- else
- {
- if (isset($matches[2]) or in_array($matches[1], $this->voidElements))
- {
- return;
- }
-
- if (preg_match('/<\/'.$matches[1].'>[ ]*$/i', $remainder))
- {
- $Block['closed'] = true;
- }
- }
-
return $Block;
}
}
From c05bff047ad6703b1b4abd58bca9de78f32fa05a Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 22 Jun 2017 00:03:12 +0100
Subject: [PATCH 059/106] correct test to match CommonMark specified input for
output
---
test/data/self-closing_html.md | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/test/data/self-closing_html.md b/test/data/self-closing_html.md
index acb2032..61d16a3 100644
--- a/test/data/self-closing_html.md
+++ b/test/data/self-closing_html.md
@@ -1,12 +1,18 @@
+
paragraph
+
paragraph
+
paragraph
+
paragraph
+
paragraph
+
paragraph
\ No newline at end of file
From 44042011755697dd1b8972b6a79c2b87c759660e Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sun, 20 Aug 2017 10:28:46 +0100
Subject: [PATCH 060/106] Properly support fenced code block infostring
Reference: http://spec.commonmark.org/0.28/#info-string
---
Parsedown.php | 6 +++---
test/data/fenced_code_block.html | 3 ++-
test/data/fenced_code_block.md | 4 ++++
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index f5dd0fa..00f61f3 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -396,7 +396,7 @@ class Parsedown
protected function blockFencedCode($Line)
{
- if (preg_match('/^['.$Line['text'][0].']{3,}[ ]*([\w-]+)?[ ]*$/', $Line['text'], $matches))
+ if (preg_match('/^['.$Line['text'][0].']{3,}[ ]*([^`]+)?[ ]*$/', $Line['text'], $matches))
{
$Element = array(
'name' => 'code',
@@ -515,10 +515,10 @@ class Parsedown
),
);
- if($name === 'ol')
+ if($name === 'ol')
{
$listStart = stristr($matches[0], '.', true);
-
+
if($listStart !== '1')
{
$Block['element']['attributes'] = array('start' => $listStart);
diff --git a/test/data/fenced_code_block.html b/test/data/fenced_code_block.html
index 8bdabba..ce8dfd0 100644
--- a/test/data/fenced_code_block.html
+++ b/test/data/fenced_code_block.html
@@ -3,4 +3,5 @@
$message = 'fenced code block';
echo $message;
tilde
-echo 'language identifier';
\ No newline at end of file
+echo 'language identifier';
+echo 'language identifier with non words';
\ No newline at end of file
diff --git a/test/data/fenced_code_block.md b/test/data/fenced_code_block.md
index cbed8eb..9176ef4 100644
--- a/test/data/fenced_code_block.md
+++ b/test/data/fenced_code_block.md
@@ -11,4 +11,8 @@ tilde
```php
echo 'language identifier';
+```
+
+```c#
+echo 'language identifier with non words';
```
\ No newline at end of file
From 07c937583d56776b7cfd0564b542fa95a7765012 Mon Sep 17 00:00:00 2001
From: Emanuil Rusev
Date: Sun, 22 Oct 2017 15:57:58 +0300
Subject: [PATCH 061/106] improve readme
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index ffe3116..0459e3c 100644
--- a/README.md
+++ b/README.md
@@ -21,6 +21,8 @@ Better Markdown Parser in PHP
* Tested in 5.3 to 7.1 and in HHVM
* [Markdown Extra extension](https://github.com/erusev/parsedown-extra)
+Note that when you deal with untrusted content (ex: user commnets) you should also use a HTML sanitizer like [HTML Purifier](http://htmlpurifier.org/).
+
### Installation
Include `Parsedown.php` or install [the composer package](https://packagist.org/packages/erusev/parsedown).
From 16aadff2ed7f03e3ea19bff15cac980e339a84b9 Mon Sep 17 00:00:00 2001
From: Emanuil Rusev
Date: Sun, 22 Oct 2017 16:00:43 +0300
Subject: [PATCH 062/106] improve readme
---
README.md | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 0459e3c..9a2d56e 100644
--- a/README.md
+++ b/README.md
@@ -21,8 +21,6 @@ Better Markdown Parser in PHP
* Tested in 5.3 to 7.1 and in HHVM
* [Markdown Extra extension](https://github.com/erusev/parsedown-extra)
-Note that when you deal with untrusted content (ex: user commnets) you should also use a HTML sanitizer like [HTML Purifier](http://htmlpurifier.org/).
-
### Installation
Include `Parsedown.php` or install [the composer package](https://packagist.org/packages/erusev/parsedown).
@@ -37,6 +35,10 @@ echo $Parsedown->text('Hello _Parsedown_!'); # prints: Hello Parsedown
Date: Sun, 22 Oct 2017 16:01:34 +0300
Subject: [PATCH 063/106] improve readme
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 9a2d56e..7073a95 100644
--- a/README.md
+++ b/README.md
@@ -37,7 +37,7 @@ More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [t
### Security
-Parsedownw does not sanitize the outut HTML. When you deal with untrusted content (ex: user commnets) you should also use a HTML sanitizer like [HTML Purifier](http://htmlpurifier.org/).
+Parsedown does not sanitize the HTML that it generates. When you deal with untrusted content (ex: user commnets) you should also use a HTML sanitizer like [HTML Purifier](http://htmlpurifier.org/).
### Questions
From af6affdc2c7dcdfb1c14bc642c374005193b10ca Mon Sep 17 00:00:00 2001
From: Emanuil Rusev
Date: Mon, 6 Nov 2017 16:54:00 +0200
Subject: [PATCH 064/106] improve readme
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 7073a95..5f5c38e 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,7 @@ Better Markdown Parser in PHP
### Features
* One File
+* No Dependencies
* Super Fast
* Extensible
* [GitHub flavored](https://help.github.com/articles/github-flavored-markdown)
From 691e36b1f241e7000fa36d176a2b13de4820b64c Mon Sep 17 00:00:00 2001
From: Gabriel Caruso
Date: Sat, 11 Nov 2017 00:56:03 -0200
Subject: [PATCH 065/106] Use PHPUnit\Framework\TestCase instead of
PHPUnit_Framework_TestCase
---
composer.json | 3 +++
phpunit.xml.dist | 2 +-
test/CommonMarkTest.php | 5 ++++-
test/ParsedownTest.php | 4 +++-
test/bootstrap.php | 4 ----
5 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/composer.json b/composer.json
index 28145af..b7f8aea 100644
--- a/composer.json
+++ b/composer.json
@@ -15,6 +15,9 @@
"require": {
"php": ">=5.3.0"
},
+ "require-dev": {
+ "phpunit/phpunit": "^4.8.35"
+ },
"autoload": {
"psr-0": {"Parsedown": ""}
}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index b2d5e9d..dd9da22 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -5,4 +5,4 @@
test/ParsedownTest.php
-
\ No newline at end of file
+
diff --git a/test/CommonMarkTest.php b/test/CommonMarkTest.php
index 9b8d116..7111f0b 100644
--- a/test/CommonMarkTest.php
+++ b/test/CommonMarkTest.php
@@ -8,7 +8,10 @@
* @link http://commonmark.org/ CommonMark
* @link http://git.io/8WtRvQ JavaScript test runner
*/
-class CommonMarkTest extends PHPUnit_Framework_TestCase
+
+use PHPUnit\Framework\TestCase;
+
+class CommonMarkTest extends TestCase
{
const SPEC_URL = 'https://raw.githubusercontent.com/jgm/stmd/master/spec.txt';
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index 323dace..3b4c7d9 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -1,6 +1,8 @@
Date: Sat, 11 Nov 2017 01:02:11 -0200
Subject: [PATCH 066/106] Make Travis CI use installed PHPUnit version, not
global one
---
.travis.yml | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 6799ce6..58831c9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,5 +14,10 @@ matrix:
fast_finish: true
allow_failures:
- php: nightly
+ - php: 5.3
-sudo: false
\ No newline at end of file
+before_script:
+ - composer install --prefer-dist --no-interaction --no-progress
+
+script:
+ - vendor/bin/phpunit
From 09827f542c09ef729e34a01ff9eafa1c832f7559 Mon Sep 17 00:00:00 2001
From: Gabriel Caruso
Date: Tue, 14 Nov 2017 15:19:24 -0200
Subject: [PATCH 067/106] Rewrite Travis CI
---
.travis.yml | 24 ++++++++++++++----------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 58831c9..cfb4d8d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,20 +1,24 @@
language: php
-php:
- - 7.1
- - 7.0
- - 5.6
- - 5.5
- - 5.4
- - 5.3
- - hhvm
- - nightly
+dist: trusty
+sudo: false
matrix:
+ include:
+ - php: 5.3
+ dist: precise
+ - php: 5.4
+ - php: 5.5
+ - php: 5.6
+ - php: 7.0
+ - php: 7.1
+ - php: nightly
+ - php: hhvm
+ - php: hhvm-nightly
fast_finish: true
allow_failures:
- php: nightly
- - php: 5.3
+ - php: hhvm-nightly
before_script:
- composer install --prefer-dist --no-interaction --no-progress
From 089789dfff34a552e96998933803d75b230f465b Mon Sep 17 00:00:00 2001
From: John Bafford
Date: Tue, 14 Nov 2017 17:13:31 -0500
Subject: [PATCH 068/106] Fix typo in README
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 5f5c38e..e1f2b53 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,7 @@ More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [t
### Security
-Parsedown does not sanitize the HTML that it generates. When you deal with untrusted content (ex: user commnets) you should also use a HTML sanitizer like [HTML Purifier](http://htmlpurifier.org/).
+Parsedown does not sanitize the HTML that it generates. When you deal with untrusted content (ex: user comments) you should also use a HTML sanitizer like [HTML Purifier](http://htmlpurifier.org/).
### Questions
From d98d60aaf336ebdfbd612a51cce4dc748409d659 Mon Sep 17 00:00:00 2001
From: Miguel Piedrafita
Date: Sun, 31 Dec 2017 22:10:48 +0100
Subject: [PATCH 069/106] Update license year
---
LICENSE.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/LICENSE.txt b/LICENSE.txt
index baca86f..4552494 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2013 Emanuil Rusev, erusev.com
+Copyright (c) 2018 Emanuil Rusev, erusev.com
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
@@ -17,4 +17,4 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
From 1244122b841f3930052a16c9f4ddd6858dc1060c Mon Sep 17 00:00:00 2001
From: Miguel Piedrafita
Date: Mon, 1 Jan 2018 14:09:31 +0100
Subject: [PATCH 070/106] Update LICENSE.txt
---
LICENSE.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/LICENSE.txt b/LICENSE.txt
index 4552494..8e7c764 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2018 Emanuil Rusev, erusev.com
+Copyright (c) 2013-2018 Emanuil Rusev, erusev.com
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
From 0e1043a8d6bb5bae93bfc65c99bd109e7f486b7b Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sun, 19 Feb 2017 16:12:04 +0000
Subject: [PATCH 071/106] consistent li items for loose list
---
Parsedown.php | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 757666e..877f5b8 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -515,10 +515,10 @@ class Parsedown
),
);
- if($name === 'ol')
+ if($name === 'ol')
{
$listStart = stristr($matches[0], '.', true);
-
+
if($listStart !== '1')
{
$Block['element']['attributes'] = array('start' => $listStart);
@@ -547,6 +547,8 @@ class Parsedown
{
$Block['li']['text'] []= '';
+ $Block['loose'] = true;
+
unset($Block['interrupted']);
}
@@ -595,6 +597,22 @@ class Parsedown
}
}
+ protected function blockListComplete(array $Block)
+ {
+ if (isset($Block['loose']))
+ {
+ foreach ($Block['element']['text'] as &$li)
+ {
+ if (end($li['text']) !== '')
+ {
+ $li['text'] []= '';
+ }
+ }
+ }
+
+ return $Block;
+ }
+
#
# Quote
From 7fd92a8fbd76dc9312dc7fb47fe05c8fb02fe3b7 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sun, 19 Feb 2017 16:19:55 +0000
Subject: [PATCH 072/106] update tests
---
test/data/paragraph_list.html | 4 +++-
test/data/sparse_dense_list.html | 8 ++++++--
test/data/sparse_list.html | 4 +++-
3 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/test/data/paragraph_list.html b/test/data/paragraph_list.html
index ced1c43..00a612c 100644
--- a/test/data/paragraph_list.html
+++ b/test/data/paragraph_list.html
@@ -8,5 +8,7 @@
li
-li
+
+li
+
\ No newline at end of file
diff --git a/test/data/sparse_dense_list.html b/test/data/sparse_dense_list.html
index 095bc73..58923f8 100644
--- a/test/data/sparse_dense_list.html
+++ b/test/data/sparse_dense_list.html
@@ -2,6 +2,10 @@
li
-li
-li
+
+li
+
+
+li
+
\ No newline at end of file
diff --git a/test/data/sparse_list.html b/test/data/sparse_list.html
index 452b2b8..9803d27 100644
--- a/test/data/sparse_list.html
+++ b/test/data/sparse_list.html
@@ -2,7 +2,9 @@
li
-li
+
+li
+
From 722b776684eb10a0cb4e59c45b51156670cf6465 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Mon, 29 Jan 2018 14:25:00 +0100
Subject: [PATCH 073/106] Test multiple multiline lists
---
test/data/multiline_lists.html | 10 ++++++++++
test/data/multiline_lists.md | 5 +++++
2 files changed, 15 insertions(+)
create mode 100644 test/data/multiline_lists.html
create mode 100644 test/data/multiline_lists.md
diff --git a/test/data/multiline_lists.html b/test/data/multiline_lists.html
new file mode 100644
index 0000000..a223792
--- /dev/null
+++ b/test/data/multiline_lists.html
@@ -0,0 +1,10 @@
+
+-
+
One
+First body copy
+
+-
+
Two
+Last body copy
+
+
\ No newline at end of file
diff --git a/test/data/multiline_lists.md b/test/data/multiline_lists.md
new file mode 100644
index 0000000..6251115
--- /dev/null
+++ b/test/data/multiline_lists.md
@@ -0,0 +1,5 @@
+1. One
+ First body copy
+
+2. Two
+ Last body copy
From e69374af0d3bc849272c0a6eec09910f220d6136 Mon Sep 17 00:00:00 2001
From: Emanuil Rusev
Date: Mon, 29 Jan 2018 20:52:27 +0200
Subject: [PATCH 074/106] improve readme
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index e1f2b53..92d7202 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-> You might also like [Caret](https://caret.io?ref=parsedown) - our Markdown editor for Mac / Windows / Linux.
+> I also make [Caret](https://caret.io?ref=parsedown), a Markdown editor for Mac, Windows and Linux.
## Parsedown
From e938ab4ffe74ebf84afa43d8875ab418fcfc8e4d Mon Sep 17 00:00:00 2001
From: Emanuil Rusev
Date: Mon, 29 Jan 2018 20:54:40 +0200
Subject: [PATCH 075/106] improve readme
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 92d7202..7bc3be1 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-> I also make [Caret](https://caret.io?ref=parsedown), a Markdown editor for Mac, Windows and Linux.
+> I also make [Caret](https://caret.io?ref=parsedown) - a Markdown editor for Mac, Windows and Linux.
## Parsedown
From c999a4b61bfc15d3eed74a40ce814afe6faa21ea Mon Sep 17 00:00:00 2001
From: Emanuil Rusev
Date: Mon, 29 Jan 2018 20:55:30 +0200
Subject: [PATCH 076/106] improve readme
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 7bc3be1..76b6905 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-> I also make [Caret](https://caret.io?ref=parsedown) - a Markdown editor for Mac, Windows and Linux.
+> I also make [Caret](https://caret.io?ref=parsedown) - a Markdown editor for Mac and PC.
## Parsedown
From ad62bf5a6fc25052949f4ebba29375363045a009 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Wed, 28 Feb 2018 17:01:31 +0000
Subject: [PATCH 077/106] Talk about safe mode in the README
---
README.md | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 76b6905..68f216e 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,20 @@ More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [t
### Security
-Parsedown does not sanitize the HTML that it generates. When you deal with untrusted content (ex: user comments) you should also use a HTML sanitizer like [HTML Purifier](http://htmlpurifier.org/).
+Parsedown is capable of escaping user-input within the HTML that it generates.
+Additionally Parsedown can attempt to sanitize additional scriping vectors (such
+as scripting link destinations). To tell Parsedown that it is processing untrusted
+user input, use the following:
+```php
+$parsedown = new Parsedown;
+$parsedown->setSafeMode(true);
+```
+
+It is recommended that when you deal with untrusted content (ex: user comments)
+you should employ defense-in-depth measures, like making use of a HTML sanitizer
+that allows HTML tags to be whitelisted, like [HTML Purifier](http://htmlpurifier.org/).
+Additionally, you should strongly consider
+[deploying a Content-Secuity-Policy](https://scotthelme.co.uk/content-security-policy-an-introduction/).
### Questions
From e2f3961f8092730980b0e09a8e78b66f81b62045 Mon Sep 17 00:00:00 2001
From: Hari KT
Date: Wed, 28 Feb 2018 23:25:38 +0530
Subject: [PATCH 078/106] Add test case to make sure issue 232 no longer exists
---
test/data/fenced_code_block.html | 6 +++++-
test/data/fenced_code_block.md | 7 +++++++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/test/data/fenced_code_block.html b/test/data/fenced_code_block.html
index ce8dfd0..565a541 100644
--- a/test/data/fenced_code_block.html
+++ b/test/data/fenced_code_block.html
@@ -4,4 +4,8 @@ $message = 'fenced code block';
echo $message;
tilde
echo 'language identifier';
-echo 'language identifier with non words';
\ No newline at end of file
+echo 'language identifier with non words';
+<?php
+echo "Hello World";
+?>
+<a href="http://auraphp.com" >Aura Project</a>
\ No newline at end of file
diff --git a/test/data/fenced_code_block.md b/test/data/fenced_code_block.md
index 9176ef4..62db24a 100644
--- a/test/data/fenced_code_block.md
+++ b/test/data/fenced_code_block.md
@@ -15,4 +15,11 @@ echo 'language identifier';
```c#
echo 'language identifier with non words';
+```
+
+```html+php
+
+Aura Project
```
\ No newline at end of file
From 096e16475639a3e934777f21715ac8152a03d136 Mon Sep 17 00:00:00 2001
From: Daniel Rudolf
Date: Wed, 28 Feb 2018 18:59:34 +0100
Subject: [PATCH 079/106] Update README.md
Sort "Who uses it" alphabetically, add Laravel + Pico
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 76b6905..2f65e56 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@ It passes most of the CommonMark tests. Most of the tests that don't pass deal w
**Who uses it?**
-[phpDocumentor](http://www.phpdoc.org/), [October CMS](http://octobercms.com/), [Bolt CMS](http://bolt.cm/), [Kirby CMS](http://getkirby.com/), [Grav CMS](http://getgrav.org/), [Statamic CMS](http://www.statamic.com/), [Herbie CMS](http://www.getherbie.org/), [RaspberryPi.org](http://www.raspberrypi.org/), [Symfony demo](https://github.com/symfony/symfony-demo) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
+[Bolt CMS](http://bolt.cm/), [Grav CMS](http://getgrav.org/), [Herbie CMS](http://www.getherbie.org/), [Kirby CMS](http://getkirby.com/), [Laravel](https://laravel.com/), [October CMS](http://octobercms.com/), [phpDocumentor](http://www.phpdoc.org/), [Pico](http://picocms.org), [RaspberryPi.org](http://www.raspberrypi.org/), [Statamic CMS](http://www.statamic.com/), [Symfony demo](https://github.com/symfony/symfony-demo) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
**How can I help?**
From cc53d5ae2959b3ea946a7b4f79b82cd55c7225c8 Mon Sep 17 00:00:00 2001
From: Daniel Rudolf
Date: Wed, 28 Feb 2018 19:12:19 +0100
Subject: [PATCH 080/106] Travis: Issue build error when Parsedown::version
isn't up-to-date
---
.travis.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.travis.yml b/.travis.yml
index db5d725..b9361a6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -26,3 +26,4 @@ install:
script:
- vendor/bin/phpunit
- vendor/bin/phpunit test/CommonMarkTestWeak.php || true
+ - '[ -z "$TRAVIS_TAG" ] || [ "$TRAVIS_TAG" == "$(php -r "require(\"Parsedown.php\"); echo Parsedown::version;")" ]'
From fa89f0d743792dac266780d24f5ff7fe77c2ca6d Mon Sep 17 00:00:00 2001
From: Daniel Rudolf
Date: Wed, 28 Feb 2018 20:42:25 +0100
Subject: [PATCH 081/106] Add mbstring dependency to composer.json
---
composer.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/composer.json b/composer.json
index dc349d4..f8b40f8 100644
--- a/composer.json
+++ b/composer.json
@@ -13,7 +13,8 @@
}
],
"require": {
- "php": ">=5.3.0"
+ "php": ">=5.3.0",
+ "ext-mbstring": "*"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35"
From 72d30d33bc126676bff7c13c27155bd3e45c3a9e Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Tue, 13 Jun 2017 20:28:32 +0100
Subject: [PATCH 082/106] allow element to have no name
---
Parsedown.php | 33 ++++++++++++++++++++-------------
1 file changed, 20 insertions(+), 13 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index e0ce3ac..cd93e9c 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1460,26 +1460,33 @@ class Parsedown
$Element = $this->sanitiseElement($Element);
}
- $markup = '<'.$Element['name'];
+ $hasName = isset($Element['name']);
- if (isset($Element['attributes']))
+ $markup = '';
+
+ if ($hasName)
{
- foreach ($Element['attributes'] as $name => $value)
- {
- if ($value === null)
- {
- continue;
- }
+ $markup .= '<'.$Element['name'];
- $markup .= ' '.$name.'="'.self::escape($value).'"';
+ if (isset($Element['attributes']))
+ {
+ foreach ($Element['attributes'] as $name => $value)
+ {
+ if ($value === null)
+ {
+ continue;
+ }
+
+ $markup .= ' '.$name.'="'.self::escape($value).'"';
+ }
}
}
if (isset($Element['text']))
{
- $markup .= '>';
+ $markup .= $hasName ? '>' : '';
- if (!isset($Element['nonNestables']))
+ if (!isset($Element['nonNestables']))
{
$Element['nonNestables'] = array();
}
@@ -1493,9 +1500,9 @@ class Parsedown
$markup .= self::escape($Element['text'], true);
}
- $markup .= ''.$Element['name'].'>';
+ $markup .= $hasName ? ''.$Element['name'].'>' : '';
}
- else
+ elseif ($hasName)
{
$markup .= ' />';
}
From 90439ef882500d98f581e725833bec370ece6bb2 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 1 Mar 2018 18:44:11 +0000
Subject: [PATCH 083/106] Rewrite section
---
README.md | 32 +++++++++++++++++++++++++-------
1 file changed, 25 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 68f216e..9bc3657 100644
--- a/README.md
+++ b/README.md
@@ -39,19 +39,37 @@ More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [t
### Security
Parsedown is capable of escaping user-input within the HTML that it generates.
-Additionally Parsedown can attempt to sanitize additional scriping vectors (such
-as scripting link destinations). To tell Parsedown that it is processing untrusted
-user input, use the following:
+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:
```php
$parsedown = new Parsedown;
$parsedown->setSafeMode(true);
```
-It is recommended that when you deal with untrusted content (ex: user comments)
-you should employ defense-in-depth measures, like making use of a HTML sanitizer
+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](http://htmlpurifier.org/).
-Additionally, you should strongly consider
-[deploying a Content-Secuity-Policy](https://scotthelme.co.uk/content-security-policy-an-introduction/).
+
+In both cases you should strongly consider employing defence-in-depth measures,
+like [deploying a Content-Secuity-Policy](https://scotthelme.co.uk/content-security-policy-an-introduction/)
+(making use of 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:
+```php
+$parsedown = new Parsedown;
+$parsedown->setMarkupEscaped(true);
+```
+
+Beware that this still allows users to insert unsafe scripting vectors, such as links like `[xss](javascript:alert%281%29)`.
### Questions
From 9b1f54b9d3bbe45b5a204a3a3c731fb5dccca695 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 1 Mar 2018 18:45:38 +0000
Subject: [PATCH 084/106] Lets be consistent with hyphenation
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 9bc3657..b67a886 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,7 @@ $parsedown = new Parsedown;
$parsedown->setSafeMode(true);
```
-If instead, you wish to allow HTML within untrusted user input, but still want
+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](http://htmlpurifier.org/).
From f3068df45a80f98e96666682423b025c51cf301d Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 1 Mar 2018 19:54:58 +0000
Subject: [PATCH 085/106] Remove extra line breaks
---
README.md | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/README.md b/README.md
index b67a886..e950bd2 100644
--- a/README.md
+++ b/README.md
@@ -38,23 +38,17 @@ More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [t
### 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.
+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:
```php
$parsedown = new Parsedown;
$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](http://htmlpurifier.org/).
+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](http://htmlpurifier.org/).
-In both cases you should strongly consider employing defence-in-depth measures,
-like [deploying a Content-Secuity-Policy](https://scotthelme.co.uk/content-security-policy-an-introduction/)
-(making use of 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.
+In both cases you should strongly consider employing defence-in-depth measures, like [deploying a Content-Secuity-Policy](https://scotthelme.co.uk/content-security-policy-an-introduction/) (making use of 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
From 33b51eaefa8c0ef4d87b089493f5ed0df78f5108 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Fri, 2 Mar 2018 01:13:58 +0000
Subject: [PATCH 086/106] Fix typo
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 1b629e6..fc0419c 100644
--- a/README.md
+++ b/README.md
@@ -48,7 +48,7 @@ $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](http://htmlpurifier.org/).
-In both cases you should strongly consider employing defence-in-depth measures, like [deploying a Content-Secuity-Policy](https://scotthelme.co.uk/content-security-policy-an-introduction/) (making use of 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.
+In both cases you should strongly consider employing defence-in-depth measures, like [deploying a Content-Security-Policy](https://scotthelme.co.uk/content-security-policy-an-introduction/) (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
From e5bf9560d72cd38fcc5ad73d3f1a76faa94f1c1e Mon Sep 17 00:00:00 2001
From: Emanuil Rusev
Date: Fri, 2 Mar 2018 17:37:16 +0200
Subject: [PATCH 087/106] add Laravel to who uses it
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index fc0419c..ed47c11 100644
--- a/README.md
+++ b/README.md
@@ -79,7 +79,7 @@ It passes most of the CommonMark tests. Most of the tests that don't pass deal w
**Who uses it?**
-[Bolt CMS](http://bolt.cm/), [Grav CMS](http://getgrav.org/), [Herbie CMS](http://www.getherbie.org/), [Kirby CMS](http://getkirby.com/), [Laravel](https://laravel.com/), [October CMS](http://octobercms.com/), [phpDocumentor](http://www.phpdoc.org/), [Pico](http://picocms.org), [RaspberryPi.org](http://www.raspberrypi.org/), [Statamic CMS](http://www.statamic.com/), [Symfony demo](https://github.com/symfony/symfony-demo) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
+[Laravel](https://github.com/laravel/framework), [Bolt CMS](http://bolt.cm/), [Grav CMS](http://getgrav.org/), [Herbie CMS](http://www.getherbie.org/), [Kirby CMS](http://getkirby.com/), [Laravel](https://laravel.com/), [October CMS](http://octobercms.com/), [phpDocumentor](http://www.phpdoc.org/), [Pico](http://picocms.org), [RaspberryPi.org](http://www.raspberrypi.org/), [Statamic CMS](http://www.statamic.com/), [Symfony demo](https://github.com/symfony/symfony-demo) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
**How can I help?**
From a18bf495edd81d68e30e6c5e7f9c602d4e503cc5 Mon Sep 17 00:00:00 2001
From: Emanuil Rusev
Date: Fri, 2 Mar 2018 17:40:21 +0200
Subject: [PATCH 088/106] refactor who uses it section in readme
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index ed47c11..c6006d4 100644
--- a/README.md
+++ b/README.md
@@ -79,7 +79,7 @@ It passes most of the CommonMark tests. Most of the tests that don't pass deal w
**Who uses it?**
-[Laravel](https://github.com/laravel/framework), [Bolt CMS](http://bolt.cm/), [Grav CMS](http://getgrav.org/), [Herbie CMS](http://www.getherbie.org/), [Kirby CMS](http://getkirby.com/), [Laravel](https://laravel.com/), [October CMS](http://octobercms.com/), [phpDocumentor](http://www.phpdoc.org/), [Pico](http://picocms.org), [RaspberryPi.org](http://www.raspberrypi.org/), [Statamic CMS](http://www.statamic.com/), [Symfony demo](https://github.com/symfony/symfony-demo) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
+[Laravel Framework](https://laravel.com/), [Bolt CMS](http://bolt.cm/), [Grav CMS](http://getgrav.org/), [Herbie CMS](http://www.getherbie.org/), [Kirby CMS](http://getkirby.com/), [October CMS](http://octobercms.com/), [Pico CMS](http://picocms.org), [phpDocumentor](http://www.phpdoc.org/), [RaspberryPi.org](http://www.raspberrypi.org/), [Statamic CMS](http://www.statamic.com/), [Symfony demo](https://github.com/symfony/symfony-demo) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
**How can I help?**
From 253822057aae085f7ae8c405905743b17d7b04c9 Mon Sep 17 00:00:00 2001
From: Emanuil Rusev
Date: Fri, 2 Mar 2018 17:46:45 +0200
Subject: [PATCH 089/106] refactor who uses it section in readme a bit more
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index c6006d4..b5d9ed2 100644
--- a/README.md
+++ b/README.md
@@ -79,7 +79,7 @@ It passes most of the CommonMark tests. Most of the tests that don't pass deal w
**Who uses it?**
-[Laravel Framework](https://laravel.com/), [Bolt CMS](http://bolt.cm/), [Grav CMS](http://getgrav.org/), [Herbie CMS](http://www.getherbie.org/), [Kirby CMS](http://getkirby.com/), [October CMS](http://octobercms.com/), [Pico CMS](http://picocms.org), [phpDocumentor](http://www.phpdoc.org/), [RaspberryPi.org](http://www.raspberrypi.org/), [Statamic CMS](http://www.statamic.com/), [Symfony demo](https://github.com/symfony/symfony-demo) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
+[Laravel Framework](https://laravel.com/), [Bolt CMS](http://bolt.cm/), [Grav CMS](http://getgrav.org/), [Herbie CMS](http://www.getherbie.org/), [Kirby CMS](http://getkirby.com/), [October CMS](http://octobercms.com/), [Pico CMS](http://picocms.org), [Statamic CMS](http://www.statamic.com/), [phpDocumentor](http://www.phpdoc.org/), [RaspberryPi.org](http://www.raspberrypi.org/), [Symfony demo](https://github.com/symfony/symfony-demo) and [more](https://packagist.org/packages/erusev/parsedown/dependents).
**How can I help?**
From ae7e8e50672dc5f16cf59097f7b147a0e26b2b55 Mon Sep 17 00:00:00 2001
From: "Luiz Paulo \"Bills"
Date: Wed, 7 Mar 2018 21:51:35 -0300
Subject: [PATCH 090/106] bump version
---
Parsedown.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Parsedown.php b/Parsedown.php
index e0ce3ac..e3f045f 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -17,7 +17,7 @@ class Parsedown
{
# ~
- const version = '1.6.0';
+ const version = '1.7.0';
# ~
From 98573341861280a80cca9b6223e1540de3f1d6fb Mon Sep 17 00:00:00 2001
From: "Luiz Paulo \"Bills"
Date: Wed, 7 Mar 2018 22:04:55 -0300
Subject: [PATCH 091/106] bump version
---
Parsedown.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Parsedown.php b/Parsedown.php
index e3f045f..87d612a 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -17,7 +17,7 @@ class Parsedown
{
# ~
- const version = '1.7.0';
+ const version = '1.7.1';
# ~
From f70d96479aa9ebca173c0e2829e8ee051f16c200 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Fri, 9 Mar 2018 16:48:32 +0000
Subject: [PATCH 092/106] Add test case for email surrounded by tags
---
test/data/email.html | 3 ++-
test/data/email.md | 4 +++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/test/data/email.html b/test/data/email.html
index c40759c..93e0705 100644
--- a/test/data/email.html
+++ b/test/data/email.html
@@ -1 +1,2 @@
-my email is me@example.com
\ No newline at end of file
+my email is me@example.com
+html tags shouldn't start an email autolink first.last@example.com
\ No newline at end of file
diff --git a/test/data/email.md b/test/data/email.md
index 26b7b6c..00b6969 100644
--- a/test/data/email.md
+++ b/test/data/email.md
@@ -1 +1,3 @@
-my email is
\ No newline at end of file
+my email is
+
+html tags shouldn't start an email autolink first.last@example.com
\ No newline at end of file
From 721b885dd3d569b64377bed548efeb743ce5cbf7 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Fri, 9 Mar 2018 16:49:04 +0000
Subject: [PATCH 093/106] Fix #565 by validating email as defined in commonmark
spec
---
Parsedown.php | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 87d612a..685d6df 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1142,8 +1142,14 @@ class Parsedown
protected function inlineEmailTag($Excerpt)
{
- if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\S+?@\S+?)>/i', $Excerpt['text'], $matches))
- {
+ $commonMarkEmail = '[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9]'
+ .'(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?'
+ .'(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*'
+ ;
+
+ if (strpos($Excerpt['text'], '>') !== false
+ and preg_match("/^<((mailto:)?$commonMarkEmail)>/i", $Excerpt['text'], $matches)
+ ){
$url = $matches[1];
if ( ! isset($matches[2]))
@@ -1479,7 +1485,7 @@ class Parsedown
{
$markup .= '>';
- if (!isset($Element['nonNestables']))
+ if (!isset($Element['nonNestables']))
{
$Element['nonNestables'] = array();
}
From 19f1bb9353506f9c25c8b803333606cd6568cfc3 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Fri, 9 Mar 2018 16:54:21 +0000
Subject: [PATCH 094/106] Disable backtracking where the regex doesn't need it
---
Parsedown.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Parsedown.php b/Parsedown.php
index 685d6df..27a35bf 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1142,7 +1142,7 @@ class Parsedown
protected function inlineEmailTag($Excerpt)
{
- $commonMarkEmail = '[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9]'
+ $commonMarkEmail = '[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]++@[a-zA-Z0-9]'
.'(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?'
.'(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*'
;
From 6830c3339f70046183280ceaba83bcbc5c60634b Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Fri, 9 Mar 2018 17:38:41 +0000
Subject: [PATCH 095/106] Readability
Thanks @PhrozenByte for the suggestion :)
---
Parsedown.php | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 27a35bf..c0dbf08 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1142,10 +1142,10 @@ class Parsedown
protected function inlineEmailTag($Excerpt)
{
- $commonMarkEmail = '[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]++@[a-zA-Z0-9]'
- .'(?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?'
- .'(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*'
- ;
+ $hostnameLabel = '[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?';
+
+ $commonMarkEmail = '[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]++@'
+ . $hostnameLabel . '(?:\.' . $hostnameLabel . ')*';
if (strpos($Excerpt['text'], '>') !== false
and preg_match("/^<((mailto:)?$commonMarkEmail)>/i", $Excerpt['text'], $matches)
From e6444bb57e60d56648ea60cf6b30f737c052e2c1 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 15 Mar 2018 10:42:29 +0000
Subject: [PATCH 096/106] Add unsafeHtml option for extensions to use on
trusted input
---
Parsedown.php | 21 +++++++++++++++++++--
test/ParsedownTest.php | 12 ++++++++++++
test/UnsafeExtension.php | 14 ++++++++++++++
3 files changed, 45 insertions(+), 2 deletions(-)
create mode 100644 test/UnsafeExtension.php
diff --git a/Parsedown.php b/Parsedown.php
index 2725170..b274f52 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1488,7 +1488,20 @@ class Parsedown
}
}
+ $unsafeHtml = false;
if (isset($Element['text']))
+ {
+ $text = $Element['text'];
+ }
+ // very strongly consider an alternative if you're writing an
+ // extension
+ elseif (isset($Element['unsafeHtml']) and !$this->safeMode)
+ {
+ $text = $Element['unsafeHtml'];
+ $unsafeHtml = true;
+ }
+
+ if (isset($text))
{
$markup .= $hasName ? '>' : '';
@@ -1499,11 +1512,15 @@ class Parsedown
if (isset($Element['handler']))
{
- $markup .= $this->{$Element['handler']}($Element['text'], $Element['nonNestables']);
+ $markup .= $this->{$Element['handler']}($text, $Element['nonNestables']);
+ }
+ elseif ($unsafeHtml !== true or $this->safeMode)
+ {
+ $markup .= self::escape($text, true);
}
else
{
- $markup .= self::escape($Element['text'], true);
+ $markup .= $text;
}
$markup .= $hasName ? ''.$Element['name'].'>' : '';
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index c28cedf..3cd796e 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -1,4 +1,5 @@
assertEquals($expectedMarkup, $actualMarkup);
}
+ function testUnsafeHtml()
+ {
+ $markdown = "```php\nfoobar\n```";
+ $expectedMarkup = 'foobar
';
+
+ $unsafeExtension = new UnsafeExtension;
+ $actualMarkup = $unsafeExtension->text($markdown);
+
+ $this->assertEquals($expectedMarkup, $actualMarkup);
+ }
+
function data()
{
$data = array();
diff --git a/test/UnsafeExtension.php b/test/UnsafeExtension.php
new file mode 100644
index 0000000..f2343c4
--- /dev/null
+++ b/test/UnsafeExtension.php
@@ -0,0 +1,14 @@
+$text
";
+
+ return $Block;
+ }
+}
From e4c5be026d4c776261edf5e8ef802e258bfaee9f Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 15 Mar 2018 11:00:03 +0000
Subject: [PATCH 097/106] Further attempt to dissuade this feature's use
---
test/UnsafeExtension.php | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/test/UnsafeExtension.php b/test/UnsafeExtension.php
index f2343c4..9a8dcc7 100644
--- a/test/UnsafeExtension.php
+++ b/test/UnsafeExtension.php
@@ -7,6 +7,11 @@ class UnsafeExtension extends Parsedown
$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']['unsafeHtml'] = "$text
";
return $Block;
From ef7ed7b66cf22b268c459a98e4fe3f7f809d40b5 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 15 Mar 2018 11:09:55 +0000
Subject: [PATCH 098/106] Still grab the text if safe mode enabled, but output
it escaped
---
Parsedown.php | 3 ++-
test/ParsedownTest.php | 6 ++++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/Parsedown.php b/Parsedown.php
index b274f52..9558525 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1495,9 +1495,10 @@ class Parsedown
}
// very strongly consider an alternative if you're writing an
// extension
- elseif (isset($Element['unsafeHtml']) and !$this->safeMode)
+ elseif (isset($Element['unsafeHtml']))
{
$text = $Element['unsafeHtml'];
+
$unsafeHtml = true;
}
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index 3cd796e..8f3e6c8 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -60,11 +60,17 @@ class ParsedownTest extends TestCase
{
$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 data()
From 3fc54bc966caea29a633dba41ebb6728a917ee67 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 15 Mar 2018 19:46:03 +0000
Subject: [PATCH 099/106] Allow extension to "vouch" for raw HTML they produce
Rename "unsafeHtml" to "rawHtml"
---
Parsedown.php | 25 ++++++++++++++++++++-----
test/ParsedownTest.php | 21 +++++++++++++++++++--
test/SampleExtensions.php | 39 +++++++++++++++++++++++++++++++++++++++
test/UnsafeExtension.php | 19 -------------------
4 files changed, 78 insertions(+), 26 deletions(-)
create mode 100644 test/SampleExtensions.php
delete mode 100644 test/UnsafeExtension.php
diff --git a/Parsedown.php b/Parsedown.php
index 9558525..160594e 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1488,18 +1488,33 @@ class Parsedown
}
}
- $unsafeHtml = false;
+ $permitRawHtml = false;
+
if (isset($Element['text']))
{
$text = $Element['text'];
}
// very strongly consider an alternative if you're writing an
// extension
- elseif (isset($Element['unsafeHtml']))
+ elseif (isset($Element['rawHtml']))
{
- $text = $Element['unsafeHtml'];
+ $text = $Element['rawHtml'];
- $unsafeHtml = true;
+ $allowRawHtmlInSafeMode = false;
+
+ if (isset($Element['allowRawHtmlInSafeMode']))
+ {
+ $allowRawHtmlInSafeMode = (true === $Element['allowRawHtmlInSafeMode']);
+ }
+
+ if ($this->safeMode !== true)
+ {
+ $permitRawHtml = true;
+ }
+ elseif ($this->safeMode and $allowRawHtmlInSafeMode)
+ {
+ $permitRawHtml = true;
+ }
}
if (isset($text))
@@ -1515,7 +1530,7 @@ class Parsedown
{
$markup .= $this->{$Element['handler']}($text, $Element['nonNestables']);
}
- elseif ($unsafeHtml !== true or $this->safeMode)
+ elseif ($permitRawHtml !== true)
{
$markup .= self::escape($text, true);
}
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index 8f3e6c8..cc0cc1d 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -1,5 +1,5 @@
assertEquals($expectedMarkup, $actualMarkup);
}
- function testUnsafeHtml()
+ function testRawHtml()
{
$markdown = "```php\nfoobar\n```";
$expectedMarkup = 'foobar
';
@@ -73,6 +73,23 @@ class ParsedownTest extends TestCase
$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..6d7ec9f
--- /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 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'] = "$text
";
+ $Block['element']['text']['allowRawHtmlInSafeMode'] = true;
+
+ return $Block;
+ }
+}
diff --git a/test/UnsafeExtension.php b/test/UnsafeExtension.php
deleted file mode 100644
index 9a8dcc7..0000000
--- a/test/UnsafeExtension.php
+++ /dev/null
@@ -1,19 +0,0 @@
-$text";
-
- return $Block;
- }
-}
From 624a08b7eb8c3a4b0b99e7175251b76483e387cf Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 15 Mar 2018 19:55:33 +0000
Subject: [PATCH 100/106] Update commment
---
test/SampleExtensions.php | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/test/SampleExtensions.php b/test/SampleExtensions.php
index 6d7ec9f..c66190c 100644
--- a/test/SampleExtensions.php
+++ b/test/SampleExtensions.php
@@ -28,9 +28,10 @@ class TrustDelegatedExtension extends Parsedown
// 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).
+ // 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;
From 88dc94989039d37e09f186e94ec3a3964af82b36 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sun, 18 Mar 2018 19:42:14 +0000
Subject: [PATCH 101/106] Refactor based on suggestion by @PhrozenByte
---
Parsedown.php | 19 +++----------------
1 file changed, 3 insertions(+), 16 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 160594e..bf08700 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1500,21 +1500,8 @@ class Parsedown
{
$text = $Element['rawHtml'];
- $allowRawHtmlInSafeMode = false;
-
- if (isset($Element['allowRawHtmlInSafeMode']))
- {
- $allowRawHtmlInSafeMode = (true === $Element['allowRawHtmlInSafeMode']);
- }
-
- if ($this->safeMode !== true)
- {
- $permitRawHtml = true;
- }
- elseif ($this->safeMode and $allowRawHtmlInSafeMode)
- {
- $permitRawHtml = true;
- }
+ $allowRawHtmlInSafeMode = isset($Element['allowRawHtmlInSafeMode']) && $Element['allowRawHtmlInSafeMode'];
+ $permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode;
}
if (isset($text))
@@ -1530,7 +1517,7 @@ class Parsedown
{
$markup .= $this->{$Element['handler']}($text, $Element['nonNestables']);
}
- elseif ($permitRawHtml !== true)
+ elseif (!$permitRawHtml)
{
$markup .= self::escape($text, true);
}
From 972648ff64228ee4c775febef962e863d16c853e Mon Sep 17 00:00:00 2001
From: Carsten Brandt
Date: Tue, 20 Mar 2018 16:56:40 +0100
Subject: [PATCH 102/106] Added inline example to README
see https://github.com/erusev/parsedown/issues/562
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index b5d9ed2..9a4bb36 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,8 @@ Include `Parsedown.php` or install [the composer package](https://packagist.org/
$Parsedown = new Parsedown();
echo $Parsedown->text('Hello _Parsedown_!'); # prints: Hello Parsedown!
+// you can also parse inline markdown only
+echo $Parsedown->line('Hello _Parsedown_!'); # prints: Hello Parsedown!
```
More examples in [the wiki](https://github.com/erusev/parsedown/wiki/) and in [this video tutorial](http://youtu.be/wYZBY8DEikI).
From 913e04782f970bb8ff1fa1441aa127dfa2155867 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sun, 25 Mar 2018 22:50:16 +0100
Subject: [PATCH 103/106] Add failing test cases to be fixed
---
test/data/setext_header_spaces.html | 12 ++++++++++++
test/data/setext_header_spaces.md | 29 +++++++++++++++++++++++++++++
2 files changed, 41 insertions(+)
create mode 100644 test/data/setext_header_spaces.html
create mode 100644 test/data/setext_header_spaces.md
diff --git a/test/data/setext_header_spaces.html b/test/data/setext_header_spaces.html
new file mode 100644
index 0000000..daf97c0
--- /dev/null
+++ b/test/data/setext_header_spaces.html
@@ -0,0 +1,12 @@
+trailing space
+trailing space
+leading and trailing space
+leading and trailing space
+1 leading space
+1 leading space
+3 leading spaces
+3 leading spaces
+too many leading spaces
+==
+too many leading spaces
+--
\ No newline at end of file
diff --git a/test/data/setext_header_spaces.md b/test/data/setext_header_spaces.md
new file mode 100644
index 0000000..4ac35bb
--- /dev/null
+++ b/test/data/setext_header_spaces.md
@@ -0,0 +1,29 @@
+trailing space
+==
+
+trailing space
+--
+
+leading and trailing space
+ ==
+
+leading and trailing space
+ --
+
+1 leading space
+ ==
+
+1 leading space
+ --
+
+3 leading spaces
+ ==
+
+3 leading spaces
+ --
+
+too many leading spaces
+ ==
+
+too many leading spaces
+ --
\ No newline at end of file
From f71bec00f4053854ebaf2b842724e35aec6cd5b6 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sun, 25 Mar 2018 22:50:42 +0100
Subject: [PATCH 104/106] Fix space handling in setext headings
---
Parsedown.php | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index bf08700..844a504 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -705,8 +705,10 @@ class Parsedown
return;
}
- if (chop($Line['text'], $Line['text'][0]) === '')
- {
+ if (
+ chop(chop($Line['text'], ' '), $Line['text'][0]) === ''
+ and $Line['indent'] < 4
+ ) {
$Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2';
return $Block;
From e7fbbf537b36d2748bef4dddbff0f976d3e7cafe Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Mon, 26 Mar 2018 18:45:34 +0100
Subject: [PATCH 105/106] Add repo specific paths to .gitignore
---
.gitignore | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 .gitignore
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d8a7996
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+composer.lock
+vendor/
From dd9f4036ee92e2d281b8f5b0501c3e9e3f34d11c Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Mon, 26 Mar 2018 18:47:33 +0100
Subject: [PATCH 106/106] Add .gitignore to export ignore in .gitattribtutes
---
.gitattributes | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitattributes b/.gitattributes
index 001c45c..c1a5d9a 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,5 +1,6 @@
# Ignore all tests for archive
/test export-ignore
/.gitattributes export-ignore
+/.gitignore export-ignore
/.travis.yml export-ignore
/phpunit.xml.dist export-ignore