diff --git a/Parsedown.php b/Parsedown.php
index fdc2aa6..1d9839b 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -294,7 +294,7 @@ class Parsedown
}
$markup .= "\n";
- $markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']);
+ $markup .= $this->element($Block['element']);
}
$markup .= "\n";
@@ -386,7 +386,7 @@ class Parsedown
if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!')
{
$Block = array(
- 'markup' => $Line['body'],
+ 'element' => array('rawHtml' => $Line['body']),
);
if (preg_match('/-->$/', $Line['text']))
@@ -405,7 +405,7 @@ class Parsedown
return;
}
- $Block['markup'] .= "\n" . $Line['body'];
+ $Block['element']['rawHtml'] .= "\n" . $Line['body'];
if (preg_match('/-->$/', $Line['text']))
{
@@ -777,7 +777,7 @@ class Parsedown
$Block = array(
'name' => $matches[1],
- 'markup' => $Line['text'],
+ 'element' => array('rawHtml' => $Line['text']),
);
return $Block;
@@ -791,7 +791,7 @@ class Parsedown
return;
}
- $Block['markup'] .= "\n".$Line['body'];
+ $Block['element']['rawHtml'] .= "\n".$Line['body'];
return $Block;
}
@@ -1007,13 +1007,11 @@ class Parsedown
#
protected $InlineTypes = array(
- '"' => array('SpecialCharacter'),
'!' => array('Image'),
'&' => array('SpecialCharacter'),
'*' => array('Emphasis'),
':' => array('Url'),
- '<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'),
- '>' => array('SpecialCharacter'),
+ '<' => array('UrlTag', 'EmailTag', 'Markup'),
'[' => array('Link'),
'_' => array('Emphasis'),
'`' => array('Code'),
@@ -1023,7 +1021,7 @@ class Parsedown
# ~
- protected $inlineMarkerList = '!"*_&[:<>`~\\';
+ protected $inlineMarkerList = '!*_&[:<`~\\';
#
# ~
@@ -1087,7 +1085,7 @@ class Parsedown
$markup .= $this->unmarkedText($unmarkedText);
# compile the inline
- $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']);
+ $markup .= $this->element($Inline['element']);
# remove the examined text
$text = substr($text, $Inline['position'] + $Inline['extent']);
@@ -1113,6 +1111,41 @@ class Parsedown
# ~
#
+ protected function inlineText($text)
+ {
+ $Inline = array(
+ 'extent' => strlen($text),
+ 'element' => array(
+ 'handler' => 'elements',
+ ),
+ );
+
+ if ($this->breaksEnabled)
+ {
+ $Inline['element']['text'] = self::pregReplaceElements(
+ '/[ ]*\n/',
+ array(
+ array('name' => 'br'),
+ array('text' => "\n"),
+ ),
+ $text
+ );
+ }
+ else
+ {
+ $Inline['element']['text'] = self::pregReplaceElements(
+ '/(?:[ ][ ]+|[ ]*\\\\)\n/',
+ array(
+ array('name' => 'br'),
+ array('text' => "\n"),
+ ),
+ $text
+ );
+ }
+
+ return $Inline;
+ }
+
protected function inlineCode($Excerpt)
{
$marker = $Excerpt['text'][0];
@@ -1199,7 +1232,7 @@ class Parsedown
if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters))
{
return array(
- 'markup' => $Excerpt['text'][1],
+ 'element' => array('rawHtml' => $Excerpt['text'][1]),
'extent' => 2,
);
}
@@ -1321,7 +1354,7 @@ class Parsedown
if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w[\w-]*[ ]*>/s', $Excerpt['text'], $matches))
{
return array(
- 'markup' => $matches[0],
+ 'element' => array('rawHtml' => $matches[0]),
'extent' => strlen($matches[0]),
);
}
@@ -1329,7 +1362,7 @@ class Parsedown
if ($Excerpt['text'][1] === '!' and preg_match('/^/s', $Excerpt['text'], $matches))
{
return array(
- 'markup' => $matches[0],
+ 'element' => array('rawHtml' => $matches[0]),
'extent' => strlen($matches[0]),
);
}
@@ -1337,7 +1370,7 @@ class Parsedown
if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w[\w-]*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\/?>/s', $Excerpt['text'], $matches))
{
return array(
- 'markup' => $matches[0],
+ 'element' => array('rawHtml' => $matches[0]),
'extent' => strlen($matches[0]),
);
}
@@ -1345,23 +1378,15 @@ class Parsedown
protected function inlineSpecialCharacter($Excerpt)
{
- if ($Excerpt['text'][0] === '&' and ! preg_match('/^?\w+;/', $Excerpt['text']))
+ if (preg_match('/^&(#?+[0-9a-zA-Z]++);/', $Excerpt['text'], $matches))
{
return array(
- 'markup' => '&',
- 'extent' => 1,
+ 'element' => array('rawHtml' => '&'.$matches[1].';'),
+ 'extent' => strlen($matches[0]),
);
}
- $SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot');
-
- if (isset($SpecialCharacter[$Excerpt['text'][0]]))
- {
- return array(
- 'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';',
- 'extent' => 1,
- );
- }
+ return;
}
protected function inlineStrikethrough($Excerpt)
@@ -1434,17 +1459,8 @@ class Parsedown
protected function unmarkedText($text)
{
- if ($this->breaksEnabled)
- {
- $text = preg_replace('/[ ]*\n/', "
\n", $text);
- }
- else
- {
- $text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\n/', "
\n", $text);
- $text = str_replace(" \n", "\n", $text);
- }
-
- return $text;
+ $Inline = $this->inlineText($text);
+ return $this->element($Inline['element']);
}
#
@@ -1532,12 +1548,18 @@ class Parsedown
{
$markup = '';
+ $autoBreak = true;
+
foreach ($Elements as $Element)
{
- $markup .= "\n" . $this->element($Element);
+ // (autobreak === false) covers both sides of an element
+ $autoBreak = !$autoBreak ? $autoBreak : isset($Element['name']);
+
+ $markup .= ($autoBreak ? "\n" : '') . $this->element($Element);
+ $autoBreak = isset($Element['name']);
}
- $markup .= "\n";
+ $markup .= $autoBreak ? "\n" : '';
return $markup;
}
@@ -1563,6 +1585,39 @@ class Parsedown
return $markup;
}
+ #
+ # AST Convenience
+ #
+
+ /**
+ * Replace occurrences $regexp with $Elements in $text. Return an array of
+ * elements representing the replacement.
+ */
+ protected static function pregReplaceElements($regexp, $Elements, $text)
+ {
+ $newElements = array();
+
+ while (preg_match($regexp, $text, $matches, PREG_OFFSET_CAPTURE))
+ {
+ $offset = $matches[0][1];
+ $before = substr($text, 0, $offset);
+ $after = substr($text, $offset + strlen($matches[0][0]));
+
+ $newElements[] = array('text' => $before);
+
+ foreach ($Elements as $Element)
+ {
+ $newElements[] = $Element;
+ }
+
+ $text = $after;
+ }
+
+ $newElements[] = array('text' => $text);
+
+ return $newElements;
+ }
+
#
# Deprecated Methods
#
@@ -1582,6 +1637,12 @@ class Parsedown
'img' => 'src',
);
+ if ( ! isset($Element['name']))
+ {
+ unset($Element['attributes']);
+ return $Element;
+ }
+
if (isset($safeUrlNameToAtt[$Element['name']]))
{
$Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]);
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index 2f58418..01b4e25 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -159,12 +159,12 @@ MARKDOWN_WITH_MARKUP;
<div>content</div>
sparse:
<div> -<div class="inner"> +<div class="inner"> content </div> </div>
paragraph
-<style type="text/css"> +
<style type="text/css"> p { color: red; }