Completed
Push — master ( 6130d0...57338d )
by Dev
24:32 queued 11:23
created

MarkdownParser::doAutoLinks()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 2
eloc 6
nc 2
nop 1
dl 0
loc 11
rs 10
c 2
b 1
f 0
1
<?php
2
3
namespace PiedWeb\CMSBundle\Twig;
4
5
use Michelf\MarkdownExtra;
6
7
/**
8
 * MarkdownParser
9
 * from https://raw.githubusercontent.com/KnpLabs/KnpMarkdownBundle/master/Parser/MarkdownParser.php
10
 * This class extends the original Markdown parser.
11
 * It allows to disable unwanted features to increase performances.
12
 */
13
class MarkdownParser extends MarkdownExtra
14
{
15
    /**
16
     * Use the constructor to disable some of them.
17
     *
18
     * @var array Enabled features
19
     */
20
    protected $features = [
21
        'header' => true,
22
        'list' => true,
23
        'horizontal_rule' => true,
24
        'table' => true,
25
        'foot_note' => true,
26
        'fenced_code_block' => true,
27
        'abbreviation' => true,
28
        'definition_list' => true,
29
        'inline_link' => true, // [link text](url "optional title")
30
        'reference_link' => true, // [link text] [id]
31
        'shortcut_link' => true, // [link text]
32
        'images' => true,
33
        'block_quote' => true,
34
        'code_block' => true,
35
        'html_block' => true,
36
        'auto_link' => true,
37
        'auto_mailto' => true,
38
        'entities' => true,
39
        'no_html' => false,
40
    ];
41
42
    /**
43
     * Create a new instance and enable or disable features.
44
     *
45
     * @param array $features enabled or disabled features
46
     *
47
     *                        You can pass an array of features to disable some of them for performance improvement.
48
     *                        E.g.
49
     *                        $features = array(
50
     *                        'table' => false,
51
     *                        'definition_list' => false
52
     *                        )
53
     */
54
    public function __construct(array $features = [])
55
    {
56
        parent::__construct();
57
58
        $this->features = array_merge($this->features, $features);
59
60
        if (!$this->features['header']) {
61
            unset($this->block_gamut['doHeaders']);
62
        }
63
        if (!$this->features['list']) {
64
            unset($this->block_gamut['doLists']);
65
        }
66
        if (!$this->features['horizontal_rule']) {
67
            unset($this->block_gamut['doHorizontalRules']);
68
        }
69
        if (!$this->features['table']) {
70
            unset($this->block_gamut['doTables']);
71
        }
72
        if (!$this->features['foot_note']) {
73
            unset($this->document_gamut['stripFootnotes']);
74
            unset($this->document_gamut['appendFootnotes']);
75
            unset($this->span_gamut['doFootnotes']);
76
        }
77
        if (!$this->features['fenced_code_block']) {
78
            unset($this->document_gamut['doFencedCodeBlocks']);
79
            unset($this->block_gamut['doFencedCodeBlocks']);
80
        }
81
        if (!$this->features['abbreviation']) {
82
            unset($this->document_gamut['stripAbbreviations']);
83
            unset($this->span_gamut['doAbbreviations']);
84
        }
85
        if (!$this->features['definition_list']) {
86
            unset($this->block_gamut['doDefLists']);
87
        }
88
        if (!$this->features['reference_link']) {
89
            unset($this->document_gamut['stripLinkDefinitions']);
90
        }
91
        if (!$this->features['images']) {
92
            unset($this->span_gamut['doImages']);
93
        }
94
        if (!$this->features['block_quote']) {
95
            unset($this->block_gamut['doBlockQuotes']);
96
        }
97
        if (!$this->features['code_block']) {
98
            unset($this->block_gamut['doCodeBlocks']);
99
        }
100
        if (!$this->features['auto_link']) {
101
            unset($this->span_gamut['doAutoLinks']);
102
        }
103
        if (false === $this->features['entities']) {
104
            $this->no_entities = true;
105
        }
106
        if (true === $this->features['no_html']) {
107
            $this->no_markup = true;
108
        }
109
    }
110
111
    /**
112
     * {@inheritdoc}
113
     */
114
    public function transformMarkdown($text)
115
    {
116
        return parent::transform($text);
117
    }
118
119
    /**
120
     * MarkdownExtraParser overwritten methods.
121
     */
122
123
    /**
124
     * Simplify detab.
125
     */
126
    public function detab($text)
127
    {
128
        return str_replace("\t", str_repeat(' ', $this->tab_width), $text);
129
    }
130
131
    /**
132
     * Disable unless html_block.
133
     */
134
    public function hashHTMLBlocks($text)
135
    {
136
        if (!$this->features['html_block']) {
137
            return $text;
138
        }
139
140
        return parent::hashHTMLBlocks($text);
141
    }
142
143
    /**
144
     * Disable mailto unless auto_mailto.
145
     */
146
    public function doAutoLinks($text)
147
    {
148
        if (!$this->features['auto_mailto']) {
149
            return preg_replace_callback(
150
                '{<((https?|ftp|dict):[^\'">\s]+)>}i',
151
                [&$this, '_doAutoLinks_url_callback'],
152
                $text
153
            );
154
        }
155
156
        return parent::doAutoLinks($text);
157
    }
158
159
    /**
160
     * Conditional features: reference_link, inline_link,.
161
     */
162
    public function doAnchors($text)
163
    {
164
        //
165
        // Turn Markdown link shortcuts into XHTML <a> tags.
166
        //
167
        if ($this->in_anchor) {
168
            return $text;
169
        }
170
        $this->in_anchor = true;
171
172
        //
173
        // First, handle reference-style links: [link text] [id]
174
        //
175
        if ($this->features['reference_link']) {
176
            $text = preg_replace_callback(
177
                '{
178
                (               # wrap whole match in $1
179
                  \[
180
                    ('.$this->nested_brackets_re.')	# link text = $2
181
                  \]
182
183
                  [ ]?          # one optional space
184
                  (?:\n[ ]*)?   # one optional newline followed by spaces
185
186
                  \[
187
                    (.*?)       # id = $3
188
                  \]
189
                )
190
                }xs',
191
                [&$this, '_doAnchors_reference_callback'],
192
                $text
193
            );
194
        }
195
196
        //
197
        // Next, inline-style links: [link text](url "optional title")
198
        //
199
        if ($this->features['inline_link']) {
200
            $text = preg_replace_callback(
201
                '{
202
                (               # wrap whole match in $1
203
                  \[
204
                    ('.$this->nested_brackets_re.')	# link text = $2
205
                  \]
206
                  \(            # literal parent
207
                    [ \n]*
208
                    (?:
209
                        <(.+?)> # href = $3
210
                    |
211
                        ('.$this->nested_url_parenthesis_re.')	# href = $4
212
                    )
213
                    [ \n]*
214
                    (           # $5
215
                      ([\'"])   # quote char = $6
216
                      (.*?)     # Title = $7
217
                      \6        # matching quote
218
                      [ \n]*    # ignore any spaces/tabs between closing quote and )
219
                    )?          # title is optional
220
                  \)
221
                  (?:[ ]? '.$this->id_class_attr_catch_re.' )?	 # $8 = id/class attributes
222
                )
223
                }xs',
224
                [&$this, '_doAnchors_inline_callback'],
225
                $text
226
            );
227
        }
228
229
        //
230
        // Last, handle reference-style shortcuts: [link text]
231
        // These must come last in case you've also got [link text][1]
232
        // or [link text](/foo)
233
        //
234
        if ($this->features['shortcut_link']) {
235
            $text = preg_replace_callback(
236
                '{
237
                (               # wrap whole match in $1
238
                  \[
239
                    ([^\[\]]+)  # link text = $2; can\'t contain [ or ]
240
                  \]
241
                )
242
                }xs',
243
                [&$this, '_doAnchors_reference_callback'],
244
                $text
245
            );
246
        }
247
248
        $this->in_anchor = false;
249
250
        return $text;
251
    }
252
}
253