1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @copyright Copyright (c) 2014 Carsten Brandt |
4
|
|
|
* @license https://github.com/cebe/markdown/blob/master/LICENSE |
5
|
|
|
* @link https://github.com/cebe/markdown#readme |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace cebe\markdown; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Markdown parser for the [initial markdown spec](http://daringfireball.net/projects/markdown/syntax). |
12
|
|
|
* |
13
|
|
|
* @author Carsten Brandt <[email protected]> |
14
|
|
|
*/ |
15
|
|
|
class Markdown extends Parser |
16
|
|
|
{ |
17
|
|
|
// include block element parsing using traits |
18
|
|
|
use block\CodeTrait; |
19
|
|
|
use block\HeadlineTrait; |
20
|
|
|
use block\HtmlTrait { |
21
|
|
|
parseInlineHtml as private; |
22
|
|
|
} |
23
|
|
|
use block\ListTrait { |
24
|
|
|
// Check Ul List before headline |
25
|
|
|
identifyUl as protected identifyBUl; |
26
|
|
|
consumeUl as protected consumeBUl; |
27
|
|
|
} |
28
|
|
|
use block\QuoteTrait; |
29
|
|
|
use block\RuleTrait { |
30
|
|
|
// Check Hr before checking lists |
31
|
|
|
identifyHr as protected identifyAHr; |
32
|
|
|
consumeHr as protected consumeAHr; |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
// include inline element parsing using traits |
36
|
|
|
use inline\CodeTrait; |
37
|
|
|
use inline\EmphStrongTrait; |
38
|
|
|
use inline\LinkTrait; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @var boolean whether to format markup according to HTML5 spec. |
42
|
|
|
* Defaults to `false` which means that markup is formatted as HTML4. |
43
|
|
|
*/ |
44
|
|
|
public $html5 = false; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* @var array these are "escapeable" characters. When using one of these prefixed with a |
48
|
|
|
* backslash, the character will be outputted without the backslash and is not interpreted |
49
|
|
|
* as markdown. |
50
|
|
|
*/ |
51
|
|
|
protected $escapeCharacters = [ |
52
|
|
|
'\\', // backslash |
53
|
|
|
'`', // backtick |
54
|
|
|
'*', // asterisk |
55
|
|
|
'_', // underscore |
56
|
|
|
'{', '}', // curly braces |
57
|
|
|
'[', ']', // square brackets |
58
|
|
|
'(', ')', // parentheses |
59
|
|
|
'#', // hash mark |
60
|
|
|
'+', // plus sign |
61
|
|
|
'-', // minus sign (hyphen) |
62
|
|
|
'.', // dot |
63
|
|
|
'!', // exclamation mark |
64
|
|
|
'<', '>', |
65
|
|
|
]; |
66
|
|
|
|
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* @inheritDoc |
70
|
|
|
*/ |
71
|
201 |
|
protected function prepare() |
72
|
|
|
{ |
73
|
|
|
// reset references |
74
|
201 |
|
$this->references = []; |
75
|
201 |
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Consume lines for a paragraph |
79
|
|
|
* |
80
|
|
|
* Allow headlines and code to break paragraphs |
81
|
|
|
*/ |
82
|
128 |
|
protected function consumeParagraph($lines, $current) |
83
|
|
|
{ |
84
|
|
|
// consume until newline |
85
|
128 |
|
$content = []; |
86
|
128 |
|
for ($i = $current, $count = count($lines); $i < $count; $i++) { |
87
|
128 |
|
$line = $lines[$i]; |
88
|
|
|
|
89
|
|
|
// a list may break a paragraph when it is inside of a list |
90
|
128 |
|
if (isset($this->context[1]) && $this->context[1] === 'list' && !ctype_alpha($line[0]) && ( |
91
|
128 |
|
$this->identifyUl($line, $lines, $i) || $this->identifyOl($line, $lines, $i))) { |
92
|
|
|
break; |
93
|
|
|
} |
94
|
|
|
|
95
|
128 |
|
if ($line === '' || ltrim($line) === '' || $this->identifyHeadline($line, $lines, $i)) { |
96
|
104 |
|
break; |
97
|
128 |
|
} elseif ($line[0] === "\t" || $line[0] === " " && strncmp($line, ' ', 4) === 0) { |
98
|
|
|
// possible beginning of a code block |
99
|
|
|
// but check for continued inline HTML |
100
|
|
|
// e.g. <img src="file.jpg" |
101
|
|
|
// alt="some alt aligned with src attribute" title="some text" /> |
102
|
4 |
|
if (preg_match('~<\w+([^>]+)$~s', implode("\n", $content))) { |
103
|
2 |
|
$content[] = $line; |
104
|
|
|
} else { |
105
|
4 |
|
break; |
106
|
|
|
} |
107
|
|
|
} else { |
108
|
128 |
|
$content[] = $line; |
109
|
|
|
} |
110
|
|
|
} |
111
|
|
|
$block = [ |
112
|
128 |
|
'paragraph', |
113
|
128 |
|
'content' => $this->parseInline(implode("\n", $content)), |
114
|
|
|
]; |
115
|
128 |
|
return [$block, --$i]; |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* @inheritdocs |
121
|
|
|
* |
122
|
|
|
* Parses a newline indicated by two spaces on the end of a markdown line. |
123
|
|
|
*/ |
124
|
200 |
|
protected function renderText($text) |
125
|
|
|
{ |
126
|
200 |
|
return str_replace(" \n", $this->html5 ? "<br>\n" : "<br />\n", $text[1]); |
127
|
|
|
} |
128
|
|
|
} |
129
|
|
|
|