mirror of
https://github.com/erusev/parsedown.git
synced 2023-08-10 21:13:06 +03:00
Compare commits
55 Commits
Author | SHA1 | Date | |
---|---|---|---|
3225c66863 | |||
d6dc5ba25b | |||
f5451a9eff | |||
849a89b121 | |||
28064a63b3 | |||
800aac5b56 | |||
b15d40e8a3 | |||
ddc5b7e2dd | |||
5a563008aa | |||
b6f795962f | |||
cdb2646063 | |||
e3b8026e39 | |||
d96f668c42 | |||
96bf75bd91 | |||
67b51794d8 | |||
a9d6232705 | |||
b91629ad94 | |||
24d300ea5d | |||
d54712b989 | |||
6ef043ba7d | |||
fe27b70bdb | |||
18d3dbf4f6 | |||
4758f58f73 | |||
5fa3eb1b2f | |||
38300323a6 | |||
96609329b9 | |||
e497acb6dc | |||
30e436ec7d | |||
3972f18881 | |||
4fb12be60a | |||
f8b07611d3 | |||
21d7f75f5b | |||
a4fb0651d5 | |||
50a58eab16 | |||
1f347e17eb | |||
df3db71698 | |||
a37f5ff31e | |||
8e6f4cf7b8 | |||
ee9a1e92c0 | |||
689ef24cc5 | |||
4403fe4d96 | |||
400c8f7d46 | |||
379cbf34b3 | |||
b6c8cac512 | |||
0e9202689e | |||
7249d02cff | |||
ecf86b073e | |||
b12973415f | |||
6d113f47fb | |||
d4d3612710 | |||
2e314ad474 | |||
e475602e2f | |||
f43f54b877 | |||
d733acc94e | |||
6a0695deb9 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
.DS_Store
|
||||
.idea
|
||||
nbproject
|
@ -4,3 +4,4 @@ php:
|
||||
- 5.5
|
||||
- 5.4
|
||||
- 5.3
|
||||
- 5.2
|
575
Parsedown.php
575
Parsedown.php
@ -46,17 +46,17 @@ class Parsedown
|
||||
|
||||
function parse($text)
|
||||
{
|
||||
# Removes UTF-8 BOM and marker characters.
|
||||
# removes UTF-8 BOM and marker characters
|
||||
$text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
|
||||
|
||||
# Removes \r characters.
|
||||
# removes \r characters
|
||||
$text = str_replace("\r\n", "\n", $text);
|
||||
$text = str_replace("\r", "\n", $text);
|
||||
|
||||
# Replaces tabs with spaces.
|
||||
# replaces tabs with spaces
|
||||
$text = str_replace("\t", ' ', $text);
|
||||
|
||||
# Encodes escape sequences.
|
||||
# encodes escape sequences
|
||||
|
||||
if (strpos($text, '\\') !== FALSE)
|
||||
{
|
||||
@ -66,7 +66,7 @@ class Parsedown
|
||||
{
|
||||
if (strpos($text, $escape_sequence) !== FALSE)
|
||||
{
|
||||
$code = "\x1A".'\\'.$index;
|
||||
$code = "\x1A".'\\'.$index.';';
|
||||
|
||||
$text = str_replace($escape_sequence, $code, $text);
|
||||
|
||||
@ -75,18 +75,6 @@ class Parsedown
|
||||
}
|
||||
}
|
||||
|
||||
# Extracts link references.
|
||||
|
||||
if (preg_match_all('/^[ ]{0,3}\[(.+)\][ ]?:[ ]*\n?[ ]*(.+)$/m', $text, $matches, PREG_SET_ORDER))
|
||||
{
|
||||
foreach ($matches as $matches)
|
||||
{
|
||||
$this->reference_map[strtolower($matches[1])] = $matches[2];
|
||||
|
||||
$text = str_replace($matches[0], '', $text);
|
||||
}
|
||||
}
|
||||
|
||||
# ~
|
||||
|
||||
$text = preg_replace('/\n\s*\n/', "\n\n", $text);
|
||||
@ -96,7 +84,7 @@ class Parsedown
|
||||
|
||||
$text = $this->parse_block_elements($lines);
|
||||
|
||||
# Decodes escape sequences (leaves out backslashes).
|
||||
# decodes escape sequences
|
||||
|
||||
foreach ($this->escape_sequence_map as $code => $escape_sequence)
|
||||
{
|
||||
@ -122,32 +110,84 @@ class Parsedown
|
||||
|
||||
foreach ($lines as $line)
|
||||
{
|
||||
# Empty
|
||||
#
|
||||
# fenced elements
|
||||
|
||||
switch ($element['type'])
|
||||
{
|
||||
case 'fenced_code_block':
|
||||
|
||||
if ( ! isset($element['closed']))
|
||||
{
|
||||
if (preg_match('/^[ ]*'.$element['fence'][0].'{3,}[ ]*$/', $line))
|
||||
{
|
||||
$element['closed'] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$element['text'] !== '' and $element['text'] .= "\n";
|
||||
|
||||
$element['text'] .= $line;
|
||||
}
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'markup':
|
||||
|
||||
if ( ! isset($element['closed']))
|
||||
{
|
||||
if (preg_match('{<'.$element['subtype'].'>$}', $line)) # opening tag
|
||||
{
|
||||
$element['depth']++;
|
||||
}
|
||||
|
||||
if (preg_match('{</'.$element['subtype'].'>$}', $line)) # closing tag
|
||||
{
|
||||
$element['depth'] > 0
|
||||
? $element['depth']--
|
||||
: $element['closed'] = true;
|
||||
}
|
||||
|
||||
$element['text'] .= "\n".$line;
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
# *
|
||||
|
||||
if ($line === '')
|
||||
{
|
||||
$element['interrupted'] = true;
|
||||
|
||||
$element['type'] === 'code' and $element['text'] .= "\n";
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
# Lazy Blockquote
|
||||
#
|
||||
# composite elements
|
||||
|
||||
if ($element['type'] === 'blockquote' and ! isset($element['interrupted']))
|
||||
switch ($element['type'])
|
||||
{
|
||||
case 'blockquote':
|
||||
|
||||
if ( ! isset($element['interrupted']))
|
||||
{
|
||||
$line = preg_replace('/^[ ]*>[ ]?/', '', $line);
|
||||
|
||||
$element['lines'] []= $line;
|
||||
|
||||
continue;
|
||||
continue 2;
|
||||
}
|
||||
|
||||
# Lazy List Item
|
||||
break;
|
||||
|
||||
case 'li':
|
||||
|
||||
if ($element['type'] === 'li')
|
||||
{
|
||||
if (preg_match('/^([ ]{0,3})(\d+[.]|[*+-])[ ](.*)/', $line, $matches))
|
||||
{
|
||||
if ($element['indentation'] !== $matches[1])
|
||||
@ -170,7 +210,7 @@ class Parsedown
|
||||
);
|
||||
}
|
||||
|
||||
continue;
|
||||
continue 2;
|
||||
}
|
||||
|
||||
if (isset($element['interrupted']))
|
||||
@ -179,78 +219,56 @@ class Parsedown
|
||||
{
|
||||
$element['lines'] []= '';
|
||||
|
||||
$line = preg_replace('/^[ ]{0,4}/', '', $line);;
|
||||
$line = preg_replace('/^[ ]{0,4}/', '', $line);
|
||||
|
||||
$element['lines'] []= $line;
|
||||
|
||||
continue;
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$line = preg_replace('/^[ ]{0,4}/', '', $line);;
|
||||
$line = preg_replace('/^[ ]{0,4}/', '', $line);
|
||||
|
||||
$element['lines'] []= $line;
|
||||
|
||||
continue;
|
||||
}
|
||||
continue 2;
|
||||
}
|
||||
|
||||
# Quick Paragraph
|
||||
break;
|
||||
}
|
||||
|
||||
if ($line[0] >= 'A' and $line['0'] !== '_')
|
||||
#
|
||||
# indentation sensitive types
|
||||
|
||||
$deindented_line = $line;
|
||||
|
||||
switch ($line[0])
|
||||
{
|
||||
goto paragraph; # trust me
|
||||
}
|
||||
case ' ':
|
||||
|
||||
# Setext Header (---)
|
||||
# ~
|
||||
|
||||
if ($element['type'] === 'p' and ! isset($element['interrupted']) and preg_match('/^[-]+[ ]*$/', $line))
|
||||
$deindented_line = ltrim($line);
|
||||
|
||||
if ($deindented_line === '')
|
||||
{
|
||||
$element['type'] = 'h.';
|
||||
$element['level'] = 2;
|
||||
|
||||
continue;
|
||||
continue 2;
|
||||
}
|
||||
|
||||
# Horizontal Rule
|
||||
|
||||
if (preg_match('/^[ ]{0,3}([-*_])([ ]{0,2}\1){2,}[ ]*$/', $line))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'hr',
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
# List Item
|
||||
|
||||
if (preg_match('/^([ ]{0,3})(\d+[.]|[*+-])[ ](.*)/', $line, $matches))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'li',
|
||||
'ordered' => isset($matches[2][1]),
|
||||
'indentation' => $matches[1],
|
||||
'last' => true,
|
||||
'lines' => array(
|
||||
preg_replace('/^[ ]{0,4}/', '', $matches[3]),
|
||||
),
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
# Code
|
||||
# code block
|
||||
|
||||
if (preg_match('/^[ ]{4}(.*)/', $line, $matches))
|
||||
{
|
||||
if ($element['type'] === 'code')
|
||||
if ($element['type'] === 'code_block')
|
||||
{
|
||||
if (isset($element['interrupted']))
|
||||
{
|
||||
$element['text'] .= "\n";
|
||||
|
||||
unset ($element['interrupted']);
|
||||
}
|
||||
|
||||
$element['text'] .= "\n".$matches[1];
|
||||
}
|
||||
else
|
||||
@ -258,17 +276,21 @@ class Parsedown
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'code',
|
||||
'type' => 'code_block',
|
||||
'text' => $matches[1],
|
||||
);
|
||||
}
|
||||
|
||||
continue;
|
||||
continue 2;
|
||||
}
|
||||
|
||||
# Atx Header (#)
|
||||
break;
|
||||
|
||||
if ($line[0] === '#' and preg_match('/^(#{1,6})[ ]*(.+?)[ ]*#*$/', $line, $matches))
|
||||
case '#':
|
||||
|
||||
# atx heading (#)
|
||||
|
||||
if (preg_match('/^(#{1,6})[ ]*(.+?)[ ]*#*$/', $line, $matches))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
@ -280,25 +302,86 @@ class Parsedown
|
||||
'level' => $level,
|
||||
);
|
||||
|
||||
continue;
|
||||
continue 2;
|
||||
}
|
||||
|
||||
# Blockquote
|
||||
break;
|
||||
|
||||
if (preg_match('/^[ ]*>[ ]?(.*)/', $line, $matches))
|
||||
{
|
||||
if ($element['type'] === 'blockquote')
|
||||
{
|
||||
if (isset($element['interrupted']))
|
||||
{
|
||||
$element['lines'] []= '';
|
||||
case '-':
|
||||
|
||||
unset($element['interrupted']);
|
||||
# setext heading (---)
|
||||
|
||||
if ($line[0] === '-' and $element['type'] === 'p' and ! isset($element['interrupted']) and preg_match('/^[-]+[ ]*$/', $line))
|
||||
{
|
||||
$element['type'] = 'h.';
|
||||
$element['level'] = 2;
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
$element['lines'] []= $matches[1];
|
||||
break;
|
||||
|
||||
case '=':
|
||||
|
||||
# setext heading (===)
|
||||
|
||||
if ($line[0] === '=' and $element['type'] === 'p' and ! isset($element['interrupted']) and preg_match('/^[=]+[ ]*$/', $line))
|
||||
{
|
||||
$element['type'] = 'h.';
|
||||
$element['level'] = 1;
|
||||
|
||||
continue 2;
|
||||
}
|
||||
else
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#
|
||||
# indentation insensitive types
|
||||
|
||||
switch ($deindented_line[0])
|
||||
{
|
||||
case '<':
|
||||
|
||||
# self-closing tag
|
||||
|
||||
if (preg_match('{^<.+?/>$}', $deindented_line))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => '',
|
||||
'text' => $deindented_line,
|
||||
);
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
# opening tag
|
||||
|
||||
if (preg_match('{^<(\w+)(?:[ ].*?)?>}', $deindented_line, $matches))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'markup',
|
||||
'subtype' => strtolower($matches[1]),
|
||||
'text' => $deindented_line,
|
||||
'depth' => 0,
|
||||
);
|
||||
|
||||
preg_match('{</'.$matches[1].'>\s*$}', $deindented_line) and $element['closed'] = true;
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '>':
|
||||
|
||||
# quote
|
||||
|
||||
if (preg_match('/^>[ ]?(.*)/', $deindented_line, $matches))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
@ -308,24 +391,107 @@ class Parsedown
|
||||
$matches[1],
|
||||
),
|
||||
);
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
# Setext Header (===)
|
||||
case '[':
|
||||
|
||||
if ($element['type'] === 'p' and ! isset($element['interrupted']) and preg_match('/^[=]+[ ]*$/', $line))
|
||||
# reference
|
||||
|
||||
if (preg_match('/^\[(.+?)\]:[ ]*([^ ]+)/', $deindented_line, $matches))
|
||||
{
|
||||
$element['type'] = 'h.';
|
||||
$element['level'] = 1;
|
||||
$label = strtolower($matches[1]);
|
||||
|
||||
$this->reference_map[$label] = trim($matches[2], '<>');;
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '`':
|
||||
case '~':
|
||||
|
||||
# fenced code block
|
||||
|
||||
if (preg_match('/^([`]{3,}|[~]{3,})[ ]*(\S+)?[ ]*$/', $deindented_line, $matches))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'fenced_code_block',
|
||||
'text' => '',
|
||||
'fence' => $matches[1],
|
||||
);
|
||||
|
||||
isset($matches[2]) and $element['language'] = $matches[2];
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '*':
|
||||
case '+':
|
||||
case '-':
|
||||
case '_':
|
||||
|
||||
# hr
|
||||
|
||||
if (preg_match('/^([-*_])([ ]{0,2}\1){2,}[ ]*$/', $deindented_line))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'hr',
|
||||
);
|
||||
|
||||
continue 2;
|
||||
}
|
||||
|
||||
# li
|
||||
|
||||
if (preg_match('/^([ ]*)[*+-][ ](.*)/', $line, $matches))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'li',
|
||||
'ordered' => false,
|
||||
'indentation' => $matches[1],
|
||||
'last' => true,
|
||||
'lines' => array(
|
||||
preg_replace('/^[ ]{0,4}/', '', $matches[2]),
|
||||
),
|
||||
);
|
||||
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
# li
|
||||
|
||||
if ($deindented_line[0] <= '9' and $deindented_line >= '0' and preg_match('/^([ ]*)\d+[.][ ](.*)/', $line, $matches))
|
||||
{
|
||||
$elements []= $element;
|
||||
|
||||
$element = array(
|
||||
'type' => 'li',
|
||||
'ordered' => true,
|
||||
'indentation' => $matches[1],
|
||||
'last' => true,
|
||||
'lines' => array(
|
||||
preg_replace('/^[ ]{0,4}/', '', $matches[2]),
|
||||
),
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
# ~
|
||||
|
||||
paragraph:
|
||||
# paragraph
|
||||
|
||||
if ($element['type'] === 'p')
|
||||
{
|
||||
@ -355,7 +521,7 @@ class Parsedown
|
||||
|
||||
$elements []= $element;
|
||||
|
||||
array_shift($elements);
|
||||
unset($elements[0]);
|
||||
|
||||
#
|
||||
# ~
|
||||
@ -363,10 +529,67 @@ class Parsedown
|
||||
|
||||
$markup = '';
|
||||
|
||||
foreach ($elements as $index => $element)
|
||||
foreach ($elements as $element)
|
||||
{
|
||||
switch ($element['type'])
|
||||
{
|
||||
case 'p':
|
||||
|
||||
$text = $this->parse_span_elements($element['text']);
|
||||
|
||||
$text = preg_replace('/[ ]{2}\n/', '<br />'."\n", $text);
|
||||
|
||||
if ($context === 'li' and $markup === '')
|
||||
{
|
||||
if (isset($element['interrupted']))
|
||||
{
|
||||
$markup .= "\n".'<p>'.$text.'</p>'."\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$markup .= $text;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$markup .= '<p>'.$text.'</p>'."\n";
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'blockquote':
|
||||
|
||||
$text = $this->parse_block_elements($element['lines']);
|
||||
|
||||
$markup .= '<blockquote>'."\n".$text.'</blockquote>'."\n";
|
||||
|
||||
break;
|
||||
|
||||
case 'code_block':
|
||||
case 'fenced_code_block':
|
||||
|
||||
$text = htmlspecialchars($element['text'], ENT_NOQUOTES, 'UTF-8');
|
||||
|
||||
strpos($text, "\x1A\\") !== FALSE and $text = strtr($text, $this->escape_sequence_map);
|
||||
|
||||
$markup .= '<pre><code>'.$text.'</code></pre>'."\n";
|
||||
|
||||
break;
|
||||
|
||||
case 'h.':
|
||||
|
||||
$text = $this->parse_span_elements($element['text']);
|
||||
|
||||
$markup .= '<h'.$element['level'].'>'.$text.'</h'.$element['level'].'>'."\n";
|
||||
|
||||
break;
|
||||
|
||||
case 'hr':
|
||||
|
||||
$markup .= '<hr />'."\n";
|
||||
|
||||
break;
|
||||
|
||||
case 'li':
|
||||
|
||||
if (isset($element['ordered'])) # first
|
||||
@ -389,95 +612,41 @@ class Parsedown
|
||||
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
default:
|
||||
|
||||
$text = $this->parse_inline_elements($element['text']);
|
||||
|
||||
$text = preg_replace('/[ ]{2}\n/', '<br />'."\n", $text);
|
||||
|
||||
if ($context === 'li' and $index === 0)
|
||||
{
|
||||
if (isset($element['interrupted']))
|
||||
{
|
||||
$markup .= "\n".'<p>'.$text.'</p>'."\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$markup .= $text;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$markup .= '<p>'.$text.'</p>'."\n";
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'code':
|
||||
|
||||
$text = rtrim($element['text'], "\n");
|
||||
|
||||
$text = htmlentities($text, ENT_NOQUOTES);
|
||||
|
||||
strpos($text, "\x1A\\") !== FALSE and $text = strtr($text, $this->escape_sequence_map);
|
||||
|
||||
$markup .= '<pre><code>'.$text.'</code></pre>'."\n";
|
||||
|
||||
break;
|
||||
|
||||
case 'blockquote':
|
||||
|
||||
$text = $this->parse_block_elements($element['lines']);
|
||||
|
||||
$markup .= '<blockquote>'."\n".$text.'</blockquote>'."\n";
|
||||
|
||||
break;
|
||||
|
||||
case 'h.':
|
||||
|
||||
$text = $this->parse_inline_elements($element['text']);
|
||||
|
||||
$markup .= '<h'.$element['level'].'>'.$text.'</h'.$element['level'].'>'."\n";
|
||||
|
||||
break;
|
||||
|
||||
case 'hr':
|
||||
|
||||
$markup .= '<hr />'."\n";
|
||||
|
||||
break;
|
||||
$markup .= $element['text']."\n";
|
||||
}
|
||||
}
|
||||
|
||||
return $markup;
|
||||
}
|
||||
|
||||
private function parse_inline_elements($text)
|
||||
private function parse_span_elements($text)
|
||||
{
|
||||
$map = array();
|
||||
|
||||
$index = 0;
|
||||
|
||||
# Code Span
|
||||
# code span
|
||||
|
||||
if (strpos($text, '`') !== FALSE and preg_match_all('/`(.+?)`/', $text, $matches, PREG_SET_ORDER))
|
||||
{
|
||||
foreach ($matches as $matches)
|
||||
{
|
||||
$element_text = $matches[1];
|
||||
$element_text = htmlentities($element_text, ENT_NOQUOTES);
|
||||
$element_text = htmlspecialchars($element_text, ENT_NOQUOTES, 'UTF-8');
|
||||
|
||||
# Decodes escape sequences.
|
||||
# decodes escape sequences
|
||||
|
||||
$this->escape_sequence_map
|
||||
and strpos($element_text, "\x1A") !== FALSE
|
||||
and $element_text = strtr($element_text, $this->escape_sequence_map);
|
||||
|
||||
# Composes element.
|
||||
# composes element
|
||||
|
||||
$element = '<code>'.$element_text.'</code>';
|
||||
|
||||
# Encodes element.
|
||||
# encodes element
|
||||
|
||||
$code = "\x1A".'$'.$index;
|
||||
|
||||
@ -489,25 +658,27 @@ class Parsedown
|
||||
}
|
||||
}
|
||||
|
||||
# Inline Link / Image
|
||||
# inline link or image
|
||||
|
||||
if (strpos($text, '](') !== FALSE and preg_match_all('/(!?)(\[((?:[^][]+|(?2))*)\])\((.*?)\)/', $text, $matches, PREG_SET_ORDER)) # inline
|
||||
if (strpos($text, '](') !== FALSE and preg_match_all('/(!?)(\[((?:[^\[\]]|(?2))*)\])\((.*?)\)/', $text, $matches, PREG_SET_ORDER)) # inline
|
||||
{
|
||||
foreach ($matches as $matches)
|
||||
{
|
||||
$url = $matches[4];
|
||||
|
||||
strpos($url, '&') !== FALSE and $url = preg_replace('/&(?!#?\w+;)/', '&', $url);
|
||||
|
||||
if ($matches[1]) # image
|
||||
{
|
||||
$element = '<img alt="'.$matches[3].'" src="'.$matches[4].'">';
|
||||
$element = '<img alt="'.$matches[3].'" src="'.$url.'">';
|
||||
}
|
||||
else
|
||||
{
|
||||
$element_text = $this->parse_inline_elements($matches[3]);
|
||||
$element_text = $this->parse_span_elements($matches[3]);
|
||||
|
||||
$element = '<a href="'.$matches[4].'">'.$element_text.'</a>';
|
||||
$element = '<a href="'.$url.'">'.$element_text.'</a>';
|
||||
}
|
||||
|
||||
$element_text = $this->parse_inline_elements($matches[1]);
|
||||
|
||||
# ~
|
||||
|
||||
$code = "\x1A".'$'.$index;
|
||||
@ -520,21 +691,23 @@ class Parsedown
|
||||
}
|
||||
}
|
||||
|
||||
# Reference(d) Link / Image
|
||||
# reference link or image
|
||||
|
||||
if ($this->reference_map and strpos($text, '[') !== FALSE and preg_match_all('/(!?)\[(.+?)\](?:\n?[ ]?\[(.*?)\])?/ms', $text, $matches, PREG_SET_ORDER))
|
||||
{
|
||||
foreach ($matches as $matches)
|
||||
{
|
||||
$link_difinition = isset($matches[3]) && $matches[3]
|
||||
$link_definition = isset($matches[3]) && $matches[3]
|
||||
? $matches[3]
|
||||
: $matches[2]; # implicit
|
||||
|
||||
$link_difinition = strtolower($link_difinition);
|
||||
$link_definition = strtolower($link_definition);
|
||||
|
||||
if (isset($this->reference_map[$link_difinition]))
|
||||
if (isset($this->reference_map[$link_definition]))
|
||||
{
|
||||
$url = $this->reference_map[$link_difinition];
|
||||
$url = $this->reference_map[$link_definition];
|
||||
|
||||
strpos($url, '&') !== FALSE and $url = preg_replace('/&(?!#?\w+;)/', '&', $url);
|
||||
|
||||
if ($matches[1]) # image
|
||||
{
|
||||
@ -542,7 +715,7 @@ class Parsedown
|
||||
}
|
||||
else # anchor
|
||||
{
|
||||
$element_text = $this->parse_inline_elements($matches[2]);
|
||||
$element_text = $this->parse_span_elements($matches[2]);
|
||||
|
||||
$element = '<a href="'.$url.'">'.$element_text.'</a>';
|
||||
}
|
||||
@ -560,13 +733,22 @@ class Parsedown
|
||||
}
|
||||
}
|
||||
|
||||
if (strpos($text, '<') !== FALSE and preg_match_all('/<((https?|ftp|dict):[^\^\s]+?)>/i', $text, $matches, PREG_SET_ORDER))
|
||||
if (strpos($text, '://') !== FALSE)
|
||||
{
|
||||
switch (TRUE)
|
||||
{
|
||||
case preg_match_all('{<(https?:[/]{2}[^\s]+)>}i', $text, $matches, PREG_SET_ORDER):
|
||||
case preg_match_all('{\b(https?:[/]{2}[^\s]+)\b}i', $text, $matches, PREG_SET_ORDER):
|
||||
|
||||
foreach ($matches as $matches)
|
||||
{
|
||||
$url = $matches[1];
|
||||
|
||||
strpos($url, '&') !== FALSE and $url = preg_replace('/&(?!#?\w+;)/', '&', $url);
|
||||
|
||||
$element = '<a href=":href">:text</a>';
|
||||
$element = str_replace(':text', $matches[1], $element);
|
||||
$element = str_replace(':href', $matches[1], $element);
|
||||
$element = str_replace(':text', $url, $element);
|
||||
$element = str_replace(':href', $url, $element);
|
||||
|
||||
# ~
|
||||
|
||||
@ -578,18 +760,38 @@ class Parsedown
|
||||
|
||||
$index ++;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
# ~
|
||||
|
||||
strpos($text, '&') !== FALSE and $text = preg_replace('/&(?!#?\w+;)/', '&', $text);
|
||||
strpos($text, '<') !== FALSE and $text = preg_replace('/<(?!\/?\w.*?>)/', '<', $text);
|
||||
|
||||
# ~
|
||||
|
||||
if (strpos($text, '~~') !== FALSE)
|
||||
{
|
||||
$text = preg_replace('/~~(?=\S)(.+?)(?<=\S)~~/s', '<del>$1</del>', $text);
|
||||
}
|
||||
|
||||
if (strpos($text, '_') !== FALSE)
|
||||
{
|
||||
$text = preg_replace('/__(?=\S)(.+?)(?<=\S)__/', '<strong>$1</strong>', $text);
|
||||
$text = preg_replace('/_(?=\S)(.+?)(?<=\S)_/', '<em>$1</em>', $text);
|
||||
$text = preg_replace('/__(?=\S)([^_]+?)(?<=\S)__/s', '<strong>$1</strong>', $text, -1, $count);
|
||||
$count or $text = preg_replace('/__(?=\S)(.+?)(?<=\S)__(?!_)/s', '<strong>$1</strong>', $text);
|
||||
|
||||
$text = preg_replace('/\b_(?=\S)(.+?)(?<=\S)_\b/s', '<em>$1</em>', $text);
|
||||
}
|
||||
|
||||
if (strpos($text, '*') !== FALSE)
|
||||
{
|
||||
$text = preg_replace('/\*\*(?=\S)(.+?)(?<=\S)\*\*/', '<strong>$1</strong>', $text);
|
||||
$text = preg_replace('/\*(?=\S)(.+?)(?<=\S)\*/', '<em>$1</em>', $text);
|
||||
$text = preg_replace('/\*\*(?=\S)([^*]+?)(?<=\S)\*\*/s', '<strong>$1</strong>', $text, -1, $count);
|
||||
$count or $text = preg_replace('/\*\*(?=\S)(.+?)(?<=\S)\*\*(?!\*)/s', '<strong>$1</strong>', $text);
|
||||
|
||||
$text = preg_replace('/\*(?=\S)([^*]+?)(?<=\S)\*/s', '<em>$1</em>', $text, -1, $count);
|
||||
$count or $text = preg_replace('/\*(?=\S)(.+?)(?<=\S)\*(?!\*)/s', '<em>$1</em>', $text);
|
||||
}
|
||||
|
||||
$text = strtr($text, $map);
|
||||
@ -597,4 +799,3 @@ class Parsedown
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
## Parsedown PHP
|
||||
## Parsedown
|
||||
|
||||
Parsedown is a parser for Markdown. It parses Markdown text the way people do. First, it divides texts into blocks. Then it looks at how these blocks start and how they relate to each other. Finally, it looks for special characters to identify inline elements. As a result, Parsedown is (super) fast, consistent and clean.
|
||||
Fast and consistent [Markdown][1] parser for PHP.
|
||||
|
||||
[Explorer (demo)](http://parsedown.org/explorer/)
|
||||
[Tests](http://parsedown.org/tests/)
|
||||
[Home](http://parsedown.org) · [Demo](http://parsedown.org/explorer/) · [Tests](http://parsedown.org/tests/)
|
||||
|
||||
### Installation
|
||||
|
||||
@ -18,3 +17,5 @@ $result = Parsedown::instance()->parse($text);
|
||||
|
||||
echo $result; # prints: <p>Hello <strong>Parsedown</strong>!</p>
|
||||
```
|
||||
|
||||
[1]: http://daringfireball.net/projects/markdown/
|
||||
|
@ -20,20 +20,29 @@ class Test extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
$provider = array();
|
||||
|
||||
$DirectoryIterator = new DirectoryIterator(__DIR__ . '/' . self::provider_dir);
|
||||
$path = dirname(__FILE__).'/';
|
||||
|
||||
$DirectoryIterator = new DirectoryIterator($path . '/' . self::provider_dir);
|
||||
|
||||
foreach ($DirectoryIterator as $Item)
|
||||
{
|
||||
if ($Item->isFile() and $Item->getExtension() === 'md')
|
||||
if ($Item->isFile())
|
||||
{
|
||||
$filename = $Item->getFilename();
|
||||
|
||||
$extension = pathinfo($filename, PATHINFO_EXTENSION);
|
||||
|
||||
if ($extension !== 'md')
|
||||
continue;
|
||||
|
||||
$basename = $Item->getBasename('.md');
|
||||
|
||||
$markdown = file_get_contents(__DIR__ . '/' . self::provider_dir . $basename . '.md');
|
||||
$markdown = file_get_contents($path . '/' . self::provider_dir . $basename . '.md');
|
||||
|
||||
if (!$markdown)
|
||||
continue;
|
||||
|
||||
$expected_markup = file_get_contents(__DIR__ . '/' . self::provider_dir . $basename . '.html');
|
||||
$expected_markup = file_get_contents($path . '/' . self::provider_dir . $basename . '.html');
|
||||
$expected_markup = str_replace("\r\n", "\n", $expected_markup);
|
||||
$expected_markup = str_replace("\r", "\n", $expected_markup);
|
||||
|
||||
@ -44,4 +53,3 @@ class Test extends PHPUnit_Framework_TestCase
|
||||
return $provider;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
<h1>This is an h1</h1>
|
||||
<h2>This is an h2</h2>
|
||||
<h3>This is an h3</h3>
|
||||
<h4>This is an h4</h4>
|
||||
<h5>This is an h5</h5>
|
||||
<h6>This is an h6</h6>
|
||||
<h1>h1</h1>
|
||||
<h2>h2</h2>
|
||||
<h3>h3</h3>
|
||||
<h4>h4</h4>
|
||||
<h5>h5</h5>
|
||||
<h6>h6</h6>
|
||||
<h1>closed h1</h1>
|
@ -1,11 +1,13 @@
|
||||
# This is an h1
|
||||
# h1
|
||||
|
||||
## This is an h2
|
||||
## h2
|
||||
|
||||
### This is an h3
|
||||
### h3
|
||||
|
||||
#### This is an h4
|
||||
#### h4
|
||||
|
||||
##### This is an h5
|
||||
##### h5
|
||||
|
||||
###### This is an h6
|
||||
###### h6
|
||||
|
||||
# closed h1 #
|
9
tests/data/block-level_html.html
Normal file
9
tests/data/block-level_html.html
Normal file
@ -0,0 +1,9 @@
|
||||
<div>content</div>
|
||||
<hr style="background: #eaa;" />
|
||||
<p>nested elements:</p>
|
||||
<div>
|
||||
parent
|
||||
<div>
|
||||
child
|
||||
</div>
|
||||
</div>
|
12
tests/data/block-level_html.md
Normal file
12
tests/data/block-level_html.md
Normal file
@ -0,0 +1,12 @@
|
||||
<div>content</div>
|
||||
|
||||
<hr style="background: #eaa;" />
|
||||
|
||||
nested elements:
|
||||
|
||||
<div>
|
||||
parent
|
||||
<div>
|
||||
child
|
||||
</div>
|
||||
</div>
|
@ -1,13 +0,0 @@
|
||||
<p>Here's a regular blockquote:</p>
|
||||
<blockquote>
|
||||
<p>blockquote</p>
|
||||
</blockquote>
|
||||
<p>Here's one with no space after the ">":</p>
|
||||
<blockquote>
|
||||
<p>blockquote</p>
|
||||
</blockquote>
|
||||
<p>Here's one on multiple lines:</p>
|
||||
<blockquote>
|
||||
<p>line 1
|
||||
line 2</p>
|
||||
</blockquote>
|
@ -1,12 +0,0 @@
|
||||
Here's a regular blockquote:
|
||||
|
||||
> blockquote
|
||||
|
||||
Here's one with no space after the ">":
|
||||
|
||||
>blockquote
|
||||
|
||||
Here's one on multiple lines:
|
||||
|
||||
> line 1
|
||||
> line 2
|
@ -1,6 +0,0 @@
|
||||
<h1>h1</h1>
|
||||
<h2>h2</h2>
|
||||
<h3>h3</h3>
|
||||
<h4>h4</h4>
|
||||
<h5>h5</h5>
|
||||
<h6>h6</h6>
|
@ -1,11 +0,0 @@
|
||||
# h1 #
|
||||
|
||||
## h2 ##
|
||||
|
||||
### h3 ###
|
||||
|
||||
#### h4 ####
|
||||
|
||||
##### h5 #####
|
||||
|
||||
###### h6 ######
|
@ -1,9 +1,8 @@
|
||||
<p>Here's a regular code block:</p>
|
||||
<pre><code><?php
|
||||
|
||||
echo 'Hello World!';
|
||||
|
||||
?></code></pre>
|
||||
<p>Here's one that holds a list:</p>
|
||||
<pre><code>- list item
|
||||
- another list item</code></pre>
|
||||
$message = 'Hello World!';
|
||||
echo $message;</code></pre>
|
||||
<hr />
|
||||
<pre><code>> not a quote
|
||||
- not a list item
|
||||
[not a reference]: http://foo.com</code></pre>
|
@ -1,13 +1,11 @@
|
||||
Here's a regular code block:
|
||||
|
||||
<?php
|
||||
|
||||
echo 'Hello World!';
|
||||
$message = 'Hello World!';
|
||||
echo $message;
|
||||
|
||||
?>
|
||||
---
|
||||
|
||||
Here's one that holds a list:
|
||||
|
||||
- list item
|
||||
- another list item
|
||||
> not a quote
|
||||
- not a list item
|
||||
[not a reference]: http://foo.com
|
||||
|
@ -1 +1 @@
|
||||
<p>This is a <code>code span</code>.</p>
|
||||
<p>a <code>code span</code></p>
|
@ -1 +1 @@
|
||||
This is a `code span`.
|
||||
a `code span`
|
@ -1,16 +1,9 @@
|
||||
<p>Here's one with multiple paragraphs:</p>
|
||||
<blockquote>
|
||||
<p>This is line one.</p>
|
||||
<p>This is line two.</p>
|
||||
</blockquote>
|
||||
<p>Here's one with multiple types of blocks:</p>
|
||||
<blockquote>
|
||||
<p>This is a quoted paragraph.</p>
|
||||
<h2>header</h2>
|
||||
<p>paragraph</p>
|
||||
<ul>
|
||||
<li>This is a list item of a quoted list.</li>
|
||||
<li>This is another list item.</li>
|
||||
<li>li</li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<p>This is a nested quote block.</p>
|
||||
</blockquote>
|
||||
<hr />
|
||||
<p>paragraph</p>
|
||||
</blockquote>
|
@ -1,14 +1,10 @@
|
||||
Here's one with multiple paragraphs:
|
||||
|
||||
> This is line one.
|
||||
> header
|
||||
> ------
|
||||
>
|
||||
> This is line two.
|
||||
|
||||
Here's one with multiple types of blocks:
|
||||
|
||||
> This is a quoted paragraph.
|
||||
> paragraph
|
||||
>
|
||||
> - This is a list item of a quoted list.
|
||||
> - This is another list item.
|
||||
> - li
|
||||
>
|
||||
> > This is a nested quote block.
|
||||
> ---
|
||||
>
|
||||
> paragraph
|
@ -1,13 +1,12 @@
|
||||
<p>Here's a compound list:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>This is the first paragraph of the list item.</p>
|
||||
<p>This is the second one.</p>
|
||||
<p>paragraph</p>
|
||||
<p>paragraph</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>This is another list item.</p>
|
||||
<p>paragraph</p>
|
||||
<blockquote>
|
||||
<p>This is a quote block that belongs to it.</p>
|
||||
<p>quote</p>
|
||||
</blockquote>
|
||||
</li>
|
||||
</ul>
|
@ -1,10 +1,7 @@
|
||||
Here's a compound list:
|
||||
- paragraph
|
||||
|
||||
- This is the first paragraph of the list item.
|
||||
paragraph
|
||||
|
||||
This is the second one.
|
||||
|
||||
- This is another list item.
|
||||
|
||||
> This is a quote block that belongs to it.
|
||||
- paragraph
|
||||
|
||||
> quote
|
@ -1,24 +0,0 @@
|
||||
<p>Here's a regular list:</p>
|
||||
<ul>
|
||||
<li>list item</li>
|
||||
<li>another list item</li>
|
||||
<li>3rd list item</li>
|
||||
</ul>
|
||||
<p>Here's one with white space around items:</p>
|
||||
<ul>
|
||||
<li>list item </li>
|
||||
<li>another list item </li>
|
||||
</ul>
|
||||
<p>Here's one with too much space before items:</p>
|
||||
<pre><code>- list item
|
||||
- another list item</code></pre>
|
||||
<p>Here's one with no space after markers:</p>
|
||||
<p>-list item
|
||||
-another list item</p>
|
||||
<p>Here's one where items contain line breaks:</p>
|
||||
<ul>
|
||||
<li>list
|
||||
item</li>
|
||||
<li>another
|
||||
list item</li>
|
||||
</ul>
|
@ -1,27 +0,0 @@
|
||||
Here's a regular list:
|
||||
|
||||
- list item
|
||||
- another list item
|
||||
- 3rd list item
|
||||
|
||||
Here's one with white space around items:
|
||||
|
||||
- list item
|
||||
- another list item
|
||||
|
||||
Here's one with too much space before items:
|
||||
|
||||
- list item
|
||||
- another list item
|
||||
|
||||
Here's one with no space after markers:
|
||||
|
||||
-list item
|
||||
-another list item
|
||||
|
||||
Here's one where items contain line breaks:
|
||||
|
||||
- list
|
||||
item
|
||||
- another
|
||||
list item
|
5
tests/data/em_strong.html
Normal file
5
tests/data/em_strong.html
Normal file
@ -0,0 +1,5 @@
|
||||
<p><strong><em>em strong</em></strong></p>
|
||||
<p><strong><em>one</em> at the start</strong></p>
|
||||
<p><strong>one at the <em>end</em></strong></p>
|
||||
<p><strong>one <em>in the</em> middle</strong></p>
|
||||
<p><strong>one with <em>asterisks</em></strong></p>
|
9
tests/data/em_strong.md
Normal file
9
tests/data/em_strong.md
Normal file
@ -0,0 +1,9 @@
|
||||
___em strong___
|
||||
|
||||
___one_ at the start__
|
||||
|
||||
__one at the _end___
|
||||
|
||||
__one _in the_ middle__
|
||||
|
||||
**one with *asterisks***
|
@ -1,7 +1,6 @@
|
||||
<p>Here's <em>an emphasis</em>.</p>
|
||||
<p>A short emphasis <em>a</em> <em>b</em> .</p>
|
||||
<p>Here's <strong>a strong one</strong>. </p>
|
||||
<p>Here's <em>an emphasis that uses underscores</em>. </p>
|
||||
<p>Here's <strong>a strong emphasis that uses underscores</strong>.</p>
|
||||
<p>This is not _ an emphasis _ neither is * this * neither is _ this_ neither is _this _.</p>
|
||||
<p>Empty emphasis ** is not __ an emphasis.</p>
|
||||
<p><em>underscore</em>, <em>asterisk</em>, <em>one two</em>, <em>three four</em>, <em>a</em>, <em>b</em></p>
|
||||
<p><em>multiline
|
||||
emphasis</em></p>
|
||||
<p>_ this _ is not an emphasis, neither is _ this_, _this _, or _this*</p>
|
||||
<p>this_is_not_an_emphasis</p>
|
||||
<p>an empty emphasis __ ** is not an emphasis</p>
|
@ -1,13 +1,10 @@
|
||||
Here's *an emphasis*.
|
||||
_underscore_, *asterisk*, _one two_, *three four*, _a_, *b*
|
||||
|
||||
A short emphasis _a_ *b* .
|
||||
_multiline
|
||||
emphasis_
|
||||
|
||||
Here's **a strong one**.
|
||||
_ this _ is not an emphasis, neither is _ this_, _this _, or _this*
|
||||
|
||||
Here's _an emphasis that uses underscores_.
|
||||
this_is_not_an_emphasis
|
||||
|
||||
Here's __a strong emphasis that uses underscores__.
|
||||
|
||||
This is not _ an emphasis _ neither is * this * neither is _ this_ neither is _this _.
|
||||
|
||||
Empty emphasis ** is not __ an emphasis.
|
||||
an empty emphasis __ ** is not an emphasis
|
@ -1,6 +1,4 @@
|
||||
<p>Here's an <em>emphasis</em> and here's an escaped *emphasis*. Here are also an escaped `code span`, escaped [inline link](http://example.com).</p>
|
||||
<p>Here's <code>an escaped \*emphasis\* inside of a code span</code>.</p>
|
||||
<p>Here's one inside of a code block:</p>
|
||||
<pre><code>An escaped \*emphasis\*.</code></pre>
|
||||
<p>Finally, an escaped reference:</p>
|
||||
<p>[1]: http://example.com</p>
|
||||
<p>escaped *emphasis*.</p>
|
||||
<p><code>escaped \*emphasis\* in a code span</code></p>
|
||||
<pre><code>escaped \*emphasis\* in a code block</code></pre>
|
||||
<p>\ ` * _ { } [ ] ( ) > # + - . !</p>
|
@ -1,11 +1,7 @@
|
||||
Here's an *emphasis* and here's an escaped \*emphasis\*. Here are also an escaped \`code span\`, escaped \[inline link](http://example.com).
|
||||
escaped \*emphasis\*.
|
||||
|
||||
Here's `an escaped \*emphasis\* inside of a code span`.
|
||||
`escaped \*emphasis\* in a code span`
|
||||
|
||||
Here's one inside of a code block:
|
||||
escaped \*emphasis\* in a code block
|
||||
|
||||
An escaped \*emphasis\*.
|
||||
|
||||
Finally, an escaped reference:
|
||||
|
||||
\[1]: http://example.com
|
||||
\\ \` \* \_ \{ \} \[ \] \( \) \> \# \+ \- \. \!
|
5
tests/data/fenced_code_block.html
Normal file
5
tests/data/fenced_code_block.html
Normal file
@ -0,0 +1,5 @@
|
||||
<pre><code><?php
|
||||
|
||||
$message = 'fenced code block';
|
||||
echo $message;</code></pre>
|
||||
<pre><code>tilde</code></pre>
|
10
tests/data/fenced_code_block.md
Normal file
10
tests/data/fenced_code_block.md
Normal file
@ -0,0 +1,10 @@
|
||||
```
|
||||
<?php
|
||||
|
||||
$message = 'fenced code block';
|
||||
echo $message;
|
||||
```
|
||||
|
||||
~~~
|
||||
tilde
|
||||
~~~
|
@ -1,16 +1,5 @@
|
||||
<p>Dashes:</p>
|
||||
<hr />
|
||||
<hr />
|
||||
<hr />
|
||||
<hr />
|
||||
<pre><code>---</code></pre>
|
||||
<hr />
|
||||
<hr />
|
||||
<hr />
|
||||
<hr />
|
||||
<pre><code>- - -</code></pre>
|
||||
<p>Asterisks:</p>
|
||||
<hr />
|
||||
<p>Underscores:</p>
|
||||
<hr />
|
||||
<p>Based on <a href="http://daringfireball.net/projects/downloads/MarkdownTest_1.0.zip">the original</a> test suite.</p>
|
@ -1,31 +1,9 @@
|
||||
Dashes:
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
- - -
|
||||
|
||||
- - -
|
||||
|
||||
- - -
|
||||
|
||||
- - -
|
||||
|
||||
- - -
|
||||
|
||||
Asterisks:
|
||||
|
||||
***
|
||||
|
||||
Underscores:
|
||||
|
||||
___
|
||||
|
||||
Based on [the original](http://daringfireball.net/projects/downloads/MarkdownTest_1.0.zip) test suite.
|
1
tests/data/image_reference.html
Normal file
1
tests/data/image_reference.html
Normal file
@ -0,0 +1 @@
|
||||
<p><img alt="Markdown Logo" src="/md.png"></p>
|
3
tests/data/image_reference.md
Normal file
3
tests/data/image_reference.md
Normal file
@ -0,0 +1,3 @@
|
||||
![Markdown Logo][image]
|
||||
|
||||
[image]: /md.png
|
2
tests/data/implicit_reference.html
Normal file
2
tests/data/implicit_reference.html
Normal file
@ -0,0 +1,2 @@
|
||||
<p>an <a href="http://example.com">implicit</a> reference link</p>
|
||||
<p>an <a href="http://example.com">implicit</a> reference link with an empty link definition</p>
|
5
tests/data/implicit_reference.md
Normal file
5
tests/data/implicit_reference.md
Normal file
@ -0,0 +1,5 @@
|
||||
an [implicit] reference link
|
||||
|
||||
[implicit]: http://example.com
|
||||
|
||||
an [implicit][] reference link with an empty link definition
|
@ -1,2 +1,2 @@
|
||||
<p>Here's a <a href="http://parsedown.org">link</a>.</p>
|
||||
<p>Here's an image link: <a href="http://daringfireball.net/projects/markdown/"><img alt="MD Logo" src="http://parsedown.org/md.png"></a>.</p>
|
||||
<p><a href="http://example.com">link</a></p>
|
||||
<p><a href="http://example.com"><img alt="MD Logo" src="http://parsedown.org/md.png"></a></p>
|
@ -1,3 +1,3 @@
|
||||
Here's a [link](http://parsedown.org).
|
||||
[link](http://example.com)
|
||||
|
||||
Here's an image link: [](http://daringfireball.net/projects/markdown/).
|
||||
[](http://example.com)
|
@ -1,4 +1,4 @@
|
||||
<blockquote>
|
||||
<p>line 1
|
||||
line 2</p>
|
||||
<p>quote
|
||||
the rest of it</p>
|
||||
</blockquote>
|
@ -1,2 +1,2 @@
|
||||
> line 1
|
||||
line 2
|
||||
> quote
|
||||
the rest of it
|
4
tests/data/lazy_list.html
Normal file
4
tests/data/lazy_list.html
Normal file
@ -0,0 +1,4 @@
|
||||
<ul>
|
||||
<li>li
|
||||
the rest of it</li>
|
||||
</ul>
|
2
tests/data/lazy_list.md
Normal file
2
tests/data/lazy_list.md
Normal file
@ -0,0 +1,2 @@
|
||||
- li
|
||||
the rest of it
|
@ -1,4 +0,0 @@
|
||||
<ul>
|
||||
<li>li
|
||||
more text</li>
|
||||
</ul>
|
@ -1,2 +0,0 @@
|
||||
- li
|
||||
more text
|
@ -1,16 +1,13 @@
|
||||
<p>Here's a regular ordered list:</p>
|
||||
<ol>
|
||||
<li>one</li>
|
||||
<li>two</li>
|
||||
<li>three</li>
|
||||
</ol>
|
||||
<p>Here's one with repeating numbers:</p>
|
||||
<ol>
|
||||
<li>one</li>
|
||||
<li>two</li>
|
||||
</ol>
|
||||
<p>Here's one with large numbers:</p>
|
||||
<p>repeating numbers:</p>
|
||||
<ol>
|
||||
<li>one</li>
|
||||
<li>two</li>
|
||||
</ol>
|
||||
<p>large numbers:</p>
|
||||
<ol>
|
||||
<li>one</li>
|
||||
</ol>
|
@ -1,16 +1,11 @@
|
||||
Here's a regular ordered list:
|
||||
|
||||
1. one
|
||||
2. two
|
||||
3. three
|
||||
|
||||
Here's one with repeating numbers:
|
||||
repeating numbers:
|
||||
|
||||
1. one
|
||||
1. two
|
||||
|
||||
Here's one with large numbers:
|
||||
large numbers:
|
||||
|
||||
123. one
|
||||
123. two
|
||||
|
||||
|
@ -1,4 +0,0 @@
|
||||
<p>Here's a paragraph.</p>
|
||||
<blockquote>
|
||||
<p>a block quote that belongs to it.</p>
|
||||
</blockquote>
|
@ -1,2 +0,0 @@
|
||||
Here's a paragraph.
|
||||
> a block quote that belongs to it.
|
@ -1,5 +0,0 @@
|
||||
<p>Here's a list that's "inside" a paragraph:</p>
|
||||
<ul>
|
||||
<li>list item</li>
|
||||
<li>another list item</li>
|
||||
</ul>
|
@ -1,4 +0,0 @@
|
||||
Here's a list that's "inside" a paragraph:
|
||||
- list item
|
||||
- another list item
|
||||
|
@ -1,20 +0,0 @@
|
||||
<p>Here's a regular quote block:</p>
|
||||
<blockquote>
|
||||
<p>Some quoted text.
|
||||
Here goes some more.</p>
|
||||
</blockquote>
|
||||
<p>Here's one with space before lines:</p>
|
||||
<blockquote>
|
||||
<p>Some quoted text.
|
||||
Here goes some more.</p>
|
||||
</blockquote>
|
||||
<p>Here's one with no space after >:</p>
|
||||
<blockquote>
|
||||
<p>Some quoted text.
|
||||
Here goes some more.</p>
|
||||
</blockquote>
|
||||
<p>Here's one with no > on the second line:</p>
|
||||
<blockquote>
|
||||
<p>Some quoted text.
|
||||
Here goes some more.</p>
|
||||
</blockquote>
|
@ -1,19 +0,0 @@
|
||||
Here's a regular quote block:
|
||||
|
||||
> Some quoted text.
|
||||
> Here goes some more.
|
||||
|
||||
Here's one with space before lines:
|
||||
|
||||
> Some quoted text.
|
||||
> Here goes some more.
|
||||
|
||||
Here's one with no space after >:
|
||||
|
||||
>Some quoted text.
|
||||
>Here goes some more.
|
||||
|
||||
Here's one with no > on the second line:
|
||||
|
||||
> Some quoted text.
|
||||
Here goes some more.
|
@ -1,14 +0,0 @@
|
||||
<p>Here's a <a href="http://parsedown.org">reference link</a>.</p>
|
||||
<p>Here's <a href="http://parsedown.org">one</a> with an alternative syntax.</p>
|
||||
<p>Here's <a href="http://parsedown.org">one</a> on the next line.</p>
|
||||
<p>Here's <a href="http://parsedown.org">one</a> on 2 lines.</p>
|
||||
<p>Here's <a href="http://parsedown.org/tests/">one</a> with a different URL.</p>
|
||||
<p>Here's <a href="http://parsedown.org">one</a> with a semantic name.</p>
|
||||
<p>Here's <a href="http://parsedown.org">one</a> with definition name on the next line.</p>
|
||||
<p>Here's [one][404] with no definition.</p>
|
||||
<p>Here's an image: <img alt="Markdown Logo" src="/md.png"></p>
|
||||
<p>Here's an <a href="http://google.com">implicit one</a>.</p>
|
||||
<p>Here's an <a href="http://google.com">implicit one</a>.</p>
|
||||
<p>Here's an <a href="http://google.com">implicit one</a> with an empty link definition.</p>
|
||||
<p>Here's a <a href="http://parsedown.org">multiline
|
||||
one</a> defined on 2 lines.</p>
|
@ -1,43 +0,0 @@
|
||||
Here's a [reference link][1].
|
||||
|
||||
[1]: http://parsedown.org
|
||||
|
||||
Here's [one] [2] with an alternative syntax.
|
||||
|
||||
[2] :http://parsedown.org
|
||||
|
||||
Here's [one][3] on the next line.
|
||||
[3]: http://parsedown.org
|
||||
|
||||
Here's [one][4] on 2 lines.
|
||||
|
||||
[4]:
|
||||
http://parsedown.org
|
||||
|
||||
Here's [one][5] with a different URL.
|
||||
|
||||
[5]: http://parsedown.org/tests/
|
||||
|
||||
Here's [one][website] with a semantic name.
|
||||
|
||||
[website]: http://parsedown.org
|
||||
|
||||
Here's [one]
|
||||
[website] with definition name on the next line.
|
||||
|
||||
Here's [one][404] with no definition.
|
||||
|
||||
Here's an image: ![Markdown Logo][image]
|
||||
|
||||
[image]: /md.png
|
||||
|
||||
Here's an [implicit one].
|
||||
|
||||
Here's an [implicit one].
|
||||
|
||||
[implicit one]: http://google.com
|
||||
|
||||
Here's an [implicit one][] with an empty link definition.
|
||||
|
||||
Here's a [multiline
|
||||
one][website] defined on 2 lines.
|
@ -1,6 +0,0 @@
|
||||
<h1>Heading 1</h1>
|
||||
<h2>Heading 2</h2>
|
||||
<h2>Block Heading</h2>
|
||||
<p>This is the rest of the block.</p>
|
||||
<h1>Single "="</h1>
|
||||
<h2>Single "-"</h2>
|
@ -1,16 +0,0 @@
|
||||
Heading 1
|
||||
=========
|
||||
|
||||
Heading 2
|
||||
---------
|
||||
|
||||
Block Heading
|
||||
-------------
|
||||
This is the rest of the block.
|
||||
|
||||
Single "="
|
||||
=
|
||||
|
||||
Single "-"
|
||||
-
|
||||
|
11
tests/data/simple_blockquote.html
Normal file
11
tests/data/simple_blockquote.html
Normal file
@ -0,0 +1,11 @@
|
||||
<blockquote>
|
||||
<p>quote</p>
|
||||
</blockquote>
|
||||
<p>indented:</p>
|
||||
<blockquote>
|
||||
<p>quote</p>
|
||||
</blockquote>
|
||||
<p>no space after <code>></code>:</p>
|
||||
<blockquote>
|
||||
<p>quote</p>
|
||||
</blockquote>
|
7
tests/data/simple_blockquote.md
Normal file
7
tests/data/simple_blockquote.md
Normal file
@ -0,0 +1,7 @@
|
||||
> quote
|
||||
|
||||
indented:
|
||||
> quote
|
||||
|
||||
no space after `>`:
|
||||
>quote
|
3
tests/data/span-level_html.html
Normal file
3
tests/data/span-level_html.html
Normal file
@ -0,0 +1,3 @@
|
||||
<p>an <b>important</b> <a href=''>link</a></p>
|
||||
<p>broken<br/>
|
||||
line</p>
|
4
tests/data/span-level_html.md
Normal file
4
tests/data/span-level_html.md
Normal file
@ -0,0 +1,4 @@
|
||||
an <b>important</b> <a href=''>link</a>
|
||||
|
||||
broken<br/>
|
||||
line
|
@ -1,14 +1,15 @@
|
||||
<p>Here's a list where items are separated by empty lines:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<p>list item</p>
|
||||
<p>li</p>
|
||||
</li>
|
||||
<li>another list item</li>
|
||||
<li>li</li>
|
||||
</ul>
|
||||
<p>Here's an ordered one:</p>
|
||||
<ol>
|
||||
<hr />
|
||||
<ul>
|
||||
<li>
|
||||
<p>item one</p>
|
||||
<p>li</p>
|
||||
<ul>
|
||||
<li>indented li</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>item two</li>
|
||||
</ol>
|
||||
</ul>
|
@ -1,11 +1,9 @@
|
||||
Here's a list where items are separated by empty lines:
|
||||
- li
|
||||
|
||||
- list item
|
||||
- li
|
||||
|
||||
- another list item
|
||||
---
|
||||
|
||||
Here's an ordered one:
|
||||
- li
|
||||
|
||||
1. item one
|
||||
|
||||
2. item two
|
||||
- indented li
|
8
tests/data/special_characters.html
Normal file
8
tests/data/special_characters.html
Normal file
@ -0,0 +1,8 @@
|
||||
<p>AT&T has an ampersand in their name</p>
|
||||
<pre><code>Let's play some cards ♠ ♣ ♥ ♦</code></pre>
|
||||
<p>AT&T is another way to write it</p>
|
||||
<p>this & that</p>
|
||||
<p>4 < 5 and 6 > 5</p>
|
||||
<p><a href="http://example.com/autolink?a=1&b=2">http://example.com/autolink?a=1&b=2</a> </p>
|
||||
<p><a href="/script?a=1&b=2">inline link</a></p>
|
||||
<p><a href="http://example.com/?a=1&b=2">reference link</a></p>
|
17
tests/data/special_characters.md
Normal file
17
tests/data/special_characters.md
Normal file
@ -0,0 +1,17 @@
|
||||
AT&T has an ampersand in their name
|
||||
|
||||
Let's play some cards ♠ ♣ ♥ ♦
|
||||
|
||||
AT&T is another way to write it
|
||||
|
||||
this & that
|
||||
|
||||
4 < 5 and 6 > 5
|
||||
|
||||
<http://example.com/autolink?a=1&b=2>
|
||||
|
||||
[inline link](/script?a=1&b=2)
|
||||
|
||||
[reference link][1]
|
||||
|
||||
[1]: http://example.com/?a=1&b=2
|
3
tests/data/strikethrough.html
Normal file
3
tests/data/strikethrough.html
Normal file
@ -0,0 +1,3 @@
|
||||
<p><del>strikethrough</del></p>
|
||||
<p>in the <del>middle</del> of a sentence</p>
|
||||
<p>in the middle of a w<del>or</del>d</p>
|
5
tests/data/strikethrough.md
Normal file
5
tests/data/strikethrough.md
Normal file
@ -0,0 +1,5 @@
|
||||
~~strikethrough~~
|
||||
|
||||
in the ~~middle~~ of a sentence
|
||||
|
||||
in the middle of a w~~or~~d
|
6
tests/data/strong_em.html
Normal file
6
tests/data/strong_em.html
Normal file
@ -0,0 +1,6 @@
|
||||
<p><em><strong>strong em</strong></em> </p>
|
||||
<p><em>em <strong>strong em</strong></em></p>
|
||||
<p><em><strong>strong em</strong> em</em></p>
|
||||
<p><em><strong>strong em</strong></em></p>
|
||||
<p><em>em <strong>strong em</strong></em></p>
|
||||
<p><em><strong>strong em</strong> em</em></p>
|
11
tests/data/strong_em.md
Normal file
11
tests/data/strong_em.md
Normal file
@ -0,0 +1,11 @@
|
||||
***strong em***
|
||||
|
||||
*em **strong em***
|
||||
|
||||
***strong em** em*
|
||||
|
||||
___strong em___
|
||||
|
||||
_em __strong em___
|
||||
|
||||
___strong em__ em_
|
6
tests/data/text_reference.html
Normal file
6
tests/data/text_reference.html
Normal file
@ -0,0 +1,6 @@
|
||||
<p><a href="http://example.com">reference link</a></p>
|
||||
<p><a href="http://example.com">one</a> with a semantic name</p>
|
||||
<p>[one][404] with no definition</p>
|
||||
<p><a href="http://example.com">multiline
|
||||
one</a> defined on 2 lines</p>
|
||||
<p><a href="http://example.com">one</a> with an upper case label</p>
|
16
tests/data/text_reference.md
Normal file
16
tests/data/text_reference.md
Normal file
@ -0,0 +1,16 @@
|
||||
[reference link][1]
|
||||
|
||||
[1]: http://example.com
|
||||
|
||||
[one][website] with a semantic name
|
||||
|
||||
[website]: http://example.com
|
||||
|
||||
[one][404] with no definition
|
||||
|
||||
[multiline
|
||||
one][website] defined on 2 lines
|
||||
|
||||
[one][label] with an upper case label
|
||||
|
||||
[LABEL]: http://example.com
|
@ -1,20 +1,10 @@
|
||||
<p>Here's a regular unordered list:</p>
|
||||
<ul>
|
||||
<li>list item</li>
|
||||
<li>another list item</li>
|
||||
<li>3rd list item</li>
|
||||
<li>li</li>
|
||||
<li>li</li>
|
||||
</ul>
|
||||
<p>Here's one with a variety of markers:</p>
|
||||
<p>mixed markers:</p>
|
||||
<ul>
|
||||
<li>hyphen</li>
|
||||
<li>plus</li>
|
||||
<li>asterisk</li>
|
||||
<li>li</li>
|
||||
<li>li</li>
|
||||
<li>li</li>
|
||||
</ul>
|
||||
<p>Here's one with white space around items:</p>
|
||||
<ul>
|
||||
<li>list item </li>
|
||||
<li>another list item </li>
|
||||
</ul>
|
||||
<p>Here's one with no space after markers:</p>
|
||||
<p>-list item
|
||||
-another list item</p>
|
@ -1,21 +1,8 @@
|
||||
Here's a regular unordered list:
|
||||
- li
|
||||
- li
|
||||
|
||||
- list item
|
||||
- another list item
|
||||
- 3rd list item
|
||||
mixed markers:
|
||||
|
||||
Here's one with a variety of markers:
|
||||
|
||||
- hyphen
|
||||
+ plus
|
||||
* asterisk
|
||||
|
||||
Here's one with white space around items:
|
||||
|
||||
- list item
|
||||
- another list item
|
||||
|
||||
Here's one with no space after markers:
|
||||
|
||||
-list item
|
||||
-another list item
|
||||
* li
|
||||
+ li
|
||||
- li
|
1
tests/data/url_autolinking.html
Normal file
1
tests/data/url_autolinking.html
Normal file
@ -0,0 +1 @@
|
||||
<p>Here's an autolink <a href="http://example.com">http://example.com</a>.</p>
|
1
tests/data/url_autolinking.md
Normal file
1
tests/data/url_autolinking.md
Normal file
@ -0,0 +1 @@
|
||||
Here's an autolink http://example.com.
|
1
tests/data/whitespace.html
Normal file
1
tests/data/whitespace.html
Normal file
@ -0,0 +1 @@
|
||||
<pre><code>code</code></pre>
|
5
tests/data/whitespace.md
Normal file
5
tests/data/whitespace.md
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
code
|
||||
|
||||
|
Reference in New Issue
Block a user