1
0
mirror of https://github.com/erusev/parsedown.git synced 2023-08-10 21:13:06 +03:00

Compare commits

..

19 Commits

Author SHA1 Message Date
e8d8801db4 resolve #135 2014-05-01 02:44:35 +03:00
521803cdcd resolve #136 2014-05-01 02:42:01 +03:00
0eb480324c resolve #145 2014-05-01 02:02:14 +03:00
7c78aff578 resolve #163 2014-05-01 01:47:14 +03:00
2a5f99547c resolve #162 2014-05-01 01:05:31 +03:00
e373391e7d resolve #164 2014-05-01 00:29:21 +03:00
9fa415bcc5 resolve #160 2014-04-28 21:54:38 +03:00
37416b5f07 simplify folder name 2014-04-28 21:53:34 +03:00
83d3e3dbbf improve readability 2014-04-28 02:27:05 +03:00
307a987cb6 improve naming consistency 2014-04-28 02:14:46 +03:00
eab3cbf255 remove unnecessary nesting 2014-04-28 02:10:18 +03:00
cf7f32f891 definitions are not blocks 2014-04-27 01:54:52 +03:00
4150e00dc4 remove composer dependency 2014-04-26 01:09:28 +03:00
22affa124b travis should be able to run tests in 5.2 2014-04-26 01:06:15 +03:00
5e95242318 improve code consistency 2014-04-26 01:06:14 +03:00
504991a04e Merge pull request #158 from hkdobrev/travis-composer
Run composer install in Travis CI before tests
2014-04-25 00:06:06 +03:00
3d84201d74 Run composer install in Travis CI before tests
Tests are using the Composer autoloader since: cd1c030362

Because of that Composer should have actually dumped the autoloader in the `vendor/` folder,
before the tests are ran.
2014-04-25 00:01:20 +03:00
4f027386b1 "complete" calls should be more consistent 2014-04-24 23:52:42 +03:00
cd1c030362 tests should use autoloader 2014-04-24 22:44:30 +03:00
108 changed files with 256 additions and 199 deletions

View File

@ -7,3 +7,4 @@ php:
- 5.3 - 5.3
- 5.2 - 5.2
- hhvm - hhvm

View File

@ -49,7 +49,7 @@ class Parsedown
$markup = trim($markup, "\n"); $markup = trim($markup, "\n");
# clean up # clean up
$this->references = array(); $this->definitions = array();
return $markup; return $markup;
} }
@ -97,7 +97,6 @@ class Parsedown
'~' => array('FencedCode'), '~' => array('FencedCode'),
); );
# Draft
protected $definitionMarkers = array( protected $definitionMarkers = array(
'[' => array('Reference'), '[' => array('Reference'),
); );
@ -112,30 +111,21 @@ class Parsedown
foreach ($lines as $line) foreach ($lines as $line)
{ {
if (chop($line) === '')
{
if (isset($CurrentBlock))
{
$CurrentBlock['interrupted'] = true;
}
continue;
}
$indent = 0; $indent = 0;
while (true) while (isset($line[$indent]) and $line[$indent] === ' ')
{ {
if (isset($line[$indent])) $indent ++;
{
if ($line[$indent] === ' ')
{
$indent ++;
}
else
{
break;
}
}
else # blank line
{
if (isset($CurrentBlock))
{
$CurrentBlock['interrupted'] = true;
}
continue 2;
}
} }
$text = $indent > 0 ? substr($line, $indent) : $line; $text = $indent > 0 ? substr($line, $indent) : $line;
@ -158,12 +148,33 @@ class Parsedown
} }
else else
{ {
unset($CurrentBlock['incomplete']);
if (method_exists($this, 'complete'.$CurrentBlock['type'])) if (method_exists($this, 'complete'.$CurrentBlock['type']))
{ {
$CurrentBlock = $this->{'complete'.$CurrentBlock['type']}($CurrentBlock); $CurrentBlock = $this->{'complete'.$CurrentBlock['type']}($CurrentBlock);
} }
unset($CurrentBlock['incomplete']);
}
}
# ~
$marker = $text[0];
# Definitions
if (isset($this->definitionMarkers[$marker]))
{
foreach ($this->definitionMarkers[$marker] as $definitionType)
{
$Definition = $this->{'identify'.$definitionType}($Line, $CurrentBlock);
if (isset($Definition))
{
$this->definitions[$definitionType][$Definition['id']] = $Definition['data'];
continue 2;
}
} }
} }
@ -171,8 +182,6 @@ class Parsedown
$blockTypes = $this->unmarkedBlockTypes; $blockTypes = $this->unmarkedBlockTypes;
$marker = $text[0];
if (isset($this->blockMarkers[$marker])) if (isset($this->blockMarkers[$marker]))
{ {
foreach ($this->blockMarkers[$marker] as $blockType) foreach ($this->blockMarkers[$marker] as $blockType)
@ -196,7 +205,7 @@ class Parsedown
if ( ! isset($Block['identified'])) # » if ( ! isset($Block['identified'])) # »
{ {
$elements []= $CurrentBlock['element']; $Elements []= $CurrentBlock['element'];
$Block['identified'] = true; $Block['identified'] = true;
} }
@ -222,7 +231,7 @@ class Parsedown
} }
else else
{ {
$elements []= $CurrentBlock['element']; $Elements []= $CurrentBlock['element'];
$CurrentBlock = array( $CurrentBlock = array(
'type' => 'Paragraph', 'type' => 'Paragraph',
@ -236,13 +245,22 @@ class Parsedown
} }
} }
$elements []= $CurrentBlock['element']; # ~
unset($elements[0]); if (isset($CurrentBlock['incomplete']) and method_exists($this, 'complete'.$CurrentBlock['type']))
{
$CurrentBlock = $this->{'complete'.$CurrentBlock['type']}($CurrentBlock);
}
# ~ # ~
$markup = $this->elements($elements); $Elements []= $CurrentBlock['element'];
unset($Elements[0]);
# ~
$markup = $this->elements($Elements);
# ~ # ~
@ -301,22 +319,19 @@ class Parsedown
{ {
if (preg_match('/^\[(.+?)\]:[ ]*<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches)) if (preg_match('/^\[(.+?)\]:[ ]*<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches))
{ {
$label = strtolower($matches[1]); $Definition = array(
'id' => strtolower($matches[1]),
$this->references[$label] = array( 'data' => array(
'url' => $matches[2], 'url' => $matches[2],
),
); );
if (isset($matches[3])) if (isset($matches[3]))
{ {
$this->references[$label]['title'] = $matches[3]; $Definition['data']['title'] = $matches[3];
} }
$Block = array( return $Definition;
'element' => null,
);
return $Block;
} }
} }
@ -403,7 +418,7 @@ class Parsedown
protected function identifyFencedCode($Line) protected function identifyFencedCode($Line)
{ {
if (preg_match('/^(['.$Line['text'][0].']{3,})[ ]*(\w+)?[ ]*$/', $Line['text'], $matches)) if (preg_match('/^(['.$Line['text'][0].']{3,})[ ]*([\w-]+)?[ ]*$/', $Line['text'], $matches))
{ {
$Element = array( $Element = array(
'name' => 'code', 'name' => 'code',
@ -455,9 +470,18 @@ class Parsedown
return $Block; return $Block;
} }
$string = htmlspecialchars($Line['body'], ENT_NOQUOTES, 'UTF-8'); $Block['element']['text']['text'] .= "\n".$Line['body'];;
$Block['element']['text']['text'] .= "\n".$string;; return $Block;
}
protected function completeFencedCode($Block)
{
$text = $Block['element']['text']['text'];
$text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
$Block['element']['text']['text'] = $text;
return $Block; return $Block;
} }
@ -522,7 +546,7 @@ class Parsedown
if ( ! isset($Block['interrupted'])) if ( ! isset($Block['interrupted']))
{ {
$text = preg_replace('/^[ ]{0,2}/', '', $Line['body']); $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
$Block['li']['text'] []= $text; $Block['li']['text'] []= $text;
@ -533,7 +557,7 @@ class Parsedown
{ {
$Block['li']['text'] []= ''; $Block['li']['text'] []= '';
$text = preg_replace('/^[ ]{0,2}/', '', $Line['body']); $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
$Block['li']['text'] []= $text; $Block['li']['text'] []= $text;
@ -569,6 +593,8 @@ class Parsedown
if (isset($Block['interrupted'])) if (isset($Block['interrupted']))
{ {
$Block['element']['text'] []= ''; $Block['element']['text'] []= '';
unset($Block['interrupted']);
} }
$Block['element']['text'] []= $matches[1]; $Block['element']['text'] []= $matches[1];
@ -747,7 +773,6 @@ class Parsedown
if ($Line['indent'] >= 4) if ($Line['indent'] >= 4)
{ {
$text = substr($Line['body'], 4); $text = substr($Line['body'], 4);
$text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
$Block = array( $Block = array(
'element' => array( 'element' => array(
@ -778,7 +803,6 @@ class Parsedown
$Block['element']['text']['text'] .= "\n"; $Block['element']['text']['text'] .= "\n";
$text = substr($Line['body'], 4); $text = substr($Line['body'], 4);
$text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
$Block['element']['text']['text'] .= $text; $Block['element']['text']['text'] .= $text;
@ -786,6 +810,17 @@ class Parsedown
} }
} }
protected function completeCodeBlock($Block)
{
$text = $Block['element']['text']['text'];
$text = htmlspecialchars($text, ENT_NOQUOTES, 'UTF-8');
$Block['element']['text']['text'] = $text;
return $Block;
}
# #
# ~ # ~
# #
@ -892,36 +927,38 @@ class Parsedown
$Span = $this->$handler($markedExcerpt, $text); $Span = $this->$handler($markedExcerpt, $text);
if (isset($Span)) if ( ! isset($Span))
{ {
# The identified span can be ahead of the marker. continue;
if (isset($Span['position']) and $Span['position'] > $markerPosition)
{
continue;
}
# Spans that start at the position of their marker don't have to set a position.
if ( ! isset($Span['position']))
{
$Span['position'] = $markerPosition;
}
$unmarkedText = substr($text, 0, $Span['position']);
$markup .= $this->readPlainText($unmarkedText);
$markup .= isset($Span['element']) ? $this->element($Span['element']) : $Span['markup'];
$text = substr($text, $Span['position'] + $Span['extent']);
$remainder = $text;
$markerPosition = 0;
continue 2;
} }
# The identified span can be ahead of the marker.
if (isset($Span['position']) and $Span['position'] > $markerPosition)
{
continue;
}
# Spans that start at the position of their marker don't have to set a position.
if ( ! isset($Span['position']))
{
$Span['position'] = $markerPosition;
}
$plainText = substr($text, 0, $Span['position']);
$markup .= $this->readPlainText($plainText);
$markup .= isset($Span['element']) ? $this->element($Span['element']) : $Span['markup'];
$text = substr($text, $Span['position'] + $Span['extent']);
$remainder = $text;
$markerPosition = 0;
continue 2;
} }
$remainder = substr($markedExcerpt, 1); $remainder = substr($markedExcerpt, 1);
@ -1034,7 +1071,7 @@ class Parsedown
protected function identifyEmailTag($excerpt) protected function identifyEmailTag($excerpt)
{ {
if (strpos($excerpt, '>') !== false and preg_match('/<(\S+?@\S+?)>/', $excerpt, $matches)) if (strpos($excerpt, '>') !== false and preg_match('/^<(\S+?@\S+?)>/', $excerpt, $matches))
{ {
return array( return array(
'extent' => strlen($matches[0]), 'extent' => strlen($matches[0]),
@ -1095,9 +1132,9 @@ class Parsedown
{ {
$Link['label'] = strtolower($matches[1]); $Link['label'] = strtolower($matches[1]);
if (isset($this->references[$Link['label']])) if (isset($this->definitions['Reference'][$Link['label']]))
{ {
$Link += $this->references[$Link['label']]; $Link += $this->definitions['Reference'][$Link['label']];
$extent += strlen($matches[0]); $extent += strlen($matches[0]);
} }
@ -1106,9 +1143,9 @@ class Parsedown
return; return;
} }
} }
elseif ($this->references and isset($this->references[$Link['label']])) elseif (isset($this->definitions['Reference'][$Link['label']]))
{ {
$Link += $this->references[$Link['label']]; $Link += $this->definitions['Reference'][$Link['label']];
if (preg_match('/^[ ]*\[\]/', $substring, $matches)) if (preg_match('/^[ ]*\[\]/', $substring, $matches))
{ {
@ -1276,7 +1313,7 @@ class Parsedown
# Fields # Fields
# #
protected $references = array(); # » Definitions['reference'] protected $definitions;
# #
# Read-only # Read-only
@ -1298,12 +1335,12 @@ class Parsedown
protected $textLevelElements = array( protected $textLevelElements = array(
'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont', 'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont',
'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing', 'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing',
'i', 'rp', 'sub', 'code', 'strike', 'marquee', 'i', 'rp', 'del', 'code', 'strike', 'marquee',
'q', 'rt', 'sup', 'font', 'strong', 'q', 'rt', 'ins', 'font', 'strong',
's', 'tt', 'var', 'mark', 's', 'tt', 'sub', 'mark',
'u', 'xm', 'wbr', 'nobr', 'u', 'xm', 'sup', 'nobr',
'ruby', 'var', 'ruby',
'span', 'wbr', 'span',
'time', 'time',
); );
} }

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true"> <phpunit bootstrap="test/bootstrap.php" colors="true">
<testsuites> <testsuites>
<testsuite> <testsuite>
<file>tests/Test.php</file> <file>test/Test.php</file>
</testsuite> </testsuite>
</testsuites> </testsuites>
</phpunit> </phpunit>

View File

@ -1,7 +1,5 @@
<?php <?php
include 'Parsedown.php';
class Test extends PHPUnit_Framework_TestCase class Test extends PHPUnit_Framework_TestCase
{ {
public function __construct($name = null, array $data = array(), $dataName = '') public function __construct($name = null, array $data = array(), $dataName = '')

3
test/bootstrap.php Normal file
View File

@ -0,0 +1,3 @@
<?php
include 'Parsedown.php';

View File

@ -1,8 +1,8 @@
<h1>h1</h1> <h1>h1</h1>
<h2>h2</h2> <h2>h2</h2>
<h3>h3</h3> <h3>h3</h3>
<h4>h4</h4> <h4>h4</h4>
<h5>h5</h5> <h5>h5</h5>
<h6>h6</h6> <h6>h6</h6>
<h1>closed h1</h1> <h1>closed h1</h1>
<p>#</p> <p>#</p>

View File

@ -1,15 +1,15 @@
# h1 # h1
## h2 ## h2
### h3 ### h3
#### h4 #### h4
##### h5 ##### h5
###### h6 ###### h6
# closed h1 # # closed h1 #
# #

View File

@ -1,8 +1,8 @@
<pre><code>&lt;?php <pre><code>&lt;?php
$message = 'Hello World!'; $message = 'Hello World!';
echo $message;</code></pre> echo $message;</code></pre>
<hr /> <hr />
<pre><code>&gt; not a quote <pre><code>&gt; not a quote
- not a list item - not a list item
[not a reference]: http://foo.com</code></pre> [not a reference]: http://foo.com</code></pre>

View File

@ -1,10 +1,10 @@
<?php <?php
$message = 'Hello World!'; $message = 'Hello World!';
echo $message; echo $message;
--- ---
> not a quote > not a quote
- not a list item - not a list item
[not a reference]: http://foo.com [not a reference]: http://foo.com

View File

@ -1,6 +1,6 @@
- li - li
- li
- li - li
- li
- li
- li - li
- li
- li - li

View File

@ -1,8 +1,8 @@
<p><em>underscore</em>, <em>asterisk</em>, <em>one two</em>, <em>three four</em>, <em>a</em>, <em>b</em></p> <p><em>underscore</em>, <em>asterisk</em>, <em>one two</em>, <em>three four</em>, <em>a</em>, <em>b</em></p>
<p><strong>strong</strong> and <em>em</em> and <strong>strong</strong> and <em>em</em></p> <p><strong>strong</strong> and <em>em</em> and <strong>strong</strong> and <em>em</em></p>
<p><em>line <p><em>line
line line
line</em></p> line</em></p>
<p>this_is_not_an_emphasis</p> <p>this_is_not_an_emphasis</p>
<p>an empty emphasis __ ** is not an emphasis</p> <p>an empty emphasis __ ** is not an emphasis</p>
<p>*mixed *<em>double and</em> single asterisk** spans</p> <p>*mixed *<em>double and</em> single asterisk** spans</p>

View File

@ -1,13 +1,13 @@
_underscore_, *asterisk*, _one two_, *three four*, _a_, *b* _underscore_, *asterisk*, _one two_, *three four*, _a_, *b*
**strong** and *em* and **strong** and *em* **strong** and *em* and **strong** and *em*
_line _line
line line
line_ line_
this_is_not_an_emphasis this_is_not_an_emphasis
an empty emphasis __ ** is not an emphasis an empty emphasis __ ** is not an emphasis
*mixed **double and* single asterisk** spans *mixed **double and* single asterisk** spans

View File

@ -1,5 +1,5 @@
<hr /> <hr />
<hr /> <hr />
<hr /> <hr />
<hr /> <hr />
<hr /> <hr />

View File

@ -1,9 +1,9 @@
--- ---
- - - - - -
- - - - - -
*** ***
___ ___

View File

@ -1,4 +1,6 @@
<blockquote> <blockquote>
<p>quote <p>quote
the rest of it</p> the rest of it</p>
<p>another paragraph
the rest of it</p>
</blockquote> </blockquote>

View File

@ -0,0 +1,5 @@
> quote
the rest of it
> another paragraph
the rest of it

View File

@ -1,2 +1,2 @@
<p>line<br /> <p>line<br />
line</p> line</p>

View File

@ -1,2 +1,2 @@
line line
line line

View File

@ -0,0 +1,9 @@
<ul>
<li>
<p>li</p>
<ul>
<li>li</li>
<li>li</li>
</ul>
</li>
</ul>

View File

@ -0,0 +1,4 @@
- li
- li
- li

View File

@ -1,5 +1,5 @@
<h1>h1</h1> <h1>h1</h1>
<h2>h2</h2> <h2>h2</h2>
<h2>single character</h2> <h2>single character</h2>
<p>not a header</p> <p>not a header</p>
<hr /> <hr />

View File

@ -1,12 +1,12 @@
h1 h1
== ==
h2 h2
-- --
single character single character
- -
not a header not a header
------------ ------------

View File

@ -1,6 +1,6 @@
<p>AT&amp;T has an ampersand in their name</p> <p>AT&amp;T has an ampersand in their name</p>
<p>this &amp; that</p> <p>this &amp; that</p>
<p>4 &lt; 5 and 6 > 5</p> <p>4 &lt; 5 and 6 > 5</p>
<p><a href="http://example.com/autolink?a=1&amp;b=2">http://example.com/autolink?a=1&amp;b=2</a></p> <p><a href="http://example.com/autolink?a=1&amp;b=2">http://example.com/autolink?a=1&amp;b=2</a></p>
<p><a href="/script?a=1&amp;b=2">inline link</a></p> <p><a href="/script?a=1&amp;b=2">inline link</a></p>
<p><a href="http://example.com/?a=1&amp;b=2">reference link</a></p> <p><a href="http://example.com/?a=1&amp;b=2">reference link</a></p>

View File

@ -1,13 +1,13 @@
AT&T has an ampersand in their name AT&T has an ampersand in their name
this & that this & that
4 < 5 and 6 > 5 4 < 5 and 6 > 5
<http://example.com/autolink?a=1&b=2> <http://example.com/autolink?a=1&b=2>
[inline link](/script?a=1&b=2) [inline link](/script?a=1&b=2)
[reference link][1] [reference link][1]
[1]: http://example.com/?a=1&b=2 [1]: http://example.com/?a=1&b=2

Some files were not shown because too many files have changed in this diff Show More