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 github flavored markdown. |
||
12 | * |
||
13 | * @author Carsten Brandt <[email protected]> |
||
14 | */ |
||
15 | class GithubMarkdown extends Markdown |
||
16 | { |
||
17 | // include block element parsing using traits |
||
18 | use block\TableTrait; |
||
19 | use block\FencedCodeTrait; |
||
20 | |||
21 | // include inline element parsing using traits |
||
22 | use inline\StrikeoutTrait; |
||
23 | use inline\UrlLinkTrait; |
||
24 | |||
25 | /** |
||
26 | * @var boolean whether to interpret newlines as `<br />`-tags. |
||
27 | * This feature is useful for comments where newlines are often meant to be real new lines. |
||
28 | */ |
||
29 | public $enableNewlines = false; |
||
30 | |||
31 | /** |
||
32 | * @inheritDoc |
||
33 | */ |
||
34 | protected $escapeCharacters = [ |
||
35 | // from Markdown |
||
36 | '\\', // backslash |
||
37 | '`', // backtick |
||
38 | '*', // asterisk |
||
39 | '_', // underscore |
||
40 | '{', '}', // curly braces |
||
41 | '[', ']', // square brackets |
||
42 | '(', ')', // parentheses |
||
43 | '#', // hash mark |
||
44 | '+', // plus sign |
||
45 | '-', // minus sign (hyphen) |
||
46 | '.', // dot |
||
47 | '!', // exclamation mark |
||
48 | '<', '>', |
||
49 | // added by GithubMarkdown |
||
50 | ':', // colon |
||
51 | '|', // pipe |
||
52 | ]; |
||
53 | |||
54 | |||
55 | |||
56 | /** |
||
57 | * Consume lines for a paragraph |
||
58 | * |
||
59 | * Allow headlines, lists and code to break paragraphs |
||
60 | */ |
||
61 | 71 | protected function consumeParagraph($lines, $current) |
|
62 | { |
||
63 | // consume until newline |
||
64 | 71 | $content = []; |
|
65 | 71 | for ($i = $current, $count = count($lines); $i < $count; $i++) { |
|
66 | 71 | $line = $lines[$i]; |
|
67 | 71 | if ($line === '' |
|
68 | 71 | || ltrim($line) === '' |
|
69 | 71 | || !ctype_alpha($line[0]) && ( |
|
70 | 34 | $this->identifyQuote($line, $lines, $i) || |
|
71 | 34 | $this->identifyFencedCode($line, $lines, $i) || |
|
72 | 34 | $this->identifyUl($line, $lines, $i) || |
|
73 | 33 | $this->identifyOl($line, $lines, $i) || |
|
74 | 71 | $this->identifyHr($line, $lines, $i) |
|
75 | ) |
||
76 | 71 | || $this->identifyHeadline($line, $lines, $i)) |
|
77 | { |
||
78 | 61 | break; |
|
79 | 71 | } elseif ($this->identifyCode($line, $lines, $i)) { |
|
80 | // possible beginning of a code block |
||
81 | // but check for continued inline HTML |
||
82 | // e.g. <img src="file.jpg" |
||
83 | // alt="some alt aligned with src attribute" title="some text" /> |
||
84 | 2 | if (preg_match('~<\w+([^>]+)$~s', implode("\n", $content))) { |
|
85 | 1 | $content[] = $line; |
|
86 | } else { |
||
87 | 2 | break; |
|
88 | } |
||
89 | } else { |
||
90 | 71 | $content[] = $line; |
|
91 | } |
||
92 | } |
||
93 | $block = [ |
||
94 | 71 | 'paragraph', |
|
95 | 71 | 'content' => $this->parseInline(implode("\n", $content)), |
|
96 | ]; |
||
97 | 71 | return [$block, --$i]; |
|
98 | } |
||
99 | |||
100 | /** |
||
101 | * @inheritdocs |
||
102 | * |
||
103 | * Parses a newline indicated by two spaces on the end of a markdown line. |
||
104 | */ |
||
105 | 73 | protected function renderText($text) |
|
106 | { |
||
107 | 73 | if ($this->enableNewlines) { |
|
108 | 1 | $br = $this->html5 ? "<br>\n" : "<br />\n"; |
|
109 | 1 | return strtr($text[1], [" \n" => $br, "\n" => $br]); |
|
110 | } else { |
||
111 | 73 | return parent::renderText($text); |
|
112 | } |
||
113 | } |
||
114 | } |
||
115 |