Test Failed
Push — master ( 4527f5...6e7815 )
by Ylva
21:41 queued 04:42
created
a/vendor/michelf/php-smartypants/Michelf/SmartyPants.php 3 patches
Indentation   +495 added lines, -495 removed lines patch added patch discarded remove patch
@@ -19,303 +19,303 @@  discard block
 block discarded – undo
19 19
 
20 20
 class SmartyPants {
21 21
 
22
-	### Version ###
23
-
24
-	const  SMARTYPANTSLIB_VERSION  =  "1.8.1";
25
-
26
-
27
-	### Presets
28
-
29
-	# SmartyPants does nothing at all
30
-	const  ATTR_DO_NOTHING             =  0;
31
-	# "--" for em-dashes; no en-dash support
32
-	const  ATTR_EM_DASH                =  1;
33
-	# "---" for em-dashes; "--" for en-dashes
34
-	const  ATTR_LONG_EM_DASH_SHORT_EN  =  2;
35
-	# "--" for em-dashes; "---" for en-dashes
36
-	const  ATTR_SHORT_EM_DASH_LONG_EN  =  3;
37
-	# "--" for em-dashes; "---" for en-dashes
38
-	const  ATTR_STUPEFY                = -1;
39
-
40
-	# The default preset: ATTR_EM_DASH
41
-	const  ATTR_DEFAULT  =  SmartyPants::ATTR_EM_DASH;
42
-
43
-
44
-	### Standard Function Interface ###
45
-
46
-	public static function defaultTransform($text, $attr = SmartyPants::ATTR_DEFAULT) {
47
-	#
48
-	# Initialize the parser and return the result of its transform method.
49
-	# This will work fine for derived classes too.
50
-	#
51
-		# Take parser class on which this function was called.
52
-		$parser_class = \get_called_class();
53
-
54
-		# try to take parser from the static parser list
55
-		static $parser_list;
56
-		$parser =& $parser_list[$parser_class][$attr];
57
-
58
-		# create the parser if not already set
59
-		if (!$parser)
60
-			$parser = new $parser_class($attr);
61
-
62
-		# Transform text using parser.
63
-		return $parser->transform($text);
64
-	}
65
-
66
-
67
-	### Configuration Variables ###
68
-
69
-	# Partial regex for matching tags to skip
70
-	public $tags_to_skip = 'pre|code|kbd|script|style|math';
71
-
72
-	# Options to specify which transformations to make:
73
-	public $do_nothing   = 0; # disable all transforms
74
-	public $do_quotes    = 0;
75
-	public $do_backticks = 0; # 1 => double only, 2 => double & single
76
-	public $do_dashes    = 0; # 1, 2, or 3 for the three modes described above
77
-	public $do_ellipses  = 0;
78
-	public $do_stupefy   = 0;
79
-	public $convert_quot = 0; # should we translate " entities into normal quotes?
80
-
81
-	# Smart quote characters:
82
-	# Opening and closing smart double-quotes.
83
-	public $smart_doublequote_open  = '“';
84
-	public $smart_doublequote_close = '”';
85
-	public $smart_singlequote_open  = '‘';
86
-	public $smart_singlequote_close = '’'; # Also apostrophe.
87
-
88
-	# ``Backtick quotes''
89
-	public $backtick_doublequote_open  = '“'; // replacement for ``
90
-	public $backtick_doublequote_close = '”'; // replacement for ''
91
-	public $backtick_singlequote_open  = '‘'; // replacement for `
92
-	public $backtick_singlequote_close = '’'; // replacement for ' (also apostrophe)
93
-
94
-	# Other punctuation
95
-	public $em_dash = '—';
96
-	public $en_dash = '–';
97
-	public $ellipsis = '…';
98
-
99
-	### Parser Implementation ###
100
-
101
-	public function __construct($attr = SmartyPants::ATTR_DEFAULT) {
102
-	#
103
-	# Initialize a parser with certain attributes.
104
-	#
105
-	# Parser attributes:
106
-	# 0 : do nothing
107
-	# 1 : set all
108
-	# 2 : set all, using old school en- and em- dash shortcuts
109
-	# 3 : set all, using inverted old school en and em- dash shortcuts
110
-	# 
111
-	# q : quotes
112
-	# b : backtick quotes (``double'' only)
113
-	# B : backtick quotes (``double'' and `single')
114
-	# d : dashes
115
-	# D : old school dashes
116
-	# i : inverted old school dashes
117
-	# e : ellipses
118
-	# w : convert " entities to " for Dreamweaver users
119
-	#
120
-		if ($attr == "0") {
121
-			$this->do_nothing   = 1;
122
-		}
123
-		else if ($attr == "1") {
124
-			# Do everything, turn all options on.
125
-			$this->do_quotes    = 1;
126
-			$this->do_backticks = 1;
127
-			$this->do_dashes    = 1;
128
-			$this->do_ellipses  = 1;
129
-		}
130
-		else if ($attr == "2") {
131
-			# Do everything, turn all options on, use old school dash shorthand.
132
-			$this->do_quotes    = 1;
133
-			$this->do_backticks = 1;
134
-			$this->do_dashes    = 2;
135
-			$this->do_ellipses  = 1;
136
-		}
137
-		else if ($attr == "3") {
138
-			# Do everything, turn all options on, use inverted old school dash shorthand.
139
-			$this->do_quotes    = 1;
140
-			$this->do_backticks = 1;
141
-			$this->do_dashes    = 3;
142
-			$this->do_ellipses  = 1;
143
-		}
144
-		else if ($attr == "-1") {
145
-			# Special "stupefy" mode.
146
-			$this->do_stupefy   = 1;
147
-		}
148
-		else {
149
-			$chars = preg_split('//', $attr);
150
-			foreach ($chars as $c){
151
-				if      ($c == "q") { $this->do_quotes    = 1; }
152
-				else if ($c == "b") { $this->do_backticks = 1; }
153
-				else if ($c == "B") { $this->do_backticks = 2; }
154
-				else if ($c == "d") { $this->do_dashes    = 1; }
155
-				else if ($c == "D") { $this->do_dashes    = 2; }
156
-				else if ($c == "i") { $this->do_dashes    = 3; }
157
-				else if ($c == "e") { $this->do_ellipses  = 1; }
158
-				else if ($c == "w") { $this->convert_quot = 1; }
159
-				else {
160
-					# Unknown attribute option, ignore.
161
-				}
162
-			}
163
-		}
164
-	}
165
-
166
-	public function transform($text) {
167
-
168
-		if ($this->do_nothing) {
169
-			return $text;
170
-		}
171
-
172
-		$tokens = $this->tokenizeHTML($text);
173
-		$result = '';
174
-		$in_pre = 0;  # Keep track of when we're inside <pre> or <code> tags.
175
-
176
-		$prev_token_last_char = ""; # This is a cheat, used to get some context
177
-									# for one-character tokens that consist of 
178
-									# just a quote char. What we do is remember
179
-									# the last character of the previous text
180
-									# token, to use as context to curl single-
181
-									# character quote tokens correctly.
182
-
183
-		foreach ($tokens as $cur_token) {
184
-			if ($cur_token[0] == "tag") {
185
-				# Don't mess with quotes inside tags.
186
-				$result .= $cur_token[1];
187
-				if (preg_match('@<(/?)(?:'.$this->tags_to_skip.')[\s>]@', $cur_token[1], $matches)) {
188
-					$in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
189
-				}
190
-			} else {
191
-				$t = $cur_token[1];
192
-				$last_char = substr($t, -1); # Remember last char of this token before processing.
193
-				if (! $in_pre) {
194
-					$t = $this->educate($t, $prev_token_last_char);
195
-				}
196
-				$prev_token_last_char = $last_char;
197
-				$result .= $t;
198
-			}
199
-		}
200
-
201
-		return $result;
202
-	}
203
-
204
-
205
-	function decodeEntitiesInConfiguration() {
206
-	#
207
-	#   Utility function that converts entities in configuration variables to
208
-	#   UTF-8 characters.
209
-	#
210
-		$output_config_vars = array(
211
-			'smart_doublequote_open',
212
-			'smart_doublequote_close',
213
-			'smart_singlequote_open',
214
-			'smart_singlequote_close',
215
-			'backtick_doublequote_open',
216
-			'backtick_doublequote_close',
217
-			'backtick_singlequote_open',
218
-			'backtick_singlequote_close',
219
-			'em_dash',
220
-			'en_dash',
221
-			'ellipsis',
222
-		);
223
-		foreach ($output_config_vars as $var) {
224
-			$this->$var = html_entity_decode($this->$var);
225
-		}
226
-	}
227
-
228
-
229
-	protected function educate($t, $prev_token_last_char) {
230
-		$t = $this->processEscapes($t);
231
-
232
-		if ($this->convert_quot) {
233
-			$t = preg_replace('/&quot;/', '"', $t);
234
-		}
235
-
236
-		if ($this->do_dashes) {
237
-			if ($this->do_dashes == 1) $t = $this->educateDashes($t);
238
-			if ($this->do_dashes == 2) $t = $this->educateDashesOldSchool($t);
239
-			if ($this->do_dashes == 3) $t = $this->educateDashesOldSchoolInverted($t);
240
-		}
241
-
242
-		if ($this->do_ellipses) $t = $this->educateEllipses($t);
243
-
244
-		# Note: backticks need to be processed before quotes.
245
-		if ($this->do_backticks) {
246
-			$t = $this->educateBackticks($t);
247
-			if ($this->do_backticks == 2) $t = $this->educateSingleBackticks($t);
248
-		}
249
-
250
-		if ($this->do_quotes) {
251
-			if ($t == "'") {
252
-				# Special case: single-character ' token
253
-				if (preg_match('/\S/', $prev_token_last_char)) {
254
-					$t = $this->smart_singlequote_close;
255
-				}
256
-				else {
257
-					$t = $this->smart_singlequote_open;
258
-				}
259
-			}
260
-			else if ($t == '"') {
261
-				# Special case: single-character " token
262
-				if (preg_match('/\S/', $prev_token_last_char)) {
263
-					$t = $this->smart_doublequote_close;
264
-				}
265
-				else {
266
-					$t = $this->smart_doublequote_open;
267
-				}
268
-			}
269
-			else {
270
-				# Normal case:
271
-				$t = $this->educateQuotes($t);
272
-			}
273
-		}
274
-
275
-		if ($this->do_stupefy) $t = $this->stupefyEntities($t);
22
+    ### Version ###
23
+
24
+    const  SMARTYPANTSLIB_VERSION  =  "1.8.1";
25
+
26
+
27
+    ### Presets
28
+
29
+    # SmartyPants does nothing at all
30
+    const  ATTR_DO_NOTHING             =  0;
31
+    # "--" for em-dashes; no en-dash support
32
+    const  ATTR_EM_DASH                =  1;
33
+    # "---" for em-dashes; "--" for en-dashes
34
+    const  ATTR_LONG_EM_DASH_SHORT_EN  =  2;
35
+    # "--" for em-dashes; "---" for en-dashes
36
+    const  ATTR_SHORT_EM_DASH_LONG_EN  =  3;
37
+    # "--" for em-dashes; "---" for en-dashes
38
+    const  ATTR_STUPEFY                = -1;
39
+
40
+    # The default preset: ATTR_EM_DASH
41
+    const  ATTR_DEFAULT  =  SmartyPants::ATTR_EM_DASH;
42
+
43
+
44
+    ### Standard Function Interface ###
45
+
46
+    public static function defaultTransform($text, $attr = SmartyPants::ATTR_DEFAULT) {
47
+    #
48
+    # Initialize the parser and return the result of its transform method.
49
+    # This will work fine for derived classes too.
50
+    #
51
+        # Take parser class on which this function was called.
52
+        $parser_class = \get_called_class();
53
+
54
+        # try to take parser from the static parser list
55
+        static $parser_list;
56
+        $parser =& $parser_list[$parser_class][$attr];
57
+
58
+        # create the parser if not already set
59
+        if (!$parser)
60
+            $parser = new $parser_class($attr);
61
+
62
+        # Transform text using parser.
63
+        return $parser->transform($text);
64
+    }
65
+
66
+
67
+    ### Configuration Variables ###
68
+
69
+    # Partial regex for matching tags to skip
70
+    public $tags_to_skip = 'pre|code|kbd|script|style|math';
71
+
72
+    # Options to specify which transformations to make:
73
+    public $do_nothing   = 0; # disable all transforms
74
+    public $do_quotes    = 0;
75
+    public $do_backticks = 0; # 1 => double only, 2 => double & single
76
+    public $do_dashes    = 0; # 1, 2, or 3 for the three modes described above
77
+    public $do_ellipses  = 0;
78
+    public $do_stupefy   = 0;
79
+    public $convert_quot = 0; # should we translate &quot; entities into normal quotes?
80
+
81
+    # Smart quote characters:
82
+    # Opening and closing smart double-quotes.
83
+    public $smart_doublequote_open  = '&#8220;';
84
+    public $smart_doublequote_close = '&#8221;';
85
+    public $smart_singlequote_open  = '&#8216;';
86
+    public $smart_singlequote_close = '&#8217;'; # Also apostrophe.
87
+
88
+    # ``Backtick quotes''
89
+    public $backtick_doublequote_open  = '&#8220;'; // replacement for ``
90
+    public $backtick_doublequote_close = '&#8221;'; // replacement for ''
91
+    public $backtick_singlequote_open  = '&#8216;'; // replacement for `
92
+    public $backtick_singlequote_close = '&#8217;'; // replacement for ' (also apostrophe)
93
+
94
+    # Other punctuation
95
+    public $em_dash = '&#8212;';
96
+    public $en_dash = '&#8211;';
97
+    public $ellipsis = '&#8230;';
98
+
99
+    ### Parser Implementation ###
100
+
101
+    public function __construct($attr = SmartyPants::ATTR_DEFAULT) {
102
+    #
103
+    # Initialize a parser with certain attributes.
104
+    #
105
+    # Parser attributes:
106
+    # 0 : do nothing
107
+    # 1 : set all
108
+    # 2 : set all, using old school en- and em- dash shortcuts
109
+    # 3 : set all, using inverted old school en and em- dash shortcuts
110
+    # 
111
+    # q : quotes
112
+    # b : backtick quotes (``double'' only)
113
+    # B : backtick quotes (``double'' and `single')
114
+    # d : dashes
115
+    # D : old school dashes
116
+    # i : inverted old school dashes
117
+    # e : ellipses
118
+    # w : convert &quot; entities to " for Dreamweaver users
119
+    #
120
+        if ($attr == "0") {
121
+            $this->do_nothing   = 1;
122
+        }
123
+        else if ($attr == "1") {
124
+            # Do everything, turn all options on.
125
+            $this->do_quotes    = 1;
126
+            $this->do_backticks = 1;
127
+            $this->do_dashes    = 1;
128
+            $this->do_ellipses  = 1;
129
+        }
130
+        else if ($attr == "2") {
131
+            # Do everything, turn all options on, use old school dash shorthand.
132
+            $this->do_quotes    = 1;
133
+            $this->do_backticks = 1;
134
+            $this->do_dashes    = 2;
135
+            $this->do_ellipses  = 1;
136
+        }
137
+        else if ($attr == "3") {
138
+            # Do everything, turn all options on, use inverted old school dash shorthand.
139
+            $this->do_quotes    = 1;
140
+            $this->do_backticks = 1;
141
+            $this->do_dashes    = 3;
142
+            $this->do_ellipses  = 1;
143
+        }
144
+        else if ($attr == "-1") {
145
+            # Special "stupefy" mode.
146
+            $this->do_stupefy   = 1;
147
+        }
148
+        else {
149
+            $chars = preg_split('//', $attr);
150
+            foreach ($chars as $c){
151
+                if      ($c == "q") { $this->do_quotes    = 1; }
152
+                else if ($c == "b") { $this->do_backticks = 1; }
153
+                else if ($c == "B") { $this->do_backticks = 2; }
154
+                else if ($c == "d") { $this->do_dashes    = 1; }
155
+                else if ($c == "D") { $this->do_dashes    = 2; }
156
+                else if ($c == "i") { $this->do_dashes    = 3; }
157
+                else if ($c == "e") { $this->do_ellipses  = 1; }
158
+                else if ($c == "w") { $this->convert_quot = 1; }
159
+                else {
160
+                    # Unknown attribute option, ignore.
161
+                }
162
+            }
163
+        }
164
+    }
165
+
166
+    public function transform($text) {
167
+
168
+        if ($this->do_nothing) {
169
+            return $text;
170
+        }
171
+
172
+        $tokens = $this->tokenizeHTML($text);
173
+        $result = '';
174
+        $in_pre = 0;  # Keep track of when we're inside <pre> or <code> tags.
175
+
176
+        $prev_token_last_char = ""; # This is a cheat, used to get some context
177
+                                    # for one-character tokens that consist of 
178
+                                    # just a quote char. What we do is remember
179
+                                    # the last character of the previous text
180
+                                    # token, to use as context to curl single-
181
+                                    # character quote tokens correctly.
182
+
183
+        foreach ($tokens as $cur_token) {
184
+            if ($cur_token[0] == "tag") {
185
+                # Don't mess with quotes inside tags.
186
+                $result .= $cur_token[1];
187
+                if (preg_match('@<(/?)(?:'.$this->tags_to_skip.')[\s>]@', $cur_token[1], $matches)) {
188
+                    $in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
189
+                }
190
+            } else {
191
+                $t = $cur_token[1];
192
+                $last_char = substr($t, -1); # Remember last char of this token before processing.
193
+                if (! $in_pre) {
194
+                    $t = $this->educate($t, $prev_token_last_char);
195
+                }
196
+                $prev_token_last_char = $last_char;
197
+                $result .= $t;
198
+            }
199
+        }
200
+
201
+        return $result;
202
+    }
203
+
204
+
205
+    function decodeEntitiesInConfiguration() {
206
+    #
207
+    #   Utility function that converts entities in configuration variables to
208
+    #   UTF-8 characters.
209
+    #
210
+        $output_config_vars = array(
211
+            'smart_doublequote_open',
212
+            'smart_doublequote_close',
213
+            'smart_singlequote_open',
214
+            'smart_singlequote_close',
215
+            'backtick_doublequote_open',
216
+            'backtick_doublequote_close',
217
+            'backtick_singlequote_open',
218
+            'backtick_singlequote_close',
219
+            'em_dash',
220
+            'en_dash',
221
+            'ellipsis',
222
+        );
223
+        foreach ($output_config_vars as $var) {
224
+            $this->$var = html_entity_decode($this->$var);
225
+        }
226
+    }
227
+
228
+
229
+    protected function educate($t, $prev_token_last_char) {
230
+        $t = $this->processEscapes($t);
231
+
232
+        if ($this->convert_quot) {
233
+            $t = preg_replace('/&quot;/', '"', $t);
234
+        }
235
+
236
+        if ($this->do_dashes) {
237
+            if ($this->do_dashes == 1) $t = $this->educateDashes($t);
238
+            if ($this->do_dashes == 2) $t = $this->educateDashesOldSchool($t);
239
+            if ($this->do_dashes == 3) $t = $this->educateDashesOldSchoolInverted($t);
240
+        }
241
+
242
+        if ($this->do_ellipses) $t = $this->educateEllipses($t);
243
+
244
+        # Note: backticks need to be processed before quotes.
245
+        if ($this->do_backticks) {
246
+            $t = $this->educateBackticks($t);
247
+            if ($this->do_backticks == 2) $t = $this->educateSingleBackticks($t);
248
+        }
249
+
250
+        if ($this->do_quotes) {
251
+            if ($t == "'") {
252
+                # Special case: single-character ' token
253
+                if (preg_match('/\S/', $prev_token_last_char)) {
254
+                    $t = $this->smart_singlequote_close;
255
+                }
256
+                else {
257
+                    $t = $this->smart_singlequote_open;
258
+                }
259
+            }
260
+            else if ($t == '"') {
261
+                # Special case: single-character " token
262
+                if (preg_match('/\S/', $prev_token_last_char)) {
263
+                    $t = $this->smart_doublequote_close;
264
+                }
265
+                else {
266
+                    $t = $this->smart_doublequote_open;
267
+                }
268
+            }
269
+            else {
270
+                # Normal case:
271
+                $t = $this->educateQuotes($t);
272
+            }
273
+        }
274
+
275
+        if ($this->do_stupefy) $t = $this->stupefyEntities($t);
276 276
 		
277
-		return $t;
278
-	}
279
-
280
-
281
-	protected function educateQuotes($_) {
282
-	#
283
-	#   Parameter:  String.
284
-	#
285
-	#   Returns:    The string, with "educated" curly quote HTML entities.
286
-	#
287
-	#   Example input:  "Isn't this fun?"
288
-	#   Example output: &#8220;Isn&#8217;t this fun?&#8221;
289
-	#
290
-		$dq_open  = $this->smart_doublequote_open;
291
-		$dq_close = $this->smart_doublequote_close;
292
-		$sq_open  = $this->smart_singlequote_open;
293
-		$sq_close = $this->smart_singlequote_close;
277
+        return $t;
278
+    }
279
+
280
+
281
+    protected function educateQuotes($_) {
282
+    #
283
+    #   Parameter:  String.
284
+    #
285
+    #   Returns:    The string, with "educated" curly quote HTML entities.
286
+    #
287
+    #   Example input:  "Isn't this fun?"
288
+    #   Example output: &#8220;Isn&#8217;t this fun?&#8221;
289
+    #
290
+        $dq_open  = $this->smart_doublequote_open;
291
+        $dq_close = $this->smart_doublequote_close;
292
+        $sq_open  = $this->smart_singlequote_open;
293
+        $sq_close = $this->smart_singlequote_close;
294 294
 	
295
-		# Make our own "punctuation" character class, because the POSIX-style
296
-		# [:PUNCT:] is only available in Perl 5.6 or later:
297
-		$punct_class = "[!\"#\\$\\%'()*+,-.\\/:;<=>?\\@\\[\\\\\]\\^_`{|}~]";
298
-
299
-		# Special case if the very first character is a quote
300
-		# followed by punctuation at a non-word-break. Close the quotes by brute force:
301
-		$_ = preg_replace(
302
-			array("/^'(?=$punct_class\\B)/", "/^\"(?=$punct_class\\B)/"),
303
-			array($sq_close,                 $dq_close), $_);
304
-
305
-		# Special case for double sets of quotes, e.g.:
306
-		#   <p>He said, "'Quoted' words in a larger quote."</p>
307
-		$_ = preg_replace(
308
-			array("/\"'(?=\w)/",     "/'\"(?=\w)/"),
309
-			array($dq_open.$sq_open, $sq_open.$dq_open), $_);
310
-
311
-		# Special case for decade abbreviations (the '80s):
312
-		$_ = preg_replace("/'(?=\\d{2}s)/", $sq_close, $_);
313
-
314
-		$close_class = '[^\ \t\r\n\[\{\(\-]';
315
-		$dec_dashes = '&\#8211;|&\#8212;';
316
-
317
-		# Get most opening single quotes:
318
-		$_ = preg_replace("{
295
+        # Make our own "punctuation" character class, because the POSIX-style
296
+        # [:PUNCT:] is only available in Perl 5.6 or later:
297
+        $punct_class = "[!\"#\\$\\%'()*+,-.\\/:;<=>?\\@\\[\\\\\]\\^_`{|}~]";
298
+
299
+        # Special case if the very first character is a quote
300
+        # followed by punctuation at a non-word-break. Close the quotes by brute force:
301
+        $_ = preg_replace(
302
+            array("/^'(?=$punct_class\\B)/", "/^\"(?=$punct_class\\B)/"),
303
+            array($sq_close,                 $dq_close), $_);
304
+
305
+        # Special case for double sets of quotes, e.g.:
306
+        #   <p>He said, "'Quoted' words in a larger quote."</p>
307
+        $_ = preg_replace(
308
+            array("/\"'(?=\w)/",     "/'\"(?=\w)/"),
309
+            array($dq_open.$sq_open, $sq_open.$dq_open), $_);
310
+
311
+        # Special case for decade abbreviations (the '80s):
312
+        $_ = preg_replace("/'(?=\\d{2}s)/", $sq_close, $_);
313
+
314
+        $close_class = '[^\ \t\r\n\[\{\(\-]';
315
+        $dec_dashes = '&\#8211;|&\#8212;';
316
+
317
+        # Get most opening single quotes:
318
+        $_ = preg_replace("{
319 319
 			(
320 320
 				\\s          |   # a whitespace char, or
321 321
 				&nbsp;      |   # a non-breaking space entity, or
@@ -327,8 +327,8 @@  discard block
 block discarded – undo
327 327
 			'                   # the quote
328 328
 			(?=\\w)              # followed by a word character
329 329
 			}x", '\1'.$sq_open, $_);
330
-		# Single closing quotes:
331
-		$_ = preg_replace("{
330
+        # Single closing quotes:
331
+        $_ = preg_replace("{
332 332
 			($close_class)?
333 333
 			'
334 334
 			(?(1)|          # If $1 captured, then do nothing;
@@ -338,12 +338,12 @@  discard block
 block discarded – undo
338 338
 							# \"<i>Custer</i>'s Last Stand.\"
339 339
 			}xi", '\1'.$sq_close, $_);
340 340
 
341
-		# Any remaining single quotes should be opening ones:
342
-		$_ = str_replace("'", $sq_open, $_);
341
+        # Any remaining single quotes should be opening ones:
342
+        $_ = str_replace("'", $sq_open, $_);
343 343
 
344 344
 
345
-		# Get most opening double quotes:
346
-		$_ = preg_replace("{
345
+        # Get most opening double quotes:
346
+        $_ = preg_replace("{
347 347
 			(
348 348
 				\\s          |   # a whitespace char, or
349 349
 				&nbsp;      |   # a non-breaking space entity, or
@@ -356,205 +356,205 @@  discard block
 block discarded – undo
356 356
 			(?=\\w)              # followed by a word character
357 357
 			}x", '\1'.$dq_open, $_);
358 358
 
359
-		# Double closing quotes:
360
-		$_ = preg_replace("{
359
+        # Double closing quotes:
360
+        $_ = preg_replace("{
361 361
 			($close_class)?
362 362
 			\"
363 363
 			(?(1)|(?=\\s))   # If $1 captured, then do nothing;
364 364
 							   # if not, then make sure the next char is whitespace.
365 365
 			}x", '\1'.$dq_close, $_);
366 366
 
367
-		# Any remaining quotes should be opening ones.
368
-		$_ = str_replace('"', $dq_open, $_);
369
-
370
-		return $_;
371
-	}
372
-
373
-
374
-	protected function educateBackticks($_) {
375
-	#
376
-	#   Parameter:  String.
377
-	#   Returns:    The string, with ``backticks'' -style double quotes
378
-	#               translated into HTML curly quote entities.
379
-	#
380
-	#   Example input:  ``Isn't this fun?''
381
-	#   Example output: &#8220;Isn't this fun?&#8221;
382
-	#
383
-
384
-		$_ = str_replace(array("``", "''",),
385
-						 array($this->backtick_doublequote_open,
386
-							   $this->backtick_doublequote_close), $_);
387
-		return $_;
388
-	}
389
-
390
-
391
-	protected function educateSingleBackticks($_) {
392
-	#
393
-	#   Parameter:  String.
394
-	#   Returns:    The string, with `backticks' -style single quotes
395
-	#               translated into HTML curly quote entities.
396
-	#
397
-	#   Example input:  `Isn't this fun?'
398
-	#   Example output: &#8216;Isn&#8217;t this fun?&#8217;
399
-	#
400
-
401
-		$_ = str_replace(array("`",       "'",),
402
-						 array($this->backtick_singlequote_open,
403
-							   $this->backtick_singlequote_close), $_);
404
-		return $_;
405
-	}
406
-
407
-
408
-	protected function educateDashes($_) {
409
-	#
410
-	#   Parameter:  String.
411
-	#
412
-	#   Returns:    The string, with each instance of "--" translated to
413
-	#               an em-dash HTML entity.
414
-	#
415
-
416
-		$_ = str_replace('--', $this->em_dash, $_);
417
-		return $_;
418
-	}
419
-
420
-
421
-	protected function educateDashesOldSchool($_) {
422
-	#
423
-	#   Parameter:  String.
424
-	#
425
-	#   Returns:    The string, with each instance of "--" translated to
426
-	#               an en-dash HTML entity, and each "---" translated to
427
-	#               an em-dash HTML entity.
428
-	#
429
-
430
-		#                      em              en
431
-		$_ = str_replace(array("---",          "--",),
432
-						 array($this->em_dash, $this->en_dash), $_);
433
-		return $_;
434
-	}
435
-
436
-
437
-	protected function educateDashesOldSchoolInverted($_) {
438
-	#
439
-	#   Parameter:  String.
440
-	#
441
-	#   Returns:    The string, with each instance of "--" translated to
442
-	#               an em-dash HTML entity, and each "---" translated to
443
-	#               an en-dash HTML entity. Two reasons why: First, unlike the
444
-	#               en- and em-dash syntax supported by
445
-	#               EducateDashesOldSchool(), it's compatible with existing
446
-	#               entries written before SmartyPants 1.1, back when "--" was
447
-	#               only used for em-dashes.  Second, em-dashes are more
448
-	#               common than en-dashes, and so it sort of makes sense that
449
-	#               the shortcut should be shorter to type. (Thanks to Aaron
450
-	#               Swartz for the idea.)
451
-	#
452
-
453
-		#                      en              em
454
-		$_ = str_replace(array("---",          "--",),
455
-						 array($this->en_dash, $this->em_dash), $_);
456
-		return $_;
457
-	}
458
-
459
-
460
-	protected function educateEllipses($_) {
461
-	#
462
-	#   Parameter:  String.
463
-	#   Returns:    The string, with each instance of "..." translated to
464
-	#               an ellipsis HTML entity. Also converts the case where
465
-	#               there are spaces between the dots.
466
-	#
467
-	#   Example input:  Huh...?
468
-	#   Example output: Huh&#8230;?
469
-	#
470
-
471
-		$_ = str_replace(array("...",     ". . .",), $this->ellipsis, $_);
472
-		return $_;
473
-	}
474
-
475
-
476
-	protected function stupefyEntities($_) {
477
-	#
478
-	#   Parameter:  String.
479
-	#   Returns:    The string, with each SmartyPants HTML entity translated to
480
-	#               its ASCII counterpart.
481
-	#
482
-	#   Example input:  &#8220;Hello &#8212; world.&#8221;
483
-	#   Example output: "Hello -- world."
484
-	#
485
-
486
-							#  en-dash    em-dash
487
-		$_ = str_replace(array('&#8211;', '&#8212;'),
488
-						 array('-',       '--'), $_);
489
-
490
-		# single quote         open       close
491
-		$_ = str_replace(array('&#8216;', '&#8217;'), "'", $_);
492
-
493
-		# double quote         open       close
494
-		$_ = str_replace(array('&#8220;', '&#8221;'), '"', $_);
495
-
496
-		$_ = str_replace('&#8230;', '...', $_); # ellipsis
497
-
498
-		return $_;
499
-	}
500
-
501
-
502
-	protected function processEscapes($_) {
503
-	#
504
-	#   Parameter:  String.
505
-	#   Returns:    The string, with after processing the following backslash
506
-	#               escape sequences. This is useful if you want to force a "dumb"
507
-	#               quote or other character to appear.
508
-	#
509
-	#               Escape  Value
510
-	#               ------  -----
511
-	#               \\      &#92;
512
-	#               \"      &#34;
513
-	#               \'      &#39;
514
-	#               \.      &#46;
515
-	#               \-      &#45;
516
-	#               \`      &#96;
517
-	#
518
-		$_ = str_replace(
519
-			array('\\\\',  '\"',    "\'",    '\.',    '\-',    '\`'),
520
-			array('&#92;', '&#34;', '&#39;', '&#46;', '&#45;', '&#96;'), $_);
521
-
522
-		return $_;
523
-	}
524
-
525
-
526
-	protected function tokenizeHTML($str) {
527
-	#
528
-	#   Parameter:  String containing HTML markup.
529
-	#   Returns:    An array of the tokens comprising the input
530
-	#               string. Each token is either a tag (possibly with nested,
531
-	#               tags contained therein, such as <a href="<MTFoo>">, or a
532
-	#               run of text between tags. Each element of the array is a
533
-	#               two-element array; the first is either 'tag' or 'text';
534
-	#               the second is the actual value.
535
-	#
536
-	#
537
-	#   Regular expression derived from the _tokenize() subroutine in 
538
-	#   Brad Choate's MTRegex plugin.
539
-	#   <http://www.bradchoate.com/past/mtregex.php>
540
-	#
541
-		$index = 0;
542
-		$tokens = array();
543
-
544
-		$match = '(?s:<!--.*?-->)|'.	# comment
545
-				 '(?s:<\?.*?\?>)|'.				# processing instruction
546
-												# regular tags
547
-				 '(?:<[/!$]?[-a-zA-Z0-9:]+\b(?>[^"\'>]+|"[^"]*"|\'[^\']*\')*>)'; 
548
-
549
-		$parts = preg_split("{($match)}", $str, -1, PREG_SPLIT_DELIM_CAPTURE);
550
-
551
-		foreach ($parts as $part) {
552
-			if (++$index % 2 && $part != '') 
553
-				$tokens[] = array('text', $part);
554
-			else
555
-				$tokens[] = array('tag', $part);
556
-		}
557
-		return $tokens;
558
-	}
367
+        # Any remaining quotes should be opening ones.
368
+        $_ = str_replace('"', $dq_open, $_);
369
+
370
+        return $_;
371
+    }
372
+
373
+
374
+    protected function educateBackticks($_) {
375
+    #
376
+    #   Parameter:  String.
377
+    #   Returns:    The string, with ``backticks'' -style double quotes
378
+    #               translated into HTML curly quote entities.
379
+    #
380
+    #   Example input:  ``Isn't this fun?''
381
+    #   Example output: &#8220;Isn't this fun?&#8221;
382
+    #
383
+
384
+        $_ = str_replace(array("``", "''",),
385
+                            array($this->backtick_doublequote_open,
386
+                                $this->backtick_doublequote_close), $_);
387
+        return $_;
388
+    }
389
+
390
+
391
+    protected function educateSingleBackticks($_) {
392
+    #
393
+    #   Parameter:  String.
394
+    #   Returns:    The string, with `backticks' -style single quotes
395
+    #               translated into HTML curly quote entities.
396
+    #
397
+    #   Example input:  `Isn't this fun?'
398
+    #   Example output: &#8216;Isn&#8217;t this fun?&#8217;
399
+    #
400
+
401
+        $_ = str_replace(array("`",       "'",),
402
+                            array($this->backtick_singlequote_open,
403
+                                $this->backtick_singlequote_close), $_);
404
+        return $_;
405
+    }
406
+
407
+
408
+    protected function educateDashes($_) {
409
+    #
410
+    #   Parameter:  String.
411
+    #
412
+    #   Returns:    The string, with each instance of "--" translated to
413
+    #               an em-dash HTML entity.
414
+    #
415
+
416
+        $_ = str_replace('--', $this->em_dash, $_);
417
+        return $_;
418
+    }
419
+
420
+
421
+    protected function educateDashesOldSchool($_) {
422
+    #
423
+    #   Parameter:  String.
424
+    #
425
+    #   Returns:    The string, with each instance of "--" translated to
426
+    #               an en-dash HTML entity, and each "---" translated to
427
+    #               an em-dash HTML entity.
428
+    #
429
+
430
+        #                      em              en
431
+        $_ = str_replace(array("---",          "--",),
432
+                            array($this->em_dash, $this->en_dash), $_);
433
+        return $_;
434
+    }
435
+
436
+
437
+    protected function educateDashesOldSchoolInverted($_) {
438
+    #
439
+    #   Parameter:  String.
440
+    #
441
+    #   Returns:    The string, with each instance of "--" translated to
442
+    #               an em-dash HTML entity, and each "---" translated to
443
+    #               an en-dash HTML entity. Two reasons why: First, unlike the
444
+    #               en- and em-dash syntax supported by
445
+    #               EducateDashesOldSchool(), it's compatible with existing
446
+    #               entries written before SmartyPants 1.1, back when "--" was
447
+    #               only used for em-dashes.  Second, em-dashes are more
448
+    #               common than en-dashes, and so it sort of makes sense that
449
+    #               the shortcut should be shorter to type. (Thanks to Aaron
450
+    #               Swartz for the idea.)
451
+    #
452
+
453
+        #                      en              em
454
+        $_ = str_replace(array("---",          "--",),
455
+                            array($this->en_dash, $this->em_dash), $_);
456
+        return $_;
457
+    }
458
+
459
+
460
+    protected function educateEllipses($_) {
461
+    #
462
+    #   Parameter:  String.
463
+    #   Returns:    The string, with each instance of "..." translated to
464
+    #               an ellipsis HTML entity. Also converts the case where
465
+    #               there are spaces between the dots.
466
+    #
467
+    #   Example input:  Huh...?
468
+    #   Example output: Huh&#8230;?
469
+    #
470
+
471
+        $_ = str_replace(array("...",     ". . .",), $this->ellipsis, $_);
472
+        return $_;
473
+    }
474
+
475
+
476
+    protected function stupefyEntities($_) {
477
+    #
478
+    #   Parameter:  String.
479
+    #   Returns:    The string, with each SmartyPants HTML entity translated to
480
+    #               its ASCII counterpart.
481
+    #
482
+    #   Example input:  &#8220;Hello &#8212; world.&#8221;
483
+    #   Example output: "Hello -- world."
484
+    #
485
+
486
+                            #  en-dash    em-dash
487
+        $_ = str_replace(array('&#8211;', '&#8212;'),
488
+                            array('-',       '--'), $_);
489
+
490
+        # single quote         open       close
491
+        $_ = str_replace(array('&#8216;', '&#8217;'), "'", $_);
492
+
493
+        # double quote         open       close
494
+        $_ = str_replace(array('&#8220;', '&#8221;'), '"', $_);
495
+
496
+        $_ = str_replace('&#8230;', '...', $_); # ellipsis
497
+
498
+        return $_;
499
+    }
500
+
501
+
502
+    protected function processEscapes($_) {
503
+    #
504
+    #   Parameter:  String.
505
+    #   Returns:    The string, with after processing the following backslash
506
+    #               escape sequences. This is useful if you want to force a "dumb"
507
+    #               quote or other character to appear.
508
+    #
509
+    #               Escape  Value
510
+    #               ------  -----
511
+    #               \\      &#92;
512
+    #               \"      &#34;
513
+    #               \'      &#39;
514
+    #               \.      &#46;
515
+    #               \-      &#45;
516
+    #               \`      &#96;
517
+    #
518
+        $_ = str_replace(
519
+            array('\\\\',  '\"',    "\'",    '\.',    '\-',    '\`'),
520
+            array('&#92;', '&#34;', '&#39;', '&#46;', '&#45;', '&#96;'), $_);
521
+
522
+        return $_;
523
+    }
524
+
525
+
526
+    protected function tokenizeHTML($str) {
527
+    #
528
+    #   Parameter:  String containing HTML markup.
529
+    #   Returns:    An array of the tokens comprising the input
530
+    #               string. Each token is either a tag (possibly with nested,
531
+    #               tags contained therein, such as <a href="<MTFoo>">, or a
532
+    #               run of text between tags. Each element of the array is a
533
+    #               two-element array; the first is either 'tag' or 'text';
534
+    #               the second is the actual value.
535
+    #
536
+    #
537
+    #   Regular expression derived from the _tokenize() subroutine in 
538
+    #   Brad Choate's MTRegex plugin.
539
+    #   <http://www.bradchoate.com/past/mtregex.php>
540
+    #
541
+        $index = 0;
542
+        $tokens = array();
543
+
544
+        $match = '(?s:<!--.*?-->)|'.	# comment
545
+                    '(?s:<\?.*?\?>)|'.				# processing instruction
546
+                                                # regular tags
547
+                    '(?:<[/!$]?[-a-zA-Z0-9:]+\b(?>[^"\'>]+|"[^"]*"|\'[^\']*\')*>)'; 
548
+
549
+        $parts = preg_split("{($match)}", $str, -1, PREG_SPLIT_DELIM_CAPTURE);
550
+
551
+        foreach ($parts as $part) {
552
+            if (++$index % 2 && $part != '') 
553
+                $tokens[] = array('text', $part);
554
+            else
555
+                $tokens[] = array('tag', $part);
556
+        }
557
+        return $tokens;
558
+    }
559 559
 
560 560
 }
Please login to merge, or discard this patch.
Spacing   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -21,24 +21,24 @@  discard block
 block discarded – undo
21 21
 
22 22
 	### Version ###
23 23
 
24
-	const  SMARTYPANTSLIB_VERSION  =  "1.8.1";
24
+	const  SMARTYPANTSLIB_VERSION = "1.8.1";
25 25
 
26 26
 
27 27
 	### Presets
28 28
 
29 29
 	# SmartyPants does nothing at all
30
-	const  ATTR_DO_NOTHING             =  0;
30
+	const  ATTR_DO_NOTHING             = 0;
31 31
 	# "--" for em-dashes; no en-dash support
32
-	const  ATTR_EM_DASH                =  1;
32
+	const  ATTR_EM_DASH                = 1;
33 33
 	# "---" for em-dashes; "--" for en-dashes
34
-	const  ATTR_LONG_EM_DASH_SHORT_EN  =  2;
34
+	const  ATTR_LONG_EM_DASH_SHORT_EN  = 2;
35 35
 	# "--" for em-dashes; "---" for en-dashes
36
-	const  ATTR_SHORT_EM_DASH_LONG_EN  =  3;
36
+	const  ATTR_SHORT_EM_DASH_LONG_EN  = 3;
37 37
 	# "--" for em-dashes; "---" for en-dashes
38 38
 	const  ATTR_STUPEFY                = -1;
39 39
 
40 40
 	# The default preset: ATTR_EM_DASH
41
-	const  ATTR_DEFAULT  =  SmartyPants::ATTR_EM_DASH;
41
+	const  ATTR_DEFAULT = SmartyPants::ATTR_EM_DASH;
42 42
 
43 43
 
44 44
 	### Standard Function Interface ###
@@ -53,7 +53,7 @@  discard block
 block discarded – undo
53 53
 
54 54
 		# try to take parser from the static parser list
55 55
 		static $parser_list;
56
-		$parser =& $parser_list[$parser_class][$attr];
56
+		$parser = & $parser_list[$parser_class][$attr];
57 57
 
58 58
 		# create the parser if not already set
59 59
 		if (!$parser)
@@ -118,7 +118,7 @@  discard block
 block discarded – undo
118 118
 	# w : convert &quot; entities to " for Dreamweaver users
119 119
 	#
120 120
 		if ($attr == "0") {
121
-			$this->do_nothing   = 1;
121
+			$this->do_nothing = 1;
122 122
 		}
123 123
 		else if ($attr == "1") {
124 124
 			# Do everything, turn all options on.
@@ -143,12 +143,12 @@  discard block
 block discarded – undo
143 143
 		}
144 144
 		else if ($attr == "-1") {
145 145
 			# Special "stupefy" mode.
146
-			$this->do_stupefy   = 1;
146
+			$this->do_stupefy = 1;
147 147
 		}
148 148
 		else {
149 149
 			$chars = preg_split('//', $attr);
150
-			foreach ($chars as $c){
151
-				if      ($c == "q") { $this->do_quotes    = 1; }
150
+			foreach ($chars as $c) {
151
+				if ($c == "q") { $this->do_quotes    = 1; }
152 152
 				else if ($c == "b") { $this->do_backticks = 1; }
153 153
 				else if ($c == "B") { $this->do_backticks = 2; }
154 154
 				else if ($c == "d") { $this->do_dashes    = 1; }
@@ -171,7 +171,7 @@  discard block
 block discarded – undo
171 171
 
172 172
 		$tokens = $this->tokenizeHTML($text);
173 173
 		$result = '';
174
-		$in_pre = 0;  # Keep track of when we're inside <pre> or <code> tags.
174
+		$in_pre = 0; # Keep track of when we're inside <pre> or <code> tags.
175 175
 
176 176
 		$prev_token_last_char = ""; # This is a cheat, used to get some context
177 177
 									# for one-character tokens that consist of 
@@ -184,13 +184,13 @@  discard block
 block discarded – undo
184 184
 			if ($cur_token[0] == "tag") {
185 185
 				# Don't mess with quotes inside tags.
186 186
 				$result .= $cur_token[1];
187
-				if (preg_match('@<(/?)(?:'.$this->tags_to_skip.')[\s>]@', $cur_token[1], $matches)) {
187
+				if (preg_match('@<(/?)(?:' . $this->tags_to_skip . ')[\s>]@', $cur_token[1], $matches)) {
188 188
 					$in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
189 189
 				}
190 190
 			} else {
191 191
 				$t = $cur_token[1];
192 192
 				$last_char = substr($t, -1); # Remember last char of this token before processing.
193
-				if (! $in_pre) {
193
+				if (!$in_pre) {
194 194
 					$t = $this->educate($t, $prev_token_last_char);
195 195
 				}
196 196
 				$prev_token_last_char = $last_char;
@@ -300,13 +300,13 @@  discard block
 block discarded – undo
300 300
 		# followed by punctuation at a non-word-break. Close the quotes by brute force:
301 301
 		$_ = preg_replace(
302 302
 			array("/^'(?=$punct_class\\B)/", "/^\"(?=$punct_class\\B)/"),
303
-			array($sq_close,                 $dq_close), $_);
303
+			array($sq_close, $dq_close), $_);
304 304
 
305 305
 		# Special case for double sets of quotes, e.g.:
306 306
 		#   <p>He said, "'Quoted' words in a larger quote."</p>
307 307
 		$_ = preg_replace(
308
-			array("/\"'(?=\w)/",     "/'\"(?=\w)/"),
309
-			array($dq_open.$sq_open, $sq_open.$dq_open), $_);
308
+			array("/\"'(?=\w)/", "/'\"(?=\w)/"),
309
+			array($dq_open . $sq_open, $sq_open . $dq_open), $_);
310 310
 
311 311
 		# Special case for decade abbreviations (the '80s):
312 312
 		$_ = preg_replace("/'(?=\\d{2}s)/", $sq_close, $_);
@@ -326,7 +326,7 @@  discard block
 block discarded – undo
326 326
 			)
327 327
 			'                   # the quote
328 328
 			(?=\\w)              # followed by a word character
329
-			}x", '\1'.$sq_open, $_);
329
+			}x", '\1' . $sq_open, $_);
330 330
 		# Single closing quotes:
331 331
 		$_ = preg_replace("{
332 332
 			($close_class)?
@@ -336,7 +336,7 @@  discard block
 block discarded – undo
336 336
 			)               # char or an 's' at a word ending position. This
337 337
 							# is a special case to handle something like:
338 338
 							# \"<i>Custer</i>'s Last Stand.\"
339
-			}xi", '\1'.$sq_close, $_);
339
+			}xi", '\1' . $sq_close, $_);
340 340
 
341 341
 		# Any remaining single quotes should be opening ones:
342 342
 		$_ = str_replace("'", $sq_open, $_);
@@ -354,7 +354,7 @@  discard block
 block discarded – undo
354 354
 			)
355 355
 			\"                   # the quote
356 356
 			(?=\\w)              # followed by a word character
357
-			}x", '\1'.$dq_open, $_);
357
+			}x", '\1' . $dq_open, $_);
358 358
 
359 359
 		# Double closing quotes:
360 360
 		$_ = preg_replace("{
@@ -362,7 +362,7 @@  discard block
 block discarded – undo
362 362
 			\"
363 363
 			(?(1)|(?=\\s))   # If $1 captured, then do nothing;
364 364
 							   # if not, then make sure the next char is whitespace.
365
-			}x", '\1'.$dq_close, $_);
365
+			}x", '\1' . $dq_close, $_);
366 366
 
367 367
 		# Any remaining quotes should be opening ones.
368 368
 		$_ = str_replace('"', $dq_open, $_);
@@ -398,7 +398,7 @@  discard block
 block discarded – undo
398 398
 	#   Example output: &#8216;Isn&#8217;t this fun?&#8217;
399 399
 	#
400 400
 
401
-		$_ = str_replace(array("`",       "'",),
401
+		$_ = str_replace(array("`", "'",),
402 402
 						 array($this->backtick_singlequote_open,
403 403
 							   $this->backtick_singlequote_close), $_);
404 404
 		return $_;
@@ -428,7 +428,7 @@  discard block
 block discarded – undo
428 428
 	#
429 429
 
430 430
 		#                      em              en
431
-		$_ = str_replace(array("---",          "--",),
431
+		$_ = str_replace(array("---", "--",),
432 432
 						 array($this->em_dash, $this->en_dash), $_);
433 433
 		return $_;
434 434
 	}
@@ -451,7 +451,7 @@  discard block
 block discarded – undo
451 451
 	#
452 452
 
453 453
 		#                      en              em
454
-		$_ = str_replace(array("---",          "--",),
454
+		$_ = str_replace(array("---", "--",),
455 455
 						 array($this->en_dash, $this->em_dash), $_);
456 456
 		return $_;
457 457
 	}
@@ -468,7 +468,7 @@  discard block
 block discarded – undo
468 468
 	#   Example output: Huh&#8230;?
469 469
 	#
470 470
 
471
-		$_ = str_replace(array("...",     ". . .",), $this->ellipsis, $_);
471
+		$_ = str_replace(array("...", ". . .",), $this->ellipsis, $_);
472 472
 		return $_;
473 473
 	}
474 474
 
@@ -485,7 +485,7 @@  discard block
 block discarded – undo
485 485
 
486 486
 							#  en-dash    em-dash
487 487
 		$_ = str_replace(array('&#8211;', '&#8212;'),
488
-						 array('-',       '--'), $_);
488
+						 array('-', '--'), $_);
489 489
 
490 490
 		# single quote         open       close
491 491
 		$_ = str_replace(array('&#8216;', '&#8217;'), "'", $_);
@@ -516,7 +516,7 @@  discard block
 block discarded – undo
516 516
 	#               \`      &#96;
517 517
 	#
518 518
 		$_ = str_replace(
519
-			array('\\\\',  '\"',    "\'",    '\.',    '\-',    '\`'),
519
+			array('\\\\', '\"', "\'", '\.', '\-', '\`'),
520 520
 			array('&#92;', '&#34;', '&#39;', '&#46;', '&#45;', '&#96;'), $_);
521 521
 
522 522
 		return $_;
@@ -541,15 +541,15 @@  discard block
 block discarded – undo
541 541
 		$index = 0;
542 542
 		$tokens = array();
543 543
 
544
-		$match = '(?s:<!--.*?-->)|'.	# comment
545
-				 '(?s:<\?.*?\?>)|'.				# processing instruction
544
+		$match = '(?s:<!--.*?-->)|' . # comment
545
+				 '(?s:<\?.*?\?>)|' . # processing instruction
546 546
 												# regular tags
547 547
 				 '(?:<[/!$]?[-a-zA-Z0-9:]+\b(?>[^"\'>]+|"[^"]*"|\'[^\']*\')*>)'; 
548 548
 
549 549
 		$parts = preg_split("{($match)}", $str, -1, PREG_SPLIT_DELIM_CAPTURE);
550 550
 
551 551
 		foreach ($parts as $part) {
552
-			if (++$index % 2 && $part != '') 
552
+			if (++$index%2 && $part != '') 
553 553
 				$tokens[] = array('text', $part);
554 554
 			else
555 555
 				$tokens[] = array('tag', $part);
Please login to merge, or discard this patch.
Braces   +36 added lines, -39 removed lines patch added patch discarded remove patch
@@ -56,8 +56,9 @@  discard block
 block discarded – undo
56 56
 		$parser =& $parser_list[$parser_class][$attr];
57 57
 
58 58
 		# create the parser if not already set
59
-		if (!$parser)
60
-			$parser = new $parser_class($attr);
59
+		if (!$parser) {
60
+					$parser = new $parser_class($attr);
61
+		}
61 62
 
62 63
 		# Transform text using parser.
63 64
 		return $parser->transform($text);
@@ -119,44 +120,31 @@  discard block
 block discarded – undo
119 120
 	#
120 121
 		if ($attr == "0") {
121 122
 			$this->do_nothing   = 1;
122
-		}
123
-		else if ($attr == "1") {
123
+		} else if ($attr == "1") {
124 124
 			# Do everything, turn all options on.
125 125
 			$this->do_quotes    = 1;
126 126
 			$this->do_backticks = 1;
127 127
 			$this->do_dashes    = 1;
128 128
 			$this->do_ellipses  = 1;
129
-		}
130
-		else if ($attr == "2") {
129
+		} else if ($attr == "2") {
131 130
 			# Do everything, turn all options on, use old school dash shorthand.
132 131
 			$this->do_quotes    = 1;
133 132
 			$this->do_backticks = 1;
134 133
 			$this->do_dashes    = 2;
135 134
 			$this->do_ellipses  = 1;
136
-		}
137
-		else if ($attr == "3") {
135
+		} else if ($attr == "3") {
138 136
 			# Do everything, turn all options on, use inverted old school dash shorthand.
139 137
 			$this->do_quotes    = 1;
140 138
 			$this->do_backticks = 1;
141 139
 			$this->do_dashes    = 3;
142 140
 			$this->do_ellipses  = 1;
143
-		}
144
-		else if ($attr == "-1") {
141
+		} else if ($attr == "-1") {
145 142
 			# Special "stupefy" mode.
146 143
 			$this->do_stupefy   = 1;
147
-		}
148
-		else {
144
+		} else {
149 145
 			$chars = preg_split('//', $attr);
150 146
 			foreach ($chars as $c){
151
-				if      ($c == "q") { $this->do_quotes    = 1; }
152
-				else if ($c == "b") { $this->do_backticks = 1; }
153
-				else if ($c == "B") { $this->do_backticks = 2; }
154
-				else if ($c == "d") { $this->do_dashes    = 1; }
155
-				else if ($c == "D") { $this->do_dashes    = 2; }
156
-				else if ($c == "i") { $this->do_dashes    = 3; }
157
-				else if ($c == "e") { $this->do_ellipses  = 1; }
158
-				else if ($c == "w") { $this->convert_quot = 1; }
159
-				else {
147
+				if      ($c == "q") { $this->do_quotes    = 1; } else if ($c == "b") { $this->do_backticks = 1; } else if ($c == "B") { $this->do_backticks = 2; } else if ($c == "d") { $this->do_dashes    = 1; } else if ($c == "D") { $this->do_dashes    = 2; } else if ($c == "i") { $this->do_dashes    = 3; } else if ($c == "e") { $this->do_ellipses  = 1; } else if ($c == "w") { $this->convert_quot = 1; } else {
160 148
 					# Unknown attribute option, ignore.
161 149
 				}
162 150
 			}
@@ -234,17 +222,27 @@  discard block
 block discarded – undo
234 222
 		}
235 223
 
236 224
 		if ($this->do_dashes) {
237
-			if ($this->do_dashes == 1) $t = $this->educateDashes($t);
238
-			if ($this->do_dashes == 2) $t = $this->educateDashesOldSchool($t);
239
-			if ($this->do_dashes == 3) $t = $this->educateDashesOldSchoolInverted($t);
225
+			if ($this->do_dashes == 1) {
226
+			    $t = $this->educateDashes($t);
227
+			}
228
+			if ($this->do_dashes == 2) {
229
+			    $t = $this->educateDashesOldSchool($t);
230
+			}
231
+			if ($this->do_dashes == 3) {
232
+			    $t = $this->educateDashesOldSchoolInverted($t);
233
+			}
240 234
 		}
241 235
 
242
-		if ($this->do_ellipses) $t = $this->educateEllipses($t);
236
+		if ($this->do_ellipses) {
237
+		    $t = $this->educateEllipses($t);
238
+		}
243 239
 
244 240
 		# Note: backticks need to be processed before quotes.
245 241
 		if ($this->do_backticks) {
246 242
 			$t = $this->educateBackticks($t);
247
-			if ($this->do_backticks == 2) $t = $this->educateSingleBackticks($t);
243
+			if ($this->do_backticks == 2) {
244
+			    $t = $this->educateSingleBackticks($t);
245
+			}
248 246
 		}
249 247
 
250 248
 		if ($this->do_quotes) {
@@ -252,27 +250,25 @@  discard block
 block discarded – undo
252 250
 				# Special case: single-character ' token
253 251
 				if (preg_match('/\S/', $prev_token_last_char)) {
254 252
 					$t = $this->smart_singlequote_close;
255
-				}
256
-				else {
253
+				} else {
257 254
 					$t = $this->smart_singlequote_open;
258 255
 				}
259
-			}
260
-			else if ($t == '"') {
256
+			} else if ($t == '"') {
261 257
 				# Special case: single-character " token
262 258
 				if (preg_match('/\S/', $prev_token_last_char)) {
263 259
 					$t = $this->smart_doublequote_close;
264
-				}
265
-				else {
260
+				} else {
266 261
 					$t = $this->smart_doublequote_open;
267 262
 				}
268
-			}
269
-			else {
263
+			} else {
270 264
 				# Normal case:
271 265
 				$t = $this->educateQuotes($t);
272 266
 			}
273 267
 		}
274 268
 
275
-		if ($this->do_stupefy) $t = $this->stupefyEntities($t);
269
+		if ($this->do_stupefy) {
270
+		    $t = $this->stupefyEntities($t);
271
+		}
276 272
 		
277 273
 		return $t;
278 274
 	}
@@ -549,10 +545,11 @@  discard block
 block discarded – undo
549 545
 		$parts = preg_split("{($match)}", $str, -1, PREG_SPLIT_DELIM_CAPTURE);
550 546
 
551 547
 		foreach ($parts as $part) {
552
-			if (++$index % 2 && $part != '') 
553
-				$tokens[] = array('text', $part);
554
-			else
555
-				$tokens[] = array('tag', $part);
548
+			if (++$index % 2 && $part != '') {
549
+							$tokens[] = array('text', $part);
550
+			} else {
551
+							$tokens[] = array('tag', $part);
552
+			}
556 553
 		}
557 554
 		return $tokens;
558 555
 	}
Please login to merge, or discard this patch.
a/vendor/michelf/php-smartypants/Michelf/SmartyPantsTypographer.php 3 patches
Indentation   +422 added lines, -422 removed lines patch added patch discarded remove patch
@@ -18,374 +18,374 @@  discard block
 block discarded – undo
18 18
 #
19 19
 class SmartyPantsTypographer extends \Michelf\SmartyPants {
20 20
 
21
-	### Configuration Variables ###
22
-
23
-	# Options to specify which transformations to make:
24
-	public $do_comma_quotes      = 0;
25
-	public $do_guillemets        = 0;
26
-	public $do_geresh_gershayim  = 0;
27
-	public $do_space_emdash      = 0;
28
-	public $do_space_endash      = 0;
29
-	public $do_space_colon       = 0;
30
-	public $do_space_semicolon   = 0;
31
-	public $do_space_marks       = 0;
32
-	public $do_space_frenchquote = 0;
33
-	public $do_space_thousand    = 0;
34
-	public $do_space_unit        = 0;
35
-
36
-	# Quote characters for replacing ASCII approximations
37
-	public $doublequote_low         = "&#8222;"; // replacement for ,,
38
-	public $guillemet_leftpointing  = "&#171;"; // replacement for <<
39
-	public $guillemet_rightpointing = "&#187;"; // replacement for >>
40
-	public $geresh    = "&#1523;";
41
-	public $gershayim = "&#1524;";
42
-
43
-	# Space characters for different places:
44
-	# Space around em-dashes.  "He_—_or she_—_should change that."
45
-	public $space_emdash      = " ";
46
-	# Space around en-dashes.  "He_–_or she_–_should change that."
47
-	public $space_endash      = " ";
48
-	# Space before a colon. "He said_: here it is."
49
-	public $space_colon       = "&#160;";
50
-	# Space before a semicolon. "That's what I said_; that's what he said."
51
-	public $space_semicolon   = "&#160;";
52
-	# Space before a question mark and an exclamation mark: "¡_Holà_! What_?"
53
-	public $space_marks       = "&#160;";
54
-	# Space inside french quotes. "Voici la «_chose_» qui m'a attaqué."
55
-	public $space_frenchquote = "&#160;";
56
-	# Space as thousand separator. "On compte 10_000 maisons sur cette liste."
57
-	public $space_thousand    = "&#160;";
58
-	# Space before a unit abreviation. "This 12_kg of matter costs 10_$."
59
-	public $space_unit        = "&#160;";
21
+    ### Configuration Variables ###
22
+
23
+    # Options to specify which transformations to make:
24
+    public $do_comma_quotes      = 0;
25
+    public $do_guillemets        = 0;
26
+    public $do_geresh_gershayim  = 0;
27
+    public $do_space_emdash      = 0;
28
+    public $do_space_endash      = 0;
29
+    public $do_space_colon       = 0;
30
+    public $do_space_semicolon   = 0;
31
+    public $do_space_marks       = 0;
32
+    public $do_space_frenchquote = 0;
33
+    public $do_space_thousand    = 0;
34
+    public $do_space_unit        = 0;
35
+
36
+    # Quote characters for replacing ASCII approximations
37
+    public $doublequote_low         = "&#8222;"; // replacement for ,,
38
+    public $guillemet_leftpointing  = "&#171;"; // replacement for <<
39
+    public $guillemet_rightpointing = "&#187;"; // replacement for >>
40
+    public $geresh    = "&#1523;";
41
+    public $gershayim = "&#1524;";
42
+
43
+    # Space characters for different places:
44
+    # Space around em-dashes.  "He_—_or she_—_should change that."
45
+    public $space_emdash      = " ";
46
+    # Space around en-dashes.  "He_–_or she_–_should change that."
47
+    public $space_endash      = " ";
48
+    # Space before a colon. "He said_: here it is."
49
+    public $space_colon       = "&#160;";
50
+    # Space before a semicolon. "That's what I said_; that's what he said."
51
+    public $space_semicolon   = "&#160;";
52
+    # Space before a question mark and an exclamation mark: "¡_Holà_! What_?"
53
+    public $space_marks       = "&#160;";
54
+    # Space inside french quotes. "Voici la «_chose_» qui m'a attaqué."
55
+    public $space_frenchquote = "&#160;";
56
+    # Space as thousand separator. "On compte 10_000 maisons sur cette liste."
57
+    public $space_thousand    = "&#160;";
58
+    # Space before a unit abreviation. "This 12_kg of matter costs 10_$."
59
+    public $space_unit        = "&#160;";
60 60
 
61 61
 	
62
-	# Expression of a space (breakable or not):
63
-	public $space = '(?: | |&nbsp;|&#0*160;|&#x0*[aA]0;)';
64
-
65
-
66
-	### Parser Implementation ###
67
-
68
-	public function __construct($attr = SmartyPants::ATTR_DEFAULT) {
69
-	#
70
-	# Initialize a SmartyPantsTypographer_Parser with certain attributes.
71
-	#
72
-	# Parser attributes:
73
-	# 0 : do nothing
74
-	# 1 : set all, except dash spacing
75
-	# 2 : set all, except dash spacing, using old school en- and em- dash shortcuts
76
-	# 3 : set all, except dash spacing, using inverted old school en and em- dash shortcuts
77
-	# 
78
-	# Punctuation:
79
-	# q -> quotes
80
-	# b -> backtick quotes (``double'' only)
81
-	# B -> backtick quotes (``double'' and `single')
82
-	# c -> comma quotes (,,double`` only)
83
-	# g -> guillemets (<<double>> only)
84
-	# d -> dashes
85
-	# D -> old school dashes
86
-	# i -> inverted old school dashes
87
-	# e -> ellipses
88
-	# w -> convert &quot; entities to " for Dreamweaver users
89
-	#
90
-	# Spacing:
91
-	# : -> colon spacing +-
92
-	# ; -> semicolon spacing +-
93
-	# m -> question and exclamation marks spacing +-
94
-	# h -> em-dash spacing +-
95
-	# H -> en-dash spacing +-
96
-	# f -> french quote spacing +-
97
-	# t -> thousand separator spacing -
98
-	# u -> unit spacing +-
99
-	#   (you can add a plus sign after some of these options denoted by + to 
100
-	#    add the space when it is not already present, or you can add a minus 
101
-	#    sign to completly remove any space present)
102
-	#
103
-		# Initialize inherited SmartyPants parser.
104
-		parent::__construct($attr);
62
+    # Expression of a space (breakable or not):
63
+    public $space = '(?: | |&nbsp;|&#0*160;|&#x0*[aA]0;)';
64
+
65
+
66
+    ### Parser Implementation ###
67
+
68
+    public function __construct($attr = SmartyPants::ATTR_DEFAULT) {
69
+    #
70
+    # Initialize a SmartyPantsTypographer_Parser with certain attributes.
71
+    #
72
+    # Parser attributes:
73
+    # 0 : do nothing
74
+    # 1 : set all, except dash spacing
75
+    # 2 : set all, except dash spacing, using old school en- and em- dash shortcuts
76
+    # 3 : set all, except dash spacing, using inverted old school en and em- dash shortcuts
77
+    # 
78
+    # Punctuation:
79
+    # q -> quotes
80
+    # b -> backtick quotes (``double'' only)
81
+    # B -> backtick quotes (``double'' and `single')
82
+    # c -> comma quotes (,,double`` only)
83
+    # g -> guillemets (<<double>> only)
84
+    # d -> dashes
85
+    # D -> old school dashes
86
+    # i -> inverted old school dashes
87
+    # e -> ellipses
88
+    # w -> convert &quot; entities to " for Dreamweaver users
89
+    #
90
+    # Spacing:
91
+    # : -> colon spacing +-
92
+    # ; -> semicolon spacing +-
93
+    # m -> question and exclamation marks spacing +-
94
+    # h -> em-dash spacing +-
95
+    # H -> en-dash spacing +-
96
+    # f -> french quote spacing +-
97
+    # t -> thousand separator spacing -
98
+    # u -> unit spacing +-
99
+    #   (you can add a plus sign after some of these options denoted by + to 
100
+    #    add the space when it is not already present, or you can add a minus 
101
+    #    sign to completly remove any space present)
102
+    #
103
+        # Initialize inherited SmartyPants parser.
104
+        parent::__construct($attr);
105 105
 				
106
-		if ($attr == "1" || $attr == "2" || $attr == "3") {
107
-			# Do everything, turn all options on.
108
-			$this->do_comma_quotes      = 1;
109
-			$this->do_guillemets        = 1;
110
-			$this->do_geresh_gershayim  = 1;
111
-			$this->do_space_emdash      = 1;
112
-			$this->do_space_endash      = 1;
113
-			$this->do_space_colon       = 1;
114
-			$this->do_space_semicolon   = 1;
115
-			$this->do_space_marks       = 1;
116
-			$this->do_space_frenchquote = 1;
117
-			$this->do_space_thousand    = 1;
118
-			$this->do_space_unit        = 1;
119
-		}
120
-		else if ($attr == "-1") {
121
-			# Special "stupefy" mode.
122
-			$this->do_stupefy   = 1;
123
-		}
124
-		else {
125
-			$chars = preg_split('//', $attr);
126
-			foreach ($chars as $c){
127
-				if      ($c == "c") { $current =& $this->do_comma_quotes; }
128
-				else if ($c == "g") { $current =& $this->do_guillemets; }
129
-				else if ($c == "G") { $current =& $this->do_geresh_gershayim; }
130
-				else if ($c == ":") { $current =& $this->do_space_colon; }
131
-				else if ($c == ";") { $current =& $this->do_space_semicolon; }
132
-				else if ($c == "m") { $current =& $this->do_space_marks; }
133
-				else if ($c == "h") { $current =& $this->do_space_emdash; }
134
-				else if ($c == "H") { $current =& $this->do_space_endash; }
135
-				else if ($c == "f") { $current =& $this->do_space_frenchquote; }
136
-				else if ($c == "t") { $current =& $this->do_space_thousand; }
137
-				else if ($c == "u") { $current =& $this->do_space_unit; }
138
-				else if ($c == "+") {
139
-					$current = 2;
140
-					unset($current);
141
-				}
142
-				else if ($c == "-") {
143
-					$current = -1;
144
-					unset($current);
145
-				}
146
-				else {
147
-					# Unknown attribute option, ignore.
148
-				}
149
-				$current = 1;
150
-			}
151
-		}
152
-	}
153
-
154
-
155
-	function decodeEntitiesInConfiguration() {
156
-		parent::decodeEntitiesInConfiguration();
157
-		$output_config_vars = array(
158
-			'doublequote_low',
159
-			'guillemet_leftpointing',
160
-			'guillemet_rightpointing',
161
-			'space_emdash',
162
-			'space_endash',
163
-			'space_colon',
164
-			'space_semicolon',
165
-			'space_marks',
166
-			'space_frenchquote',
167
-			'space_thousand',
168
-			'space_unit',
169
-		);
170
-		foreach ($output_config_vars as $var) {
171
-			$this->$var = html_entity_decode($this->$var);
172
-		}
173
-	}
174
-
175
-
176
-	function educate($t, $prev_token_last_char) {
177
-		# must happen before regular smart quotes
178
-		if ($this->do_geresh_gershayim)  $t = $this->educateGereshGershayim($t);
179
-
180
-		$t = parent::educate($t, $prev_token_last_char);
106
+        if ($attr == "1" || $attr == "2" || $attr == "3") {
107
+            # Do everything, turn all options on.
108
+            $this->do_comma_quotes      = 1;
109
+            $this->do_guillemets        = 1;
110
+            $this->do_geresh_gershayim  = 1;
111
+            $this->do_space_emdash      = 1;
112
+            $this->do_space_endash      = 1;
113
+            $this->do_space_colon       = 1;
114
+            $this->do_space_semicolon   = 1;
115
+            $this->do_space_marks       = 1;
116
+            $this->do_space_frenchquote = 1;
117
+            $this->do_space_thousand    = 1;
118
+            $this->do_space_unit        = 1;
119
+        }
120
+        else if ($attr == "-1") {
121
+            # Special "stupefy" mode.
122
+            $this->do_stupefy   = 1;
123
+        }
124
+        else {
125
+            $chars = preg_split('//', $attr);
126
+            foreach ($chars as $c){
127
+                if      ($c == "c") { $current =& $this->do_comma_quotes; }
128
+                else if ($c == "g") { $current =& $this->do_guillemets; }
129
+                else if ($c == "G") { $current =& $this->do_geresh_gershayim; }
130
+                else if ($c == ":") { $current =& $this->do_space_colon; }
131
+                else if ($c == ";") { $current =& $this->do_space_semicolon; }
132
+                else if ($c == "m") { $current =& $this->do_space_marks; }
133
+                else if ($c == "h") { $current =& $this->do_space_emdash; }
134
+                else if ($c == "H") { $current =& $this->do_space_endash; }
135
+                else if ($c == "f") { $current =& $this->do_space_frenchquote; }
136
+                else if ($c == "t") { $current =& $this->do_space_thousand; }
137
+                else if ($c == "u") { $current =& $this->do_space_unit; }
138
+                else if ($c == "+") {
139
+                    $current = 2;
140
+                    unset($current);
141
+                }
142
+                else if ($c == "-") {
143
+                    $current = -1;
144
+                    unset($current);
145
+                }
146
+                else {
147
+                    # Unknown attribute option, ignore.
148
+                }
149
+                $current = 1;
150
+            }
151
+        }
152
+    }
153
+
154
+
155
+    function decodeEntitiesInConfiguration() {
156
+        parent::decodeEntitiesInConfiguration();
157
+        $output_config_vars = array(
158
+            'doublequote_low',
159
+            'guillemet_leftpointing',
160
+            'guillemet_rightpointing',
161
+            'space_emdash',
162
+            'space_endash',
163
+            'space_colon',
164
+            'space_semicolon',
165
+            'space_marks',
166
+            'space_frenchquote',
167
+            'space_thousand',
168
+            'space_unit',
169
+        );
170
+        foreach ($output_config_vars as $var) {
171
+            $this->$var = html_entity_decode($this->$var);
172
+        }
173
+    }
174
+
175
+
176
+    function educate($t, $prev_token_last_char) {
177
+        # must happen before regular smart quotes
178
+        if ($this->do_geresh_gershayim)  $t = $this->educateGereshGershayim($t);
179
+
180
+        $t = parent::educate($t, $prev_token_last_char);
181 181
 		
182
-		if ($this->do_comma_quotes)      $t = $this->educateCommaQuotes($t);
183
-		if ($this->do_guillemets)        $t = $this->educateGuillemets($t);
182
+        if ($this->do_comma_quotes)      $t = $this->educateCommaQuotes($t);
183
+        if ($this->do_guillemets)        $t = $this->educateGuillemets($t);
184 184
 		
185
-		if ($this->do_space_emdash)      $t = $this->spaceEmDash($t);
186
-		if ($this->do_space_endash)      $t = $this->spaceEnDash($t);
187
-		if ($this->do_space_colon)       $t = $this->spaceColon($t);
188
-		if ($this->do_space_semicolon)   $t = $this->spaceSemicolon($t);
189
-		if ($this->do_space_marks)       $t = $this->spaceMarks($t);
190
-		if ($this->do_space_frenchquote) $t = $this->spaceFrenchQuotes($t);
191
-		if ($this->do_space_thousand)    $t = $this->spaceThousandSeparator($t);
192
-		if ($this->do_space_unit)        $t = $this->spaceUnit($t);
185
+        if ($this->do_space_emdash)      $t = $this->spaceEmDash($t);
186
+        if ($this->do_space_endash)      $t = $this->spaceEnDash($t);
187
+        if ($this->do_space_colon)       $t = $this->spaceColon($t);
188
+        if ($this->do_space_semicolon)   $t = $this->spaceSemicolon($t);
189
+        if ($this->do_space_marks)       $t = $this->spaceMarks($t);
190
+        if ($this->do_space_frenchquote) $t = $this->spaceFrenchQuotes($t);
191
+        if ($this->do_space_thousand)    $t = $this->spaceThousandSeparator($t);
192
+        if ($this->do_space_unit)        $t = $this->spaceUnit($t);
193 193
 		
194
-		return $t;
195
-	}
196
-
197
-
198
-	protected function educateCommaQuotes($_) {
199
-	#
200
-	#   Parameter:  String.
201
-	#   Returns:    The string, with ,,comma,, -style double quotes
202
-	#               translated into HTML curly quote entities.
203
-	#
204
-	#   Example input:  ,,Isn't this fun?,,
205
-	#   Example output: &#8222;Isn't this fun?&#8222;
206
-	#
207
-	# Note: this is meant to be used alongside with backtick quotes; there is 
208
-	# no language that use only lower quotations alone mark like in the example.
209
-	#
210
-		$_ = str_replace(",,", $this->doublequote_low, $_);
211
-		return $_;
212
-	}
213
-
214
-
215
-	protected function educateGuillemets($_) {
216
-	#
217
-	#   Parameter:  String.
218
-	#   Returns:    The string, with << guillemets >> -style quotes
219
-	#               translated into HTML guillemets entities.
220
-	#
221
-	#   Example input:  << Isn't this fun? >>
222
-	#   Example output: &#8222; Isn't this fun? &#8222;
223
-	#
224
-		$_ = preg_replace("/(?:<|&lt;){2}/", $this->guillemet_leftpointing, $_);
225
-		$_ = preg_replace("/(?:>|&gt;){2}/", $this->guillemet_rightpointing, $_);
226
-		return $_;
227
-	}
228
-
229
-
230
-	protected function educateGereshGershayim($_) {
231
-	#
232
-	#   Parameter:  String, UTF-8 encoded.
233
-	#   Returns:    The string, where simple a or double quote surrounded by
234
-	#               two hebrew characters is replaced into a typographic
235
-	#               geresh or gershayim punctuation mark.
236
-	#
237
-	#   Example input:  צה"ל / צ'ארלס
238
-	#   Example output: צה״ל / צ׳ארלס
239
-	#
240
-		// surrounding code points can be U+0590 to U+05BF and U+05D0 to U+05F2
241
-		// encoded in UTF-8: D6.90 to D6.BF and D7.90 to D7.B2
242
-		$_ = preg_replace('/(?<=\xD6[\x90-\xBF]|\xD7[\x90-\xB2])\'(?=\xD6[\x90-\xBF]|\xD7[\x90-\xB2])/', $this->geresh, $_);
243
-		$_ = preg_replace('/(?<=\xD6[\x90-\xBF]|\xD7[\x90-\xB2])"(?=\xD6[\x90-\xBF]|\xD7[\x90-\xB2])/', $this->gershayim, $_);
244
-		return $_;
245
-	}
246
-
247
-
248
-	protected function spaceFrenchQuotes($_) {
249
-	#
250
-	#	Parameters: String, replacement character, and forcing flag.
251
-	#	Returns:    The string, with appropriates spaces replaced 
252
-	#				inside french-style quotes, only french quotes.
253
-	#
254
-	#	Example input:  Quotes in « French », »German« and »Finnish» style.
255
-	#	Example output: Quotes in «_French_», »German« and »Finnish» style.
256
-	#
257
-		$opt = ( $this->do_space_frenchquote ==  2 ? '?' : '' );
258
-		$chr = ( $this->do_space_frenchquote != -1 ? $this->space_frenchquote : '' );
194
+        return $t;
195
+    }
196
+
197
+
198
+    protected function educateCommaQuotes($_) {
199
+    #
200
+    #   Parameter:  String.
201
+    #   Returns:    The string, with ,,comma,, -style double quotes
202
+    #               translated into HTML curly quote entities.
203
+    #
204
+    #   Example input:  ,,Isn't this fun?,,
205
+    #   Example output: &#8222;Isn't this fun?&#8222;
206
+    #
207
+    # Note: this is meant to be used alongside with backtick quotes; there is 
208
+    # no language that use only lower quotations alone mark like in the example.
209
+    #
210
+        $_ = str_replace(",,", $this->doublequote_low, $_);
211
+        return $_;
212
+    }
213
+
214
+
215
+    protected function educateGuillemets($_) {
216
+    #
217
+    #   Parameter:  String.
218
+    #   Returns:    The string, with << guillemets >> -style quotes
219
+    #               translated into HTML guillemets entities.
220
+    #
221
+    #   Example input:  << Isn't this fun? >>
222
+    #   Example output: &#8222; Isn't this fun? &#8222;
223
+    #
224
+        $_ = preg_replace("/(?:<|&lt;){2}/", $this->guillemet_leftpointing, $_);
225
+        $_ = preg_replace("/(?:>|&gt;){2}/", $this->guillemet_rightpointing, $_);
226
+        return $_;
227
+    }
228
+
229
+
230
+    protected function educateGereshGershayim($_) {
231
+    #
232
+    #   Parameter:  String, UTF-8 encoded.
233
+    #   Returns:    The string, where simple a or double quote surrounded by
234
+    #               two hebrew characters is replaced into a typographic
235
+    #               geresh or gershayim punctuation mark.
236
+    #
237
+    #   Example input:  צה"ל / צ'ארלס
238
+    #   Example output: צה״ל / צ׳ארלס
239
+    #
240
+        // surrounding code points can be U+0590 to U+05BF and U+05D0 to U+05F2
241
+        // encoded in UTF-8: D6.90 to D6.BF and D7.90 to D7.B2
242
+        $_ = preg_replace('/(?<=\xD6[\x90-\xBF]|\xD7[\x90-\xB2])\'(?=\xD6[\x90-\xBF]|\xD7[\x90-\xB2])/', $this->geresh, $_);
243
+        $_ = preg_replace('/(?<=\xD6[\x90-\xBF]|\xD7[\x90-\xB2])"(?=\xD6[\x90-\xBF]|\xD7[\x90-\xB2])/', $this->gershayim, $_);
244
+        return $_;
245
+    }
246
+
247
+
248
+    protected function spaceFrenchQuotes($_) {
249
+    #
250
+    #	Parameters: String, replacement character, and forcing flag.
251
+    #	Returns:    The string, with appropriates spaces replaced 
252
+    #				inside french-style quotes, only french quotes.
253
+    #
254
+    #	Example input:  Quotes in « French », »German« and »Finnish» style.
255
+    #	Example output: Quotes in «_French_», »German« and »Finnish» style.
256
+    #
257
+        $opt = ( $this->do_space_frenchquote ==  2 ? '?' : '' );
258
+        $chr = ( $this->do_space_frenchquote != -1 ? $this->space_frenchquote : '' );
259 259
 		
260
-		# Characters allowed immediatly outside quotes.
261
-		$outside_char = $this->space . '|\s|[.,:;!?\[\](){}|@*~=+-]|¡|¿';
260
+        # Characters allowed immediatly outside quotes.
261
+        $outside_char = $this->space . '|\s|[.,:;!?\[\](){}|@*~=+-]|¡|¿';
262 262
 		
263
-		$_ = preg_replace(
264
-			"/(^|$outside_char)(&#171;|«|&#8250;|‹)$this->space$opt/",
265
-			"\\1\\2$chr", $_);
266
-		$_ = preg_replace(
267
-			"/$this->space$opt(&#187;|»|&#8249;|›)($outside_char|$)/", 
268
-			"$chr\\1\\2", $_);
269
-		return $_;
270
-	}
271
-
272
-
273
-	protected function spaceColon($_) {
274
-	#
275
-	#	Parameters: String, replacement character, and forcing flag.
276
-	#	Returns:    The string, with appropriates spaces replaced 
277
-	#				before colons.
278
-	#
279
-	#	Example input:  Ingredients : fun.
280
-	#	Example output: Ingredients_: fun.
281
-	#
282
-		$opt = ( $this->do_space_colon ==  2 ? '?' : '' );
283
-		$chr = ( $this->do_space_colon != -1 ? $this->space_colon : '' );
263
+        $_ = preg_replace(
264
+            "/(^|$outside_char)(&#171;|«|&#8250;|‹)$this->space$opt/",
265
+            "\\1\\2$chr", $_);
266
+        $_ = preg_replace(
267
+            "/$this->space$opt(&#187;|»|&#8249;|›)($outside_char|$)/", 
268
+            "$chr\\1\\2", $_);
269
+        return $_;
270
+    }
271
+
272
+
273
+    protected function spaceColon($_) {
274
+    #
275
+    #	Parameters: String, replacement character, and forcing flag.
276
+    #	Returns:    The string, with appropriates spaces replaced 
277
+    #				before colons.
278
+    #
279
+    #	Example input:  Ingredients : fun.
280
+    #	Example output: Ingredients_: fun.
281
+    #
282
+        $opt = ( $this->do_space_colon ==  2 ? '?' : '' );
283
+        $chr = ( $this->do_space_colon != -1 ? $this->space_colon : '' );
284 284
 		
285
-		$_ = preg_replace("/$this->space$opt(:)(\\s|$)/m",
286
-						  "$chr\\1\\2", $_);
287
-		return $_;
288
-	}
289
-
290
-
291
-	protected function spaceSemicolon($_) {
292
-	#
293
-	#	Parameters: String, replacement character, and forcing flag.
294
-	#	Returns:    The string, with appropriates spaces replaced 
295
-	#				before semicolons.
296
-	#
297
-	#	Example input:  There he goes ; there she goes.
298
-	#	Example output: There he goes_; there she goes.
299
-	#
300
-		$opt = ( $this->do_space_semicolon ==  2 ? '?' : '' );
301
-		$chr = ( $this->do_space_semicolon != -1 ? $this->space_semicolon : '' );
285
+        $_ = preg_replace("/$this->space$opt(:)(\\s|$)/m",
286
+                            "$chr\\1\\2", $_);
287
+        return $_;
288
+    }
289
+
290
+
291
+    protected function spaceSemicolon($_) {
292
+    #
293
+    #	Parameters: String, replacement character, and forcing flag.
294
+    #	Returns:    The string, with appropriates spaces replaced 
295
+    #				before semicolons.
296
+    #
297
+    #	Example input:  There he goes ; there she goes.
298
+    #	Example output: There he goes_; there she goes.
299
+    #
300
+        $opt = ( $this->do_space_semicolon ==  2 ? '?' : '' );
301
+        $chr = ( $this->do_space_semicolon != -1 ? $this->space_semicolon : '' );
302 302
 		
303
-		$_ = preg_replace("/$this->space(;)(?=\\s|$)/m", 
304
-						  " \\1", $_);
305
-		$_ = preg_replace("/((?:^|\\s)(?>[^&;\\s]+|&#?[a-zA-Z0-9]+;)*)".
306
-						  " $opt(;)(?=\\s|$)/m", 
307
-						  "\\1$chr\\2", $_);
308
-		return $_;
309
-	}
310
-
311
-
312
-	protected function spaceMarks($_) {
313
-	#
314
-	#	Parameters: String, replacement character, and forcing flag.
315
-	#	Returns:    The string, with appropriates spaces replaced 
316
-	#				around question and exclamation marks.
317
-	#
318
-	#	Example input:  ¡ Holà ! What ?
319
-	#	Example output: ¡_Holà_! What_?
320
-	#
321
-		$opt = ( $this->do_space_marks ==  2 ? '?' : '' );
322
-		$chr = ( $this->do_space_marks != -1 ? $this->space_marks : '' );
323
-
324
-		// Regular marks.
325
-		$_ = preg_replace("/$this->space$opt([?!]+)/", "$chr\\1", $_);
326
-
327
-		// Inverted marks.
328
-		$imarks = "(?:¡|&iexcl;|&#161;|&#x[Aa]1;|¿|&iquest;|&#191;|&#x[Bb][Ff];)";
329
-		$_ = preg_replace("/($imarks+)$this->space$opt/", "\\1$chr", $_);
303
+        $_ = preg_replace("/$this->space(;)(?=\\s|$)/m", 
304
+                            " \\1", $_);
305
+        $_ = preg_replace("/((?:^|\\s)(?>[^&;\\s]+|&#?[a-zA-Z0-9]+;)*)".
306
+                            " $opt(;)(?=\\s|$)/m", 
307
+                            "\\1$chr\\2", $_);
308
+        return $_;
309
+    }
310
+
311
+
312
+    protected function spaceMarks($_) {
313
+    #
314
+    #	Parameters: String, replacement character, and forcing flag.
315
+    #	Returns:    The string, with appropriates spaces replaced 
316
+    #				around question and exclamation marks.
317
+    #
318
+    #	Example input:  ¡ Holà ! What ?
319
+    #	Example output: ¡_Holà_! What_?
320
+    #
321
+        $opt = ( $this->do_space_marks ==  2 ? '?' : '' );
322
+        $chr = ( $this->do_space_marks != -1 ? $this->space_marks : '' );
323
+
324
+        // Regular marks.
325
+        $_ = preg_replace("/$this->space$opt([?!]+)/", "$chr\\1", $_);
326
+
327
+        // Inverted marks.
328
+        $imarks = "(?:¡|&iexcl;|&#161;|&#x[Aa]1;|¿|&iquest;|&#191;|&#x[Bb][Ff];)";
329
+        $_ = preg_replace("/($imarks+)$this->space$opt/", "\\1$chr", $_);
330 330
 	
331
-		return $_;
332
-	}
333
-
334
-
335
-	protected function spaceEmDash($_) {
336
-	#
337
-	#	Parameters: String, two replacement characters separated by a hyphen (`-`),
338
-	#				and forcing flag.
339
-	#
340
-	#	Returns:    The string, with appropriates spaces replaced 
341
-	#				around dashes.
342
-	#
343
-	#	Example input:  Then — without any plan — the fun happend.
344
-	#	Example output: Then_—_without any plan_—_the fun happend.
345
-	#
346
-		$opt = ( $this->do_space_emdash ==  2 ? '?' : '' );
347
-		$chr = ( $this->do_space_emdash != -1 ? $this->space_emdash : '' );
348
-		$_ = preg_replace("/$this->space$opt(&#8212;|—)$this->space$opt/", 
349
-			"$chr\\1$chr", $_);
350
-		return $_;
351
-	}
331
+        return $_;
332
+    }
333
+
334
+
335
+    protected function spaceEmDash($_) {
336
+    #
337
+    #	Parameters: String, two replacement characters separated by a hyphen (`-`),
338
+    #				and forcing flag.
339
+    #
340
+    #	Returns:    The string, with appropriates spaces replaced 
341
+    #				around dashes.
342
+    #
343
+    #	Example input:  Then — without any plan — the fun happend.
344
+    #	Example output: Then_—_without any plan_—_the fun happend.
345
+    #
346
+        $opt = ( $this->do_space_emdash ==  2 ? '?' : '' );
347
+        $chr = ( $this->do_space_emdash != -1 ? $this->space_emdash : '' );
348
+        $_ = preg_replace("/$this->space$opt(&#8212;|—)$this->space$opt/", 
349
+            "$chr\\1$chr", $_);
350
+        return $_;
351
+    }
352 352
 	
353 353
 	
354
-	protected function spaceEnDash($_) {
355
-	#
356
-	#	Parameters: String, two replacement characters separated by a hyphen (`-`),
357
-	#				and forcing flag.
358
-	#
359
-	#	Returns:    The string, with appropriates spaces replaced 
360
-	#				around dashes.
361
-	#
362
-	#	Example input:  Then — without any plan — the fun happend.
363
-	#	Example output: Then_—_without any plan_—_the fun happend.
364
-	#
365
-		$opt = ( $this->do_space_endash ==  2 ? '?' : '' );
366
-		$chr = ( $this->do_space_endash != -1 ? $this->space_endash : '' );
367
-		$_ = preg_replace("/$this->space$opt(&#8211;|–)$this->space$opt/", 
368
-			"$chr\\1$chr", $_);
369
-		return $_;
370
-	}
371
-
372
-
373
-	protected function spaceThousandSeparator($_) {
374
-	#
375
-	#	Parameters: String, replacement character, and forcing flag.
376
-	#	Returns:    The string, with appropriates spaces replaced 
377
-	#				inside numbers (thousand separator in french).
378
-	#
379
-	#	Example input:  Il y a 10 000 insectes amusants dans ton jardin.
380
-	#	Example output: Il y a 10_000 insectes amusants dans ton jardin.
381
-	#
382
-		$chr = ( $this->do_space_thousand != -1 ? $this->space_thousand : '' );
383
-		$_ = preg_replace('/([0-9]) ([0-9])/', "\\1$chr\\2", $_);
384
-		return $_;
385
-	}
386
-
387
-
388
-	protected $units = '
354
+    protected function spaceEnDash($_) {
355
+    #
356
+    #	Parameters: String, two replacement characters separated by a hyphen (`-`),
357
+    #				and forcing flag.
358
+    #
359
+    #	Returns:    The string, with appropriates spaces replaced 
360
+    #				around dashes.
361
+    #
362
+    #	Example input:  Then — without any plan — the fun happend.
363
+    #	Example output: Then_—_without any plan_—_the fun happend.
364
+    #
365
+        $opt = ( $this->do_space_endash ==  2 ? '?' : '' );
366
+        $chr = ( $this->do_space_endash != -1 ? $this->space_endash : '' );
367
+        $_ = preg_replace("/$this->space$opt(&#8211;|–)$this->space$opt/", 
368
+            "$chr\\1$chr", $_);
369
+        return $_;
370
+    }
371
+
372
+
373
+    protected function spaceThousandSeparator($_) {
374
+    #
375
+    #	Parameters: String, replacement character, and forcing flag.
376
+    #	Returns:    The string, with appropriates spaces replaced 
377
+    #				inside numbers (thousand separator in french).
378
+    #
379
+    #	Example input:  Il y a 10 000 insectes amusants dans ton jardin.
380
+    #	Example output: Il y a 10_000 insectes amusants dans ton jardin.
381
+    #
382
+        $chr = ( $this->do_space_thousand != -1 ? $this->space_thousand : '' );
383
+        $_ = preg_replace('/([0-9]) ([0-9])/', "\\1$chr\\2", $_);
384
+        return $_;
385
+    }
386
+
387
+
388
+    protected $units = '
389 389
 		### Metric units (with prefixes)
390 390
 		(?:
391 391
 			p |
@@ -411,76 +411,76 @@  discard block
 block discarded – undo
411 411
 		%|pt|pi|M?px|em|en|gal|lb|[NSEOW]|[NS][EOW]|ha|mbar
412 412
 		'; //x
413 413
 
414
-	protected function spaceUnit($_) {
415
-	#
416
-	#	Parameters: String, replacement character, and forcing flag.
417
-	#	Returns:    The string, with appropriates spaces replaced
418
-	#				before unit symbols.
419
-	#
420
-	#	Example input:  Get 3 mol of fun for 3 $.
421
-	#	Example output: Get 3_mol of fun for 3_$.
422
-	#
423
-		$opt = ( $this->do_space_unit ==  2 ? '?' : '' );
424
-		$chr = ( $this->do_space_unit != -1 ? $this->space_unit : '' );
425
-
426
-		$_ = preg_replace('/
414
+    protected function spaceUnit($_) {
415
+    #
416
+    #	Parameters: String, replacement character, and forcing flag.
417
+    #	Returns:    The string, with appropriates spaces replaced
418
+    #				before unit symbols.
419
+    #
420
+    #	Example input:  Get 3 mol of fun for 3 $.
421
+    #	Example output: Get 3_mol of fun for 3_$.
422
+    #
423
+        $opt = ( $this->do_space_unit ==  2 ? '?' : '' );
424
+        $chr = ( $this->do_space_unit != -1 ? $this->space_unit : '' );
425
+
426
+        $_ = preg_replace('/
427 427
 			(?:([0-9])[ ]'.$opt.') # Number followed by space.
428 428
 			('.$this->units.')     # Unit.
429 429
 			(?![a-zA-Z0-9])  # Negative lookahead for other unit characters.
430 430
 			/x',
431
-			"\\1$chr\\2", $_);
432
-
433
-		return $_;
434
-	}
435
-
436
-
437
-	protected function spaceAbbr($_) {
438
-	#
439
-	#	Parameters: String, replacement character, and forcing flag.
440
-	#	Returns:    The string, with appropriates spaces replaced
441
-	#				around abbreviations.
442
-	#
443
-	#	Example input:  Fun i.e. something pleasant.
444
-	#	Example output: Fun i.e._something pleasant.
445
-	#
446
-		$opt = ( $this->do_space_abbr ==  2 ? '?' : '' );
431
+            "\\1$chr\\2", $_);
432
+
433
+        return $_;
434
+    }
435
+
436
+
437
+    protected function spaceAbbr($_) {
438
+    #
439
+    #	Parameters: String, replacement character, and forcing flag.
440
+    #	Returns:    The string, with appropriates spaces replaced
441
+    #				around abbreviations.
442
+    #
443
+    #	Example input:  Fun i.e. something pleasant.
444
+    #	Example output: Fun i.e._something pleasant.
445
+    #
446
+        $opt = ( $this->do_space_abbr ==  2 ? '?' : '' );
447 447
 		
448
-		$_ = preg_replace("/(^|\s)($this->abbr_after) $opt/m",
449
-			"\\1\\2$this->space_abbr", $_);
450
-		$_ = preg_replace("/( )$opt($this->abbr_sp_before)(?![a-zA-Z'])/m", 
451
-			"\\1$this->space_abbr\\2", $_);
452
-		return $_;
453
-	}
454
-
455
-
456
-	protected function stupefyEntities($_) {
457
-	#
458
-	#   Adding angle quotes and lower quotes to SmartyPants's stupefy mode.
459
-	#
460
-		$_ = parent::stupefyEntities($_);
461
-
462
-		$_ = str_replace(array('&#8222;', '&#171;', '&#187'), '"', $_);
463
-
464
-		return $_;
465
-	}
466
-
467
-
468
-	protected function processEscapes($_) {
469
-	#
470
-	#   Adding a few more escapes to SmartyPants's escapes:
471
-	#
472
-	#               Escape  Value
473
-	#               ------  -----
474
-	#               \,      &#44;
475
-	#               \<      &#60;
476
-	#               \>      &#62;
477
-	#
478
-		$_ = parent::processEscapes($_);
479
-
480
-		$_ = str_replace(
481
-			array('\,',    '\<',    '\>',    '\&lt;', '\&gt;'),
482
-			array('&#44;', '&#60;', '&#62;', '&#60;', '&#62;'), $_);
483
-
484
-		return $_;
485
-	}
448
+        $_ = preg_replace("/(^|\s)($this->abbr_after) $opt/m",
449
+            "\\1\\2$this->space_abbr", $_);
450
+        $_ = preg_replace("/( )$opt($this->abbr_sp_before)(?![a-zA-Z'])/m", 
451
+            "\\1$this->space_abbr\\2", $_);
452
+        return $_;
453
+    }
454
+
455
+
456
+    protected function stupefyEntities($_) {
457
+    #
458
+    #   Adding angle quotes and lower quotes to SmartyPants's stupefy mode.
459
+    #
460
+        $_ = parent::stupefyEntities($_);
461
+
462
+        $_ = str_replace(array('&#8222;', '&#171;', '&#187'), '"', $_);
463
+
464
+        return $_;
465
+    }
466
+
467
+
468
+    protected function processEscapes($_) {
469
+    #
470
+    #   Adding a few more escapes to SmartyPants's escapes:
471
+    #
472
+    #               Escape  Value
473
+    #               ------  -----
474
+    #               \,      &#44;
475
+    #               \<      &#60;
476
+    #               \>      &#62;
477
+    #
478
+        $_ = parent::processEscapes($_);
479
+
480
+        $_ = str_replace(
481
+            array('\,',    '\<',    '\>',    '\&lt;', '\&gt;'),
482
+            array('&#44;', '&#60;', '&#62;', '&#60;', '&#62;'), $_);
483
+
484
+        return $_;
485
+    }
486 486
 }
Please login to merge, or discard this patch.
Spacing   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -119,22 +119,22 @@  discard block
 block discarded – undo
119 119
 		}
120 120
 		else if ($attr == "-1") {
121 121
 			# Special "stupefy" mode.
122
-			$this->do_stupefy   = 1;
122
+			$this->do_stupefy = 1;
123 123
 		}
124 124
 		else {
125 125
 			$chars = preg_split('//', $attr);
126
-			foreach ($chars as $c){
127
-				if      ($c == "c") { $current =& $this->do_comma_quotes; }
128
-				else if ($c == "g") { $current =& $this->do_guillemets; }
129
-				else if ($c == "G") { $current =& $this->do_geresh_gershayim; }
130
-				else if ($c == ":") { $current =& $this->do_space_colon; }
131
-				else if ($c == ";") { $current =& $this->do_space_semicolon; }
132
-				else if ($c == "m") { $current =& $this->do_space_marks; }
133
-				else if ($c == "h") { $current =& $this->do_space_emdash; }
134
-				else if ($c == "H") { $current =& $this->do_space_endash; }
135
-				else if ($c == "f") { $current =& $this->do_space_frenchquote; }
136
-				else if ($c == "t") { $current =& $this->do_space_thousand; }
137
-				else if ($c == "u") { $current =& $this->do_space_unit; }
126
+			foreach ($chars as $c) {
127
+				if ($c == "c") { $current = & $this->do_comma_quotes; }
128
+				else if ($c == "g") { $current = & $this->do_guillemets; }
129
+				else if ($c == "G") { $current = & $this->do_geresh_gershayim; }
130
+				else if ($c == ":") { $current = & $this->do_space_colon; }
131
+				else if ($c == ";") { $current = & $this->do_space_semicolon; }
132
+				else if ($c == "m") { $current = & $this->do_space_marks; }
133
+				else if ($c == "h") { $current = & $this->do_space_emdash; }
134
+				else if ($c == "H") { $current = & $this->do_space_endash; }
135
+				else if ($c == "f") { $current = & $this->do_space_frenchquote; }
136
+				else if ($c == "t") { $current = & $this->do_space_thousand; }
137
+				else if ($c == "u") { $current = & $this->do_space_unit; }
138 138
 				else if ($c == "+") {
139 139
 					$current = 2;
140 140
 					unset($current);
@@ -254,8 +254,8 @@  discard block
 block discarded – undo
254 254
 	#	Example input:  Quotes in « French », »German« and »Finnish» style.
255 255
 	#	Example output: Quotes in «_French_», »German« and »Finnish» style.
256 256
 	#
257
-		$opt = ( $this->do_space_frenchquote ==  2 ? '?' : '' );
258
-		$chr = ( $this->do_space_frenchquote != -1 ? $this->space_frenchquote : '' );
257
+		$opt = ($this->do_space_frenchquote == 2 ? '?' : '');
258
+		$chr = ($this->do_space_frenchquote != -1 ? $this->space_frenchquote : '');
259 259
 		
260 260
 		# Characters allowed immediatly outside quotes.
261 261
 		$outside_char = $this->space . '|\s|[.,:;!?\[\](){}|@*~=+-]|¡|¿';
@@ -279,8 +279,8 @@  discard block
 block discarded – undo
279 279
 	#	Example input:  Ingredients : fun.
280 280
 	#	Example output: Ingredients_: fun.
281 281
 	#
282
-		$opt = ( $this->do_space_colon ==  2 ? '?' : '' );
283
-		$chr = ( $this->do_space_colon != -1 ? $this->space_colon : '' );
282
+		$opt = ($this->do_space_colon == 2 ? '?' : '');
283
+		$chr = ($this->do_space_colon != -1 ? $this->space_colon : '');
284 284
 		
285 285
 		$_ = preg_replace("/$this->space$opt(:)(\\s|$)/m",
286 286
 						  "$chr\\1\\2", $_);
@@ -297,12 +297,12 @@  discard block
 block discarded – undo
297 297
 	#	Example input:  There he goes ; there she goes.
298 298
 	#	Example output: There he goes_; there she goes.
299 299
 	#
300
-		$opt = ( $this->do_space_semicolon ==  2 ? '?' : '' );
301
-		$chr = ( $this->do_space_semicolon != -1 ? $this->space_semicolon : '' );
300
+		$opt = ($this->do_space_semicolon == 2 ? '?' : '');
301
+		$chr = ($this->do_space_semicolon != -1 ? $this->space_semicolon : '');
302 302
 		
303 303
 		$_ = preg_replace("/$this->space(;)(?=\\s|$)/m", 
304 304
 						  " \\1", $_);
305
-		$_ = preg_replace("/((?:^|\\s)(?>[^&;\\s]+|&#?[a-zA-Z0-9]+;)*)".
305
+		$_ = preg_replace("/((?:^|\\s)(?>[^&;\\s]+|&#?[a-zA-Z0-9]+;)*)" .
306 306
 						  " $opt(;)(?=\\s|$)/m", 
307 307
 						  "\\1$chr\\2", $_);
308 308
 		return $_;
@@ -318,8 +318,8 @@  discard block
 block discarded – undo
318 318
 	#	Example input:  ¡ Holà ! What ?
319 319
 	#	Example output: ¡_Holà_! What_?
320 320
 	#
321
-		$opt = ( $this->do_space_marks ==  2 ? '?' : '' );
322
-		$chr = ( $this->do_space_marks != -1 ? $this->space_marks : '' );
321
+		$opt = ($this->do_space_marks == 2 ? '?' : '');
322
+		$chr = ($this->do_space_marks != -1 ? $this->space_marks : '');
323 323
 
324 324
 		// Regular marks.
325 325
 		$_ = preg_replace("/$this->space$opt([?!]+)/", "$chr\\1", $_);
@@ -343,8 +343,8 @@  discard block
 block discarded – undo
343 343
 	#	Example input:  Then — without any plan — the fun happend.
344 344
 	#	Example output: Then_—_without any plan_—_the fun happend.
345 345
 	#
346
-		$opt = ( $this->do_space_emdash ==  2 ? '?' : '' );
347
-		$chr = ( $this->do_space_emdash != -1 ? $this->space_emdash : '' );
346
+		$opt = ($this->do_space_emdash == 2 ? '?' : '');
347
+		$chr = ($this->do_space_emdash != -1 ? $this->space_emdash : '');
348 348
 		$_ = preg_replace("/$this->space$opt(&#8212;|—)$this->space$opt/", 
349 349
 			"$chr\\1$chr", $_);
350 350
 		return $_;
@@ -362,8 +362,8 @@  discard block
 block discarded – undo
362 362
 	#	Example input:  Then — without any plan — the fun happend.
363 363
 	#	Example output: Then_—_without any plan_—_the fun happend.
364 364
 	#
365
-		$opt = ( $this->do_space_endash ==  2 ? '?' : '' );
366
-		$chr = ( $this->do_space_endash != -1 ? $this->space_endash : '' );
365
+		$opt = ($this->do_space_endash == 2 ? '?' : '');
366
+		$chr = ($this->do_space_endash != -1 ? $this->space_endash : '');
367 367
 		$_ = preg_replace("/$this->space$opt(&#8211;|–)$this->space$opt/", 
368 368
 			"$chr\\1$chr", $_);
369 369
 		return $_;
@@ -379,7 +379,7 @@  discard block
 block discarded – undo
379 379
 	#	Example input:  Il y a 10 000 insectes amusants dans ton jardin.
380 380
 	#	Example output: Il y a 10_000 insectes amusants dans ton jardin.
381 381
 	#
382
-		$chr = ( $this->do_space_thousand != -1 ? $this->space_thousand : '' );
382
+		$chr = ($this->do_space_thousand != -1 ? $this->space_thousand : '');
383 383
 		$_ = preg_replace('/([0-9]) ([0-9])/', "\\1$chr\\2", $_);
384 384
 		return $_;
385 385
 	}
@@ -420,12 +420,12 @@  discard block
 block discarded – undo
420 420
 	#	Example input:  Get 3 mol of fun for 3 $.
421 421
 	#	Example output: Get 3_mol of fun for 3_$.
422 422
 	#
423
-		$opt = ( $this->do_space_unit ==  2 ? '?' : '' );
424
-		$chr = ( $this->do_space_unit != -1 ? $this->space_unit : '' );
423
+		$opt = ($this->do_space_unit == 2 ? '?' : '');
424
+		$chr = ($this->do_space_unit != -1 ? $this->space_unit : '');
425 425
 
426 426
 		$_ = preg_replace('/
427
-			(?:([0-9])[ ]'.$opt.') # Number followed by space.
428
-			('.$this->units.')     # Unit.
427
+			(?:([0-9])[ ]'.$opt . ') # Number followed by space.
428
+			('.$this->units . ')     # Unit.
429 429
 			(?![a-zA-Z0-9])  # Negative lookahead for other unit characters.
430 430
 			/x',
431 431
 			"\\1$chr\\2", $_);
@@ -443,7 +443,7 @@  discard block
 block discarded – undo
443 443
 	#	Example input:  Fun i.e. something pleasant.
444 444
 	#	Example output: Fun i.e._something pleasant.
445 445
 	#
446
-		$opt = ( $this->do_space_abbr ==  2 ? '?' : '' );
446
+		$opt = ($this->do_space_abbr == 2 ? '?' : '');
447 447
 		
448 448
 		$_ = preg_replace("/(^|\s)($this->abbr_after) $opt/m",
449 449
 			"\\1\\2$this->space_abbr", $_);
@@ -478,7 +478,7 @@  discard block
 block discarded – undo
478 478
 		$_ = parent::processEscapes($_);
479 479
 
480 480
 		$_ = str_replace(
481
-			array('\,',    '\<',    '\>',    '\&lt;', '\&gt;'),
481
+			array('\,', '\<', '\>', '\&lt;', '\&gt;'),
482 482
 			array('&#44;', '&#60;', '&#62;', '&#60;', '&#62;'), $_);
483 483
 
484 484
 		return $_;
Please login to merge, or discard this patch.
Braces   +38 added lines, -31 removed lines patch added patch discarded remove patch
@@ -116,34 +116,19 @@  discard block
 block discarded – undo
116 116
 			$this->do_space_frenchquote = 1;
117 117
 			$this->do_space_thousand    = 1;
118 118
 			$this->do_space_unit        = 1;
119
-		}
120
-		else if ($attr == "-1") {
119
+		} else if ($attr == "-1") {
121 120
 			# Special "stupefy" mode.
122 121
 			$this->do_stupefy   = 1;
123
-		}
124
-		else {
122
+		} else {
125 123
 			$chars = preg_split('//', $attr);
126 124
 			foreach ($chars as $c){
127
-				if      ($c == "c") { $current =& $this->do_comma_quotes; }
128
-				else if ($c == "g") { $current =& $this->do_guillemets; }
129
-				else if ($c == "G") { $current =& $this->do_geresh_gershayim; }
130
-				else if ($c == ":") { $current =& $this->do_space_colon; }
131
-				else if ($c == ";") { $current =& $this->do_space_semicolon; }
132
-				else if ($c == "m") { $current =& $this->do_space_marks; }
133
-				else if ($c == "h") { $current =& $this->do_space_emdash; }
134
-				else if ($c == "H") { $current =& $this->do_space_endash; }
135
-				else if ($c == "f") { $current =& $this->do_space_frenchquote; }
136
-				else if ($c == "t") { $current =& $this->do_space_thousand; }
137
-				else if ($c == "u") { $current =& $this->do_space_unit; }
138
-				else if ($c == "+") {
125
+				if      ($c == "c") { $current =& $this->do_comma_quotes; } else if ($c == "g") { $current =& $this->do_guillemets; } else if ($c == "G") { $current =& $this->do_geresh_gershayim; } else if ($c == ":") { $current =& $this->do_space_colon; } else if ($c == ";") { $current =& $this->do_space_semicolon; } else if ($c == "m") { $current =& $this->do_space_marks; } else if ($c == "h") { $current =& $this->do_space_emdash; } else if ($c == "H") { $current =& $this->do_space_endash; } else if ($c == "f") { $current =& $this->do_space_frenchquote; } else if ($c == "t") { $current =& $this->do_space_thousand; } else if ($c == "u") { $current =& $this->do_space_unit; } else if ($c == "+") {
139 126
 					$current = 2;
140 127
 					unset($current);
141
-				}
142
-				else if ($c == "-") {
128
+				} else if ($c == "-") {
143 129
 					$current = -1;
144 130
 					unset($current);
145
-				}
146
-				else {
131
+				} else {
147 132
 					# Unknown attribute option, ignore.
148 133
 				}
149 134
 				$current = 1;
@@ -175,21 +160,43 @@  discard block
 block discarded – undo
175 160
 
176 161
 	function educate($t, $prev_token_last_char) {
177 162
 		# must happen before regular smart quotes
178
-		if ($this->do_geresh_gershayim)  $t = $this->educateGereshGershayim($t);
163
+		if ($this->do_geresh_gershayim) {
164
+		    $t = $this->educateGereshGershayim($t);
165
+		}
179 166
 
180 167
 		$t = parent::educate($t, $prev_token_last_char);
181 168
 		
182
-		if ($this->do_comma_quotes)      $t = $this->educateCommaQuotes($t);
183
-		if ($this->do_guillemets)        $t = $this->educateGuillemets($t);
169
+		if ($this->do_comma_quotes) {
170
+		    $t = $this->educateCommaQuotes($t);
171
+		}
172
+		if ($this->do_guillemets) {
173
+		    $t = $this->educateGuillemets($t);
174
+		}
184 175
 		
185
-		if ($this->do_space_emdash)      $t = $this->spaceEmDash($t);
186
-		if ($this->do_space_endash)      $t = $this->spaceEnDash($t);
187
-		if ($this->do_space_colon)       $t = $this->spaceColon($t);
188
-		if ($this->do_space_semicolon)   $t = $this->spaceSemicolon($t);
189
-		if ($this->do_space_marks)       $t = $this->spaceMarks($t);
190
-		if ($this->do_space_frenchquote) $t = $this->spaceFrenchQuotes($t);
191
-		if ($this->do_space_thousand)    $t = $this->spaceThousandSeparator($t);
192
-		if ($this->do_space_unit)        $t = $this->spaceUnit($t);
176
+		if ($this->do_space_emdash) {
177
+		    $t = $this->spaceEmDash($t);
178
+		}
179
+		if ($this->do_space_endash) {
180
+		    $t = $this->spaceEnDash($t);
181
+		}
182
+		if ($this->do_space_colon) {
183
+		    $t = $this->spaceColon($t);
184
+		}
185
+		if ($this->do_space_semicolon) {
186
+		    $t = $this->spaceSemicolon($t);
187
+		}
188
+		if ($this->do_space_marks) {
189
+		    $t = $this->spaceMarks($t);
190
+		}
191
+		if ($this->do_space_frenchquote) {
192
+		    $t = $this->spaceFrenchQuotes($t);
193
+		}
194
+		if ($this->do_space_thousand) {
195
+		    $t = $this->spaceThousandSeparator($t);
196
+		}
197
+		if ($this->do_space_unit) {
198
+		    $t = $this->spaceUnit($t);
199
+		}
193 200
 		
194 201
 		return $t;
195 202
 	}
Please login to merge, or discard this patch.
a/vendor/michelf/php-markdown/Readme.php 2 patches
Indentation   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -6,7 +6,7 @@  discard block
 block discarded – undo
6 6
 
7 7
 // Install PSR-4-compatible class autoloader
8 8
 spl_autoload_register(function($class){
9
-	require str_replace('\\', DIRECTORY_SEPARATOR, ltrim($class, '\\')).'.php';
9
+    require str_replace('\\', DIRECTORY_SEPARATOR, ltrim($class, '\\')).'.php';
10 10
 });
11 11
 // If using Composer, use this instead:
12 12
 //require 'vendor/autoload.php';
@@ -26,8 +26,8 @@  discard block
 block discarded – undo
26 26
 	</head>
27 27
 	<body>
28 28
 		<?php
29
-			// Put HTML content in the document
30
-			echo $html;
31
-		?>
29
+            // Put HTML content in the document
30
+            echo $html;
31
+        ?>
32 32
 	</body>
33 33
 </html>
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -5,8 +5,8 @@
 block discarded – undo
5 5
 // you like.
6 6
 
7 7
 // Install PSR-4-compatible class autoloader
8
-spl_autoload_register(function($class){
9
-	require str_replace('\\', DIRECTORY_SEPARATOR, ltrim($class, '\\')).'.php';
8
+spl_autoload_register(function($class) {
9
+	require str_replace('\\', DIRECTORY_SEPARATOR, ltrim($class, '\\')) . '.php';
10 10
 });
11 11
 // If using Composer, use this instead:
12 12
 //require 'vendor/autoload.php';
Please login to merge, or discard this patch.
a/vendor/michelf/php-markdown/test/integration/PhpMarkdownTest.php 1 patch
Indentation   +164 added lines, -164 removed lines patch added patch discarded remove patch
@@ -6,168 +6,168 @@
 block discarded – undo
6 6
 
7 7
 class PhpMarkdownTest extends TestCase
8 8
 {
9
-	/**
10
-	 * Returns all php-markdown.mdtest tests
11
-	 * @return array
12
-	 */
13
-	public function dataProviderForPhpMarkdown() {
14
-		$dir = TEST_RESOURCES_ROOT . '/php-markdown.mdtest';
15
-		return MarkdownTestHelper::getInputOutputPaths($dir);
16
-	}
17
-
18
-	/**
19
-	 * Runs php-markdown.mdtest against Markdown::defaultTransform
20
-	 *
21
-	 * @dataProvider dataProviderForPhpMarkdown
22
-	 *
23
-	 * @param string $inputPath Input markdown path
24
-	 * @param string $htmlPath File path of expected transformed output (X)HTML
25
-	 *
26
-	 * @param bool $xhtml True if XHTML. Otherwise, HTML is assumed.
27
-	 *
28
-	 * @return void
29
-	 */
30
-	public function testTransformingOfPhpMarkdown($inputPath, $htmlPath, $xhtml = false) {
31
-		$inputMarkdown = file_get_contents($inputPath);
32
-		$expectedHtml = file_get_contents($htmlPath);
33
-		$result = Markdown::defaultTransform($inputMarkdown);
34
-
35
-		MarkdownTestHelper::assertSameNormalized(
36
-			$expectedHtml,
37
-			$result,
38
-			"Markdown in $inputPath converts exactly to expected $htmlPath",
39
-			$xhtml
40
-		);
41
-	}
42
-
43
-	/**
44
-	 * Returns all php-markdown.mdtest tests EXCEPT Emphasis test.
45
-	 * @return array
46
-	 */
47
-	public function dataProviderForPhpMarkdownExceptEmphasis()
48
-	{
49
-		$dir = TEST_RESOURCES_ROOT . '/php-markdown.mdtest';
50
-		$allTests = MarkdownTestHelper::getInputOutputPaths($dir);
51
-
52
-		foreach ($allTests as $index => $test) {
53
-			// Because MarkdownExtra treats underscore emphasis differently, this one test has to be excluded
54
-			if (preg_match('~/Emphasis\.text$~', $test[0])) {
55
-				unset($allTests[$index]);
56
-			}
57
-		}
58
-
59
-		return array_values($allTests);
60
-	}
61
-
62
-	/**
63
-	 * Runs php-markdown.mdtest against MarkdownExtra::defaultTransform
64
-	 *
65
-	 * @dataProvider dataProviderForPhpMarkdownExceptEmphasis
66
-	 *
67
-	 * @param $inputPath
68
-	 * @param $htmlPath
69
-	 * @param bool $xhtml
70
-	 */
71
-	public function testPhpMarkdownMdTestWithMarkdownExtra($inputPath, $htmlPath, $xhtml = false)
72
-	{
73
-		$inputMarkdown = file_get_contents($inputPath);
74
-		$expectedHtml = file_get_contents($htmlPath);
75
-
76
-		$result = MarkdownExtra::defaultTransform($inputMarkdown);
77
-
78
-		MarkdownTestHelper::assertSameNormalized(
79
-			$expectedHtml,
80
-			$result,
81
-			"Markdown in $inputPath converts exactly to expected $htmlPath",
82
-			$xhtml
83
-		);
84
-	}
85
-
86
-	/**
87
-	 * @return array
88
-	 */
89
-	public function dataProviderForMarkdownExtra() {
90
-		$dir = TEST_RESOURCES_ROOT . '/php-markdown-extra.mdtest';
91
-		return MarkdownTestHelper::getInputOutputPaths($dir);
92
-	}
93
-
94
-	/**
95
-	 * @dataProvider dataProviderForMarkdownExtra
96
-	 *
97
-	 * @param string $inputPath Input markdown path
98
-	 * @param string $htmlPath File path of expected transformed output (X)HTML
99
-	 *
100
-	 * @param bool $xhtml True if XHTML. Otherwise, HTML is assumed.
101
-	 *
102
-	 * @return void
103
-	 */
104
-	public function testTransformingOfMarkdownExtra($inputPath, $htmlPath, $xhtml = false) {
105
-		$inputMarkdown = file_get_contents($inputPath);
106
-		$expectedHtml = file_get_contents($htmlPath);
107
-		$result = MarkdownExtra::defaultTransform($inputMarkdown);
108
-
109
-		MarkdownTestHelper::assertSameNormalized(
110
-			$expectedHtml,
111
-			$result,
112
-			"Markdown in $inputPath converts exactly to expected $htmlPath",
113
-			$xhtml
114
-		);
115
-	}
116
-
117
-	/**
118
-	 * @return array
119
-	 */
120
-	public function dataProviderForRegularMarkdown()
121
-	{
122
-		$dir = TEST_RESOURCES_ROOT . '/markdown.mdtest';
123
-		return MarkdownTestHelper::getInputOutputPaths($dir);
124
-	}
125
-
126
-	/**
127
-	 * @dataProvider dataProviderForRegularMarkdown
128
-	 *
129
-	 * @param string $inputPath Input markdown path
130
-	 * @param string $htmlPath File path of expected transformed output (X)HTML
131
-	 *
132
-	 * @param bool $xhtml True if XHTML. Otherwise, HTML is assumed.
133
-	 *
134
-	 * @return void
135
-	 */
136
-	public function testTransformingOfRegularMarkdown($inputPath, $htmlPath, $xhtml = false)
137
-	{
138
-		$inputMarkdown = file_get_contents($inputPath);
139
-		$expectedHtml = file_get_contents($htmlPath);
140
-		$result = Markdown::defaultTransform($inputMarkdown);
141
-
142
-		MarkdownTestHelper::assertSameNormalized(
143
-			$expectedHtml,
144
-			$result,
145
-			"Markdown in $inputPath converts exactly to expected $htmlPath",
146
-			$xhtml
147
-		);
148
-	}
149
-
150
-	/**
151
-	 * Runs markdown.mdtest against MarkdownExtra::defaultTransform
152
-	 *
153
-	 * @dataProvider dataProviderForRegularMarkdown
154
-	 *
155
-	 * @param $inputPath
156
-	 * @param $htmlPath
157
-	 * @param bool $xhtml
158
-	 */
159
-	public function testMarkdownMdTestWithMarkdownExtra($inputPath, $htmlPath, $xhtml = false)
160
-	{
161
-		$inputMarkdown = file_get_contents($inputPath);
162
-		$expectedHtml = file_get_contents($htmlPath);
163
-
164
-		$result = MarkdownExtra::defaultTransform($inputMarkdown);
165
-
166
-		MarkdownTestHelper::assertSameNormalized(
167
-			$expectedHtml,
168
-			$result,
169
-			"Markdown in $inputPath converts exactly to expected $htmlPath",
170
-			$xhtml
171
-		);
172
-	}
9
+    /**
10
+     * Returns all php-markdown.mdtest tests
11
+     * @return array
12
+     */
13
+    public function dataProviderForPhpMarkdown() {
14
+        $dir = TEST_RESOURCES_ROOT . '/php-markdown.mdtest';
15
+        return MarkdownTestHelper::getInputOutputPaths($dir);
16
+    }
17
+
18
+    /**
19
+     * Runs php-markdown.mdtest against Markdown::defaultTransform
20
+     *
21
+     * @dataProvider dataProviderForPhpMarkdown
22
+     *
23
+     * @param string $inputPath Input markdown path
24
+     * @param string $htmlPath File path of expected transformed output (X)HTML
25
+     *
26
+     * @param bool $xhtml True if XHTML. Otherwise, HTML is assumed.
27
+     *
28
+     * @return void
29
+     */
30
+    public function testTransformingOfPhpMarkdown($inputPath, $htmlPath, $xhtml = false) {
31
+        $inputMarkdown = file_get_contents($inputPath);
32
+        $expectedHtml = file_get_contents($htmlPath);
33
+        $result = Markdown::defaultTransform($inputMarkdown);
34
+
35
+        MarkdownTestHelper::assertSameNormalized(
36
+            $expectedHtml,
37
+            $result,
38
+            "Markdown in $inputPath converts exactly to expected $htmlPath",
39
+            $xhtml
40
+        );
41
+    }
42
+
43
+    /**
44
+     * Returns all php-markdown.mdtest tests EXCEPT Emphasis test.
45
+     * @return array
46
+     */
47
+    public function dataProviderForPhpMarkdownExceptEmphasis()
48
+    {
49
+        $dir = TEST_RESOURCES_ROOT . '/php-markdown.mdtest';
50
+        $allTests = MarkdownTestHelper::getInputOutputPaths($dir);
51
+
52
+        foreach ($allTests as $index => $test) {
53
+            // Because MarkdownExtra treats underscore emphasis differently, this one test has to be excluded
54
+            if (preg_match('~/Emphasis\.text$~', $test[0])) {
55
+                unset($allTests[$index]);
56
+            }
57
+        }
58
+
59
+        return array_values($allTests);
60
+    }
61
+
62
+    /**
63
+     * Runs php-markdown.mdtest against MarkdownExtra::defaultTransform
64
+     *
65
+     * @dataProvider dataProviderForPhpMarkdownExceptEmphasis
66
+     *
67
+     * @param $inputPath
68
+     * @param $htmlPath
69
+     * @param bool $xhtml
70
+     */
71
+    public function testPhpMarkdownMdTestWithMarkdownExtra($inputPath, $htmlPath, $xhtml = false)
72
+    {
73
+        $inputMarkdown = file_get_contents($inputPath);
74
+        $expectedHtml = file_get_contents($htmlPath);
75
+
76
+        $result = MarkdownExtra::defaultTransform($inputMarkdown);
77
+
78
+        MarkdownTestHelper::assertSameNormalized(
79
+            $expectedHtml,
80
+            $result,
81
+            "Markdown in $inputPath converts exactly to expected $htmlPath",
82
+            $xhtml
83
+        );
84
+    }
85
+
86
+    /**
87
+     * @return array
88
+     */
89
+    public function dataProviderForMarkdownExtra() {
90
+        $dir = TEST_RESOURCES_ROOT . '/php-markdown-extra.mdtest';
91
+        return MarkdownTestHelper::getInputOutputPaths($dir);
92
+    }
93
+
94
+    /**
95
+     * @dataProvider dataProviderForMarkdownExtra
96
+     *
97
+     * @param string $inputPath Input markdown path
98
+     * @param string $htmlPath File path of expected transformed output (X)HTML
99
+     *
100
+     * @param bool $xhtml True if XHTML. Otherwise, HTML is assumed.
101
+     *
102
+     * @return void
103
+     */
104
+    public function testTransformingOfMarkdownExtra($inputPath, $htmlPath, $xhtml = false) {
105
+        $inputMarkdown = file_get_contents($inputPath);
106
+        $expectedHtml = file_get_contents($htmlPath);
107
+        $result = MarkdownExtra::defaultTransform($inputMarkdown);
108
+
109
+        MarkdownTestHelper::assertSameNormalized(
110
+            $expectedHtml,
111
+            $result,
112
+            "Markdown in $inputPath converts exactly to expected $htmlPath",
113
+            $xhtml
114
+        );
115
+    }
116
+
117
+    /**
118
+     * @return array
119
+     */
120
+    public function dataProviderForRegularMarkdown()
121
+    {
122
+        $dir = TEST_RESOURCES_ROOT . '/markdown.mdtest';
123
+        return MarkdownTestHelper::getInputOutputPaths($dir);
124
+    }
125
+
126
+    /**
127
+     * @dataProvider dataProviderForRegularMarkdown
128
+     *
129
+     * @param string $inputPath Input markdown path
130
+     * @param string $htmlPath File path of expected transformed output (X)HTML
131
+     *
132
+     * @param bool $xhtml True if XHTML. Otherwise, HTML is assumed.
133
+     *
134
+     * @return void
135
+     */
136
+    public function testTransformingOfRegularMarkdown($inputPath, $htmlPath, $xhtml = false)
137
+    {
138
+        $inputMarkdown = file_get_contents($inputPath);
139
+        $expectedHtml = file_get_contents($htmlPath);
140
+        $result = Markdown::defaultTransform($inputMarkdown);
141
+
142
+        MarkdownTestHelper::assertSameNormalized(
143
+            $expectedHtml,
144
+            $result,
145
+            "Markdown in $inputPath converts exactly to expected $htmlPath",
146
+            $xhtml
147
+        );
148
+    }
149
+
150
+    /**
151
+     * Runs markdown.mdtest against MarkdownExtra::defaultTransform
152
+     *
153
+     * @dataProvider dataProviderForRegularMarkdown
154
+     *
155
+     * @param $inputPath
156
+     * @param $htmlPath
157
+     * @param bool $xhtml
158
+     */
159
+    public function testMarkdownMdTestWithMarkdownExtra($inputPath, $htmlPath, $xhtml = false)
160
+    {
161
+        $inputMarkdown = file_get_contents($inputPath);
162
+        $expectedHtml = file_get_contents($htmlPath);
163
+
164
+        $result = MarkdownExtra::defaultTransform($inputMarkdown);
165
+
166
+        MarkdownTestHelper::assertSameNormalized(
167
+            $expectedHtml,
168
+            $result,
169
+            "Markdown in $inputPath converts exactly to expected $htmlPath",
170
+            $xhtml
171
+        );
172
+    }
173 173
 }
Please login to merge, or discard this patch.
a/vendor/michelf/php-markdown/test/helpers/MarkdownTestHelper.php 3 patches
Indentation   +231 added lines, -231 removed lines patch added patch discarded remove patch
@@ -4,264 +4,264 @@
 block discarded – undo
4 4
 
5 5
 class MarkdownTestHelper
6 6
 {
7
-	/**
8
-	 * Takes an input directory containing .text and .(x)html files, and returns an array
9
-	 * of .text files and the corresponding output xhtml or html file. Can be used in a unit test data provider.
10
-	 *
11
-	 * @param string $directory Input directory
12
-	 *
13
-	 * @return array
14
-	 */
15
-	public static function getInputOutputPaths($directory) {
16
-		$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));
17
-		$regexIterator = new RegexIterator(
18
-			$iterator,
19
-			'/^.+\.text$/',
20
-			RecursiveRegexIterator::GET_MATCH
21
-		);
7
+    /**
8
+     * Takes an input directory containing .text and .(x)html files, and returns an array
9
+     * of .text files and the corresponding output xhtml or html file. Can be used in a unit test data provider.
10
+     *
11
+     * @param string $directory Input directory
12
+     *
13
+     * @return array
14
+     */
15
+    public static function getInputOutputPaths($directory) {
16
+        $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));
17
+        $regexIterator = new RegexIterator(
18
+            $iterator,
19
+            '/^.+\.text$/',
20
+            RecursiveRegexIterator::GET_MATCH
21
+        );
22 22
 
23
-		$dataValues = [];
23
+        $dataValues = [];
24 24
 
25
-		/** @var SplFileInfo $inputFile */
26
-		foreach ($regexIterator as $inputFiles) {
27
-			foreach ($inputFiles as $inputMarkdownPath) {
28
-				$xhtml = true;
29
-				$expectedHtmlPath = substr($inputMarkdownPath, 0, -4) . 'xhtml';
30
-				if (!file_exists($expectedHtmlPath)) {
31
-					$expectedHtmlPath = substr($inputMarkdownPath, 0, -4) . 'html';
32
-					$xhtml = false;
33
-				}
34
-				$dataValues[] = [$inputMarkdownPath, $expectedHtmlPath, $xhtml];
35
-			}
36
-		}
25
+        /** @var SplFileInfo $inputFile */
26
+        foreach ($regexIterator as $inputFiles) {
27
+            foreach ($inputFiles as $inputMarkdownPath) {
28
+                $xhtml = true;
29
+                $expectedHtmlPath = substr($inputMarkdownPath, 0, -4) . 'xhtml';
30
+                if (!file_exists($expectedHtmlPath)) {
31
+                    $expectedHtmlPath = substr($inputMarkdownPath, 0, -4) . 'html';
32
+                    $xhtml = false;
33
+                }
34
+                $dataValues[] = [$inputMarkdownPath, $expectedHtmlPath, $xhtml];
35
+            }
36
+        }
37 37
 
38
-		return $dataValues;
39
-	}
38
+        return $dataValues;
39
+    }
40 40
 
41
-	/**
42
-	 * Applies PHPUnit's assertSame after normalizing both strings (e.g. ignoring whitespace differences).
43
-	 * Uses logic found originally in MDTest.
44
-	 *
45
-	 * @param string $string1
46
-	 * @param string $string2
47
-	 * @param string $message Positive message to print when test fails (e.g. "String1 matches String2")
48
-	 * @param bool $xhtml
49
-	 */
50
-	public static function assertSameNormalized($string1, $string2, $message, $xhtml = true) {
41
+    /**
42
+     * Applies PHPUnit's assertSame after normalizing both strings (e.g. ignoring whitespace differences).
43
+     * Uses logic found originally in MDTest.
44
+     *
45
+     * @param string $string1
46
+     * @param string $string2
47
+     * @param string $message Positive message to print when test fails (e.g. "String1 matches String2")
48
+     * @param bool $xhtml
49
+     */
50
+    public static function assertSameNormalized($string1, $string2, $message, $xhtml = true) {
51 51
 
52
-		$t_result = $string1;
53
-		$t_output = $string2;
52
+        $t_result = $string1;
53
+        $t_output = $string2;
54 54
 
55
-		// DOMDocuments
56
-		if ($xhtml) {
57
-			$document = new DOMDocument();
58
-			$doc_result = $document->loadXML('<!DOCTYPE html>' .
59
-				"<html xmlns='http://www.w3.org/1999/xhtml'>" .
60
-				"<body>$t_result</body></html>");
55
+        // DOMDocuments
56
+        if ($xhtml) {
57
+            $document = new DOMDocument();
58
+            $doc_result = $document->loadXML('<!DOCTYPE html>' .
59
+                "<html xmlns='http://www.w3.org/1999/xhtml'>" .
60
+                "<body>$t_result</body></html>");
61 61
 
62
-			$document2 = new DOMDocument();
63
-			$doc_output = $document2->loadXML('<!DOCTYPE html>' .
64
-				"<html xmlns='http://www.w3.org/1999/xhtml'>" .
65
-				"<body>$t_output</body></html>");
62
+            $document2 = new DOMDocument();
63
+            $doc_output = $document2->loadXML('<!DOCTYPE html>' .
64
+                "<html xmlns='http://www.w3.org/1999/xhtml'>" .
65
+                "<body>$t_output</body></html>");
66 66
 
67
-			if ($doc_result) {
68
-				static::normalizeElementContent($document->documentElement, false);
69
-				$n_result = $document->saveXML();
70
-			} else {
71
-				$n_result = '--- Expected Result: XML Parse Error ---';
72
-			}
73
-			if ($doc_output) {
74
-				static::normalizeElementContent($document2->documentElement, false);
75
-				$n_output = $document2->saveXML();
76
-			} else {
77
-				$n_output = '--- Output: XML Parse Error ---';
78
-			}
79
-		} else {
67
+            if ($doc_result) {
68
+                static::normalizeElementContent($document->documentElement, false);
69
+                $n_result = $document->saveXML();
70
+            } else {
71
+                $n_result = '--- Expected Result: XML Parse Error ---';
72
+            }
73
+            if ($doc_output) {
74
+                static::normalizeElementContent($document2->documentElement, false);
75
+                $n_output = $document2->saveXML();
76
+            } else {
77
+                $n_output = '--- Output: XML Parse Error ---';
78
+            }
79
+        } else {
80 80
 
81
-			// '@' suppressors used because some tests have invalid HTML (multiple elements with the same id attribute)
82
-			// Perhaps isolate to a separate test and remove this?
81
+            // '@' suppressors used because some tests have invalid HTML (multiple elements with the same id attribute)
82
+            // Perhaps isolate to a separate test and remove this?
83 83
 
84
-			$document = new DOMDocument();
85
-			$doc_result = @$document->loadHTML($t_result);
84
+            $document = new DOMDocument();
85
+            $doc_result = @$document->loadHTML($t_result);
86 86
 
87
-			$document2 = new DOMDocument();
88
-			$doc_output = @$document2->loadHTML($t_output);
87
+            $document2 = new DOMDocument();
88
+            $doc_output = @$document2->loadHTML($t_output);
89 89
 
90
-			if ($doc_result) {
91
-				static::normalizeElementContent($document->documentElement, false);
92
-				$n_result = $document->saveHTML();
93
-			} else {
94
-				$n_result = '--- Expected Result: HTML Parse Error ---';
95
-			}
90
+            if ($doc_result) {
91
+                static::normalizeElementContent($document->documentElement, false);
92
+                $n_result = $document->saveHTML();
93
+            } else {
94
+                $n_result = '--- Expected Result: HTML Parse Error ---';
95
+            }
96 96
 
97
-			if ($doc_output) {
98
-				static::normalizeElementContent($document2->documentElement, false);
99
-				$n_output = $document2->saveHTML();
100
-			} else {
101
-				$n_output = '--- Output: HTML Parse Error ---';
102
-			}
103
-		}
97
+            if ($doc_output) {
98
+                static::normalizeElementContent($document2->documentElement, false);
99
+                $n_output = $document2->saveHTML();
100
+            } else {
101
+                $n_output = '--- Output: HTML Parse Error ---';
102
+            }
103
+        }
104 104
 
105
-		$n_result = preg_replace('{^.*?<body>|</body>.*?$}is', '', $n_result);
106
-		$n_output = preg_replace('{^.*?<body>|</body>.*?$}is', '', $n_output);
105
+        $n_result = preg_replace('{^.*?<body>|</body>.*?$}is', '', $n_result);
106
+        $n_output = preg_replace('{^.*?<body>|</body>.*?$}is', '', $n_output);
107 107
 
108
-		$c_result = $n_result;
109
-		$c_output = $n_output;
108
+        $c_result = $n_result;
109
+        $c_output = $n_output;
110 110
 
111
-		$c_result = trim($c_result) . "\n";
112
-		$c_output = trim($c_output) . "\n";
111
+        $c_result = trim($c_result) . "\n";
112
+        $c_output = trim($c_output) . "\n";
113 113
 
114
-		// This will throw a test exception if the strings don't exactly match
115
-		TestCase::assertSame($c_result, $c_output, $message);
116
-	}
114
+        // This will throw a test exception if the strings don't exactly match
115
+        TestCase::assertSame($c_result, $c_output, $message);
116
+    }
117 117
 
118
-	/**
119
-	 * @param DOMElement $element Modifies this element by reference
120
-	 * @param bool $whitespace_preserve Preserve Whitespace
121
-	 * @return void
122
-	 */
123
-	protected static function normalizeElementContent($element, $whitespace_preserve) {
124
-		#
125
-		# Normalize content of HTML DOM $element. The $whitespace_preserve
126
-		# argument indicates that whitespace is significant and shouldn't be
127
-		# normalized; it should be used for the content of certain elements like
128
-		# <pre> or <script>.
129
-		#
130
-		$node_list = $element->childNodes;
131
-		switch (strtolower($element->nodeName)) {
132
-			case 'body':
133
-			case 'div':
134
-			case 'blockquote':
135
-			case 'ul':
136
-			case 'ol':
137
-			case 'dl':
138
-			case 'h1':
139
-			case 'h2':
140
-			case 'h3':
141
-			case 'h4':
142
-			case 'h5':
143
-			case 'h6':
144
-				$whitespace = "\n\n";
145
-				break;
118
+    /**
119
+     * @param DOMElement $element Modifies this element by reference
120
+     * @param bool $whitespace_preserve Preserve Whitespace
121
+     * @return void
122
+     */
123
+    protected static function normalizeElementContent($element, $whitespace_preserve) {
124
+        #
125
+        # Normalize content of HTML DOM $element. The $whitespace_preserve
126
+        # argument indicates that whitespace is significant and shouldn't be
127
+        # normalized; it should be used for the content of certain elements like
128
+        # <pre> or <script>.
129
+        #
130
+        $node_list = $element->childNodes;
131
+        switch (strtolower($element->nodeName)) {
132
+            case 'body':
133
+            case 'div':
134
+            case 'blockquote':
135
+            case 'ul':
136
+            case 'ol':
137
+            case 'dl':
138
+            case 'h1':
139
+            case 'h2':
140
+            case 'h3':
141
+            case 'h4':
142
+            case 'h5':
143
+            case 'h6':
144
+                $whitespace = "\n\n";
145
+                break;
146 146
 
147
-			case 'table':
148
-				$whitespace = "\n";
149
-				break;
147
+            case 'table':
148
+                $whitespace = "\n";
149
+                break;
150 150
 
151
-			case 'pre':
152
-			case 'script':
153
-			case 'style':
154
-			case 'title':
155
-				$whitespace_preserve = true;
156
-				$whitespace = "";
157
-				break;
151
+            case 'pre':
152
+            case 'script':
153
+            case 'style':
154
+            case 'title':
155
+                $whitespace_preserve = true;
156
+                $whitespace = "";
157
+                break;
158 158
 
159
-			default:
160
-				$whitespace = "";
161
-				break;
162
-		}
163
-		foreach ($node_list as $node) {
164
-			switch ($node->nodeType) {
165
-				case XML_ELEMENT_NODE:
166
-					static::normalizeElementContent($node, $whitespace_preserve);
167
-					static::normalizeElementAttributes($node);
159
+            default:
160
+                $whitespace = "";
161
+                break;
162
+        }
163
+        foreach ($node_list as $node) {
164
+            switch ($node->nodeType) {
165
+                case XML_ELEMENT_NODE:
166
+                    static::normalizeElementContent($node, $whitespace_preserve);
167
+                    static::normalizeElementAttributes($node);
168 168
 
169
-					switch (strtolower($node->nodeName)) {
170
-						case 'p':
171
-						case 'div':
172
-						case 'hr':
173
-						case 'blockquote':
174
-						case 'ul':
175
-						case 'ol':
176
-						case 'dl':
177
-						case 'li':
178
-						case 'address':
179
-						case 'table':
180
-						case 'dd':
181
-						case 'pre':
182
-						case 'h1':
183
-						case 'h2':
184
-						case 'h3':
185
-						case 'h4':
186
-						case 'h5':
187
-						case 'h6':
188
-							$whitespace = "\n\n";
189
-							break;
169
+                    switch (strtolower($node->nodeName)) {
170
+                        case 'p':
171
+                        case 'div':
172
+                        case 'hr':
173
+                        case 'blockquote':
174
+                        case 'ul':
175
+                        case 'ol':
176
+                        case 'dl':
177
+                        case 'li':
178
+                        case 'address':
179
+                        case 'table':
180
+                        case 'dd':
181
+                        case 'pre':
182
+                        case 'h1':
183
+                        case 'h2':
184
+                        case 'h3':
185
+                        case 'h4':
186
+                        case 'h5':
187
+                        case 'h6':
188
+                            $whitespace = "\n\n";
189
+                            break;
190 190
 
191
-						case 'tr':
192
-						case 'td':
193
-						case 'dt':
194
-							$whitespace = "\n";
195
-							break;
191
+                        case 'tr':
192
+                        case 'td':
193
+                        case 'dt':
194
+                            $whitespace = "\n";
195
+                            break;
196 196
 
197
-						default:
198
-							$whitespace = "";
199
-							break;
200
-					}
197
+                        default:
198
+                            $whitespace = "";
199
+                            break;
200
+                    }
201 201
 
202
-					if (($whitespace === "\n\n" || $whitespace === "\n") &&
203
-						$node->nextSibling &&
204
-						$node->nextSibling->nodeType != XML_TEXT_NODE) {
205
-						$element->insertBefore(new DOMText($whitespace), $node->nextSibling);
206
-					}
207
-					break;
202
+                    if (($whitespace === "\n\n" || $whitespace === "\n") &&
203
+                        $node->nextSibling &&
204
+                        $node->nextSibling->nodeType != XML_TEXT_NODE) {
205
+                        $element->insertBefore(new DOMText($whitespace), $node->nextSibling);
206
+                    }
207
+                    break;
208 208
 
209
-				case XML_TEXT_NODE:
210
-					if (!$whitespace_preserve) {
211
-						if (trim($node->data) === "") {
212
-							$node->data = $whitespace;
213
-						}
214
-						else {
215
-							$node->data = preg_replace('{\s+}', ' ', $node->data);
216
-						}
217
-					}
218
-					break;
219
-			}
220
-		}
221
-		if (!$whitespace_preserve &&
222
-			($whitespace === "\n\n" || $whitespace === "\n")) {
223
-			if ($element->firstChild) {
224
-				if ($element->firstChild->nodeType == XML_TEXT_NODE) {
225
-					$element->firstChild->data =
226
-						preg_replace('{^\s+}', "\n", $element->firstChild->data);
227
-				}
228
-				else {
229
-					$element->insertBefore(new DOMText("\n"), $element->firstChild);
230
-				}
231
-			}
232
-			if ($element->lastChild) {
233
-				if ($element->lastChild->nodeType == XML_TEXT_NODE) {
234
-					$element->lastChild->data =
235
-						preg_replace('{\s+$}', "\n", $element->lastChild->data);
236
-				}
237
-				else {
238
-					$element->insertBefore(new DOMText("\n"), null);
239
-				}
240
-			}
241
-		}
242
-	}
209
+                case XML_TEXT_NODE:
210
+                    if (!$whitespace_preserve) {
211
+                        if (trim($node->data) === "") {
212
+                            $node->data = $whitespace;
213
+                        }
214
+                        else {
215
+                            $node->data = preg_replace('{\s+}', ' ', $node->data);
216
+                        }
217
+                    }
218
+                    break;
219
+            }
220
+        }
221
+        if (!$whitespace_preserve &&
222
+            ($whitespace === "\n\n" || $whitespace === "\n")) {
223
+            if ($element->firstChild) {
224
+                if ($element->firstChild->nodeType == XML_TEXT_NODE) {
225
+                    $element->firstChild->data =
226
+                        preg_replace('{^\s+}', "\n", $element->firstChild->data);
227
+                }
228
+                else {
229
+                    $element->insertBefore(new DOMText("\n"), $element->firstChild);
230
+                }
231
+            }
232
+            if ($element->lastChild) {
233
+                if ($element->lastChild->nodeType == XML_TEXT_NODE) {
234
+                    $element->lastChild->data =
235
+                        preg_replace('{\s+$}', "\n", $element->lastChild->data);
236
+                }
237
+                else {
238
+                    $element->insertBefore(new DOMText("\n"), null);
239
+                }
240
+            }
241
+        }
242
+    }
243 243
 
244
-	/**
245
-	 * @param DOMElement $element Modifies this element by reference
246
-	 */
247
-	protected static function normalizeElementAttributes (DOMElement $element)
248
-	{
249
-		#
250
-		# Sort attributes by name.
251
-		#
252
-		// Gather the list of attributes as an array.
253
-		$attr_list = array();
254
-		foreach ($element->attributes as $attr_node) {
255
-			$attr_list[$attr_node->name] = $attr_node;
256
-		}
244
+    /**
245
+     * @param DOMElement $element Modifies this element by reference
246
+     */
247
+    protected static function normalizeElementAttributes (DOMElement $element)
248
+    {
249
+        #
250
+        # Sort attributes by name.
251
+        #
252
+        // Gather the list of attributes as an array.
253
+        $attr_list = array();
254
+        foreach ($element->attributes as $attr_node) {
255
+            $attr_list[$attr_node->name] = $attr_node;
256
+        }
257 257
 
258
-		// Sort attribute list by name.
259
-		ksort($attr_list);
258
+        // Sort attribute list by name.
259
+        ksort($attr_list);
260 260
 
261
-		// Remove then put back each attribute following sort order.
262
-		foreach ($attr_list as $attr_node) {
263
-			$element->removeAttributeNode($attr_node);
264
-			$element->setAttributeNode($attr_node);
265
-		}
266
-	}
261
+        // Remove then put back each attribute following sort order.
262
+        foreach ($attr_list as $attr_node) {
263
+            $element->removeAttributeNode($attr_node);
264
+            $element->setAttributeNode($attr_node);
265
+        }
266
+    }
267 267
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -244,7 +244,7 @@
 block discarded – undo
244 244
 	/**
245 245
 	 * @param DOMElement $element Modifies this element by reference
246 246
 	 */
247
-	protected static function normalizeElementAttributes (DOMElement $element)
247
+	protected static function normalizeElementAttributes(DOMElement $element)
248 248
 	{
249 249
 		#
250 250
 		# Sort attributes by name.
Please login to merge, or discard this patch.
Braces   +3 added lines, -6 removed lines patch added patch discarded remove patch
@@ -210,8 +210,7 @@  discard block
 block discarded – undo
210 210
 					if (!$whitespace_preserve) {
211 211
 						if (trim($node->data) === "") {
212 212
 							$node->data = $whitespace;
213
-						}
214
-						else {
213
+						} else {
215 214
 							$node->data = preg_replace('{\s+}', ' ', $node->data);
216 215
 						}
217 216
 					}
@@ -224,8 +223,7 @@  discard block
 block discarded – undo
224 223
 				if ($element->firstChild->nodeType == XML_TEXT_NODE) {
225 224
 					$element->firstChild->data =
226 225
 						preg_replace('{^\s+}', "\n", $element->firstChild->data);
227
-				}
228
-				else {
226
+				} else {
229 227
 					$element->insertBefore(new DOMText("\n"), $element->firstChild);
230 228
 				}
231 229
 			}
@@ -233,8 +231,7 @@  discard block
 block discarded – undo
233 231
 				if ($element->lastChild->nodeType == XML_TEXT_NODE) {
234 232
 					$element->lastChild->data =
235 233
 						preg_replace('{\s+$}', "\n", $element->lastChild->data);
236
-				}
237
-				else {
234
+				} else {
238 235
 					$element->insertBefore(new DOMText("\n"), null);
239 236
 				}
240 237
 			}
Please login to merge, or discard this patch.
a/vendor/michelf/php-markdown/test/unit/MarkdownExtraTest.php 1 patch
Indentation   +46 added lines, -46 removed lines patch added patch discarded remove patch
@@ -2,50 +2,50 @@
 block discarded – undo
2 2
 
3 3
 class MarkdownExtraTest extends \PHPUnit\Framework\TestCase
4 4
 {
5
-	public function testSetupOfPredefinedAttributes()
6
-	{
7
-		$obj = new \Michelf\MarkdownExtra();
8
-
9
-		// Allows custom expansions of arreviations to their full version with the abbr tag
10
-		$obj->predef_abbr = array(
11
-			'foo' => 'foobar-test',
12
-		);
13
-		$result = $obj->transform('**Hello world, foo**');
14
-
15
-		$this->assertSame(
16
-			'<p><strong>Hello world, <abbr title="foobar-test">foo</abbr></strong></p>',
17
-			trim($result)
18
-		);
19
-	}
20
-
21
-	public function testSetupOfMultiplePredefinedAttributes()
22
-	{
23
-		$obj = new \Michelf\MarkdownExtra();
24
-
25
-		// Allows custom expansions of arreviations to their full version with the abbr tag
26
-		$obj->predef_abbr = array(
27
-			'foo' => 'foobar-test',
28
-			'ISP' => 'Internet Service Provider',
29
-		);
30
-		$result = $obj->transform('**I get internet from an ISP. foo.**');
31
-
32
-		$this->assertSame(
33
-			'<p><strong>I get internet from an <abbr title="Internet Service Provider">ISP' .
34
-			'</abbr>. <abbr title="foobar-test">foo</abbr>.</strong></p>',
35
-			trim($result)
36
-		);
37
-	}
38
-
39
-	public function testTransformWithNoMarkup()
40
-	{
41
-		$obj = new \Michelf\MarkdownExtra();
42
-		$obj->no_markup = true;
43
-
44
-		$result = $obj->transform('This is a <strong class="custom">no markup</strong> test.');
45
-
46
-		$this->assertSame(
47
-			'<p>This is a &lt;strong class="custom">no markup&lt;/strong> test.</p>',
48
-			trim($result)
49
-		);
50
-	}
5
+    public function testSetupOfPredefinedAttributes()
6
+    {
7
+        $obj = new \Michelf\MarkdownExtra();
8
+
9
+        // Allows custom expansions of arreviations to their full version with the abbr tag
10
+        $obj->predef_abbr = array(
11
+            'foo' => 'foobar-test',
12
+        );
13
+        $result = $obj->transform('**Hello world, foo**');
14
+
15
+        $this->assertSame(
16
+            '<p><strong>Hello world, <abbr title="foobar-test">foo</abbr></strong></p>',
17
+            trim($result)
18
+        );
19
+    }
20
+
21
+    public function testSetupOfMultiplePredefinedAttributes()
22
+    {
23
+        $obj = new \Michelf\MarkdownExtra();
24
+
25
+        // Allows custom expansions of arreviations to their full version with the abbr tag
26
+        $obj->predef_abbr = array(
27
+            'foo' => 'foobar-test',
28
+            'ISP' => 'Internet Service Provider',
29
+        );
30
+        $result = $obj->transform('**I get internet from an ISP. foo.**');
31
+
32
+        $this->assertSame(
33
+            '<p><strong>I get internet from an <abbr title="Internet Service Provider">ISP' .
34
+            '</abbr>. <abbr title="foobar-test">foo</abbr>.</strong></p>',
35
+            trim($result)
36
+        );
37
+    }
38
+
39
+    public function testTransformWithNoMarkup()
40
+    {
41
+        $obj = new \Michelf\MarkdownExtra();
42
+        $obj->no_markup = true;
43
+
44
+        $result = $obj->transform('This is a <strong class="custom">no markup</strong> test.');
45
+
46
+        $this->assertSame(
47
+            '<p>This is a &lt;strong class="custom">no markup&lt;/strong> test.</p>',
48
+            trim($result)
49
+        );
50
+    }
51 51
 }
Please login to merge, or discard this patch.
a/vendor/michelf/php-markdown/Michelf/Markdown.php 3 patches
Indentation   +1551 added lines, -1551 removed lines patch added patch discarded remove patch
@@ -14,275 +14,275 @@  discard block
 block discarded – undo
14 14
  * Markdown Parser Class
15 15
  */
16 16
 class Markdown implements MarkdownInterface {
17
-	/**
18
-	 * Define the package version
19
-	 * @var string
20
-	 */
21
-	const MARKDOWNLIB_VERSION = "1.9.0";
22
-
23
-	/**
24
-	 * Simple function interface - Initialize the parser and return the result
25
-	 * of its transform method. This will work fine for derived classes too.
26
-	 *
27
-	 * @api
28
-	 *
29
-	 * @param  string $text
30
-	 * @return string
31
-	 */
32
-	public static function defaultTransform($text) {
33
-		// Take parser class on which this function was called.
34
-		$parser_class = \get_called_class();
35
-
36
-		// Try to take parser from the static parser list
37
-		static $parser_list;
38
-		$parser =& $parser_list[$parser_class];
39
-
40
-		// Create the parser it not already set
41
-		if (!$parser) {
42
-			$parser = new $parser_class;
43
-		}
44
-
45
-		// Transform text using parser.
46
-		return $parser->transform($text);
47
-	}
48
-
49
-	/**
50
-	 * Configuration variables
51
-	 */
52
-
53
-	/**
54
-	 * Change to ">" for HTML output.
55
-	 * @var string
56
-	 */
57
-	public $empty_element_suffix = " />";
58
-
59
-	/**
60
-	 * The width of indentation of the output markup
61
-	 * @var int
62
-	 */
63
-	public $tab_width = 4;
64
-
65
-	/**
66
-	 * Change to `true` to disallow markup or entities.
67
-	 * @var boolean
68
-	 */
69
-	public $no_markup   = false;
70
-	public $no_entities = false;
71
-
72
-
73
-	/**
74
-	 * Change to `true` to enable line breaks on \n without two trailling spaces
75
-	 * @var boolean
76
-	 */
77
-	public $hard_wrap = false;
78
-
79
-	/**
80
-	 * Predefined URLs and titles for reference links and images.
81
-	 * @var array
82
-	 */
83
-	public $predef_urls   = array();
84
-	public $predef_titles = array();
85
-
86
-	/**
87
-	 * Optional filter function for URLs
88
-	 * @var callable|null
89
-	 */
90
-	public $url_filter_func = null;
91
-
92
-	/**
93
-	 * Optional header id="" generation callback function.
94
-	 * @var callable|null
95
-	 */
96
-	public $header_id_func = null;
97
-
98
-	/**
99
-	 * Optional function for converting code block content to HTML
100
-	 * @var callable|null
101
-	 */
102
-	public $code_block_content_func = null;
103
-
104
-	/**
105
-	 * Optional function for converting code span content to HTML.
106
-	 * @var callable|null
107
-	 */
108
-	public $code_span_content_func = null;
109
-
110
-	/**
111
-	 * Class attribute to toggle "enhanced ordered list" behaviour
112
-	 * setting this to true will allow ordered lists to start from the index
113
-	 * number that is defined first.
114
-	 *
115
-	 * For example:
116
-	 * 2. List item two
117
-	 * 3. List item three
118
-	 *
119
-	 * Becomes:
120
-	 * <ol start="2">
121
-	 * <li>List item two</li>
122
-	 * <li>List item three</li>
123
-	 * </ol>
124
-	 *
125
-	 * @var bool
126
-	 */
127
-	public $enhanced_ordered_list = false;
128
-
129
-	/**
130
-	 * Parser implementation
131
-	 */
132
-
133
-	/**
134
-	 * Regex to match balanced [brackets].
135
-	 * Needed to insert a maximum bracked depth while converting to PHP.
136
-	 * @var int
137
-	 */
138
-	protected $nested_brackets_depth = 6;
139
-	protected $nested_brackets_re;
140
-
141
-	protected $nested_url_parenthesis_depth = 4;
142
-	protected $nested_url_parenthesis_re;
143
-
144
-	/**
145
-	 * Table of hash values for escaped characters:
146
-	 * @var string
147
-	 */
148
-	protected $escape_chars = '\`*_{}[]()>#+-.!';
149
-	protected $escape_chars_re;
150
-
151
-	/**
152
-	 * Constructor function. Initialize appropriate member variables.
153
-	 * @return void
154
-	 */
155
-	public function __construct() {
156
-		$this->_initDetab();
157
-		$this->prepareItalicsAndBold();
158
-
159
-		$this->nested_brackets_re =
160
-			str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
161
-			str_repeat('\])*', $this->nested_brackets_depth);
162
-
163
-		$this->nested_url_parenthesis_re =
164
-			str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
165
-			str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
166
-
167
-		$this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
168
-
169
-		// Sort document, block, and span gamut in ascendent priority order.
170
-		asort($this->document_gamut);
171
-		asort($this->block_gamut);
172
-		asort($this->span_gamut);
173
-	}
174
-
175
-
176
-	/**
177
-	 * Internal hashes used during transformation.
178
-	 * @var array
179
-	 */
180
-	protected $urls        = array();
181
-	protected $titles      = array();
182
-	protected $html_hashes = array();
183
-
184
-	/**
185
-	 * Status flag to avoid invalid nesting.
186
-	 * @var boolean
187
-	 */
188
-	protected $in_anchor = false;
189
-
190
-	/**
191
-	 * Status flag to avoid invalid nesting.
192
-	 * @var boolean
193
-	 */
194
-	protected $in_emphasis_processing = false;
195
-
196
-	/**
197
-	 * Called before the transformation process starts to setup parser states.
198
-	 * @return void
199
-	 */
200
-	protected function setup() {
201
-		// Clear global hashes.
202
-		$this->urls        = $this->predef_urls;
203
-		$this->titles      = $this->predef_titles;
204
-		$this->html_hashes = array();
205
-		$this->in_anchor   = false;
206
-		$this->in_emphasis_processing = false;
207
-	}
208
-
209
-	/**
210
-	 * Called after the transformation process to clear any variable which may
211
-	 * be taking up memory unnecessarly.
212
-	 * @return void
213
-	 */
214
-	protected function teardown() {
215
-		$this->urls        = array();
216
-		$this->titles      = array();
217
-		$this->html_hashes = array();
218
-	}
219
-
220
-	/**
221
-	 * Main function. Performs some preprocessing on the input text and pass
222
-	 * it through the document gamut.
223
-	 *
224
-	 * @api
225
-	 *
226
-	 * @param  string $text
227
-	 * @return string
228
-	 */
229
-	public function transform($text) {
230
-		$this->setup();
231
-
232
-		# Remove UTF-8 BOM and marker character in input, if present.
233
-		$text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
234
-
235
-		# Standardize line endings:
236
-		#   DOS to Unix and Mac to Unix
237
-		$text = preg_replace('{\r\n?}', "\n", $text);
238
-
239
-		# Make sure $text ends with a couple of newlines:
240
-		$text .= "\n\n";
241
-
242
-		# Convert all tabs to spaces.
243
-		$text = $this->detab($text);
244
-
245
-		# Turn block-level HTML blocks into hash entries
246
-		$text = $this->hashHTMLBlocks($text);
247
-
248
-		# Strip any lines consisting only of spaces and tabs.
249
-		# This makes subsequent regexen easier to write, because we can
250
-		# match consecutive blank lines with /\n+/ instead of something
251
-		# contorted like /[ ]*\n+/ .
252
-		$text = preg_replace('/^[ ]+$/m', '', $text);
253
-
254
-		# Run document gamut methods.
255
-		foreach ($this->document_gamut as $method => $priority) {
256
-			$text = $this->$method($text);
257
-		}
258
-
259
-		$this->teardown();
260
-
261
-		return $text . "\n";
262
-	}
263
-
264
-	/**
265
-	 * Define the document gamut
266
-	 * @var array
267
-	 */
268
-	protected $document_gamut = array(
269
-		// Strip link definitions, store in hashes.
270
-		"stripLinkDefinitions" => 20,
271
-		"runBasicBlockGamut"   => 30,
272
-	);
273
-
274
-	/**
275
-	 * Strips link definitions from text, stores the URLs and titles in
276
-	 * hash references
277
-	 * @param  string $text
278
-	 * @return string
279
-	 */
280
-	protected function stripLinkDefinitions($text) {
281
-
282
-		$less_than_tab = $this->tab_width - 1;
283
-
284
-		// Link defs are in the form: ^[id]: url "optional title"
285
-		$text = preg_replace_callback('{
17
+    /**
18
+     * Define the package version
19
+     * @var string
20
+     */
21
+    const MARKDOWNLIB_VERSION = "1.9.0";
22
+
23
+    /**
24
+     * Simple function interface - Initialize the parser and return the result
25
+     * of its transform method. This will work fine for derived classes too.
26
+     *
27
+     * @api
28
+     *
29
+     * @param  string $text
30
+     * @return string
31
+     */
32
+    public static function defaultTransform($text) {
33
+        // Take parser class on which this function was called.
34
+        $parser_class = \get_called_class();
35
+
36
+        // Try to take parser from the static parser list
37
+        static $parser_list;
38
+        $parser =& $parser_list[$parser_class];
39
+
40
+        // Create the parser it not already set
41
+        if (!$parser) {
42
+            $parser = new $parser_class;
43
+        }
44
+
45
+        // Transform text using parser.
46
+        return $parser->transform($text);
47
+    }
48
+
49
+    /**
50
+     * Configuration variables
51
+     */
52
+
53
+    /**
54
+     * Change to ">" for HTML output.
55
+     * @var string
56
+     */
57
+    public $empty_element_suffix = " />";
58
+
59
+    /**
60
+     * The width of indentation of the output markup
61
+     * @var int
62
+     */
63
+    public $tab_width = 4;
64
+
65
+    /**
66
+     * Change to `true` to disallow markup or entities.
67
+     * @var boolean
68
+     */
69
+    public $no_markup   = false;
70
+    public $no_entities = false;
71
+
72
+
73
+    /**
74
+     * Change to `true` to enable line breaks on \n without two trailling spaces
75
+     * @var boolean
76
+     */
77
+    public $hard_wrap = false;
78
+
79
+    /**
80
+     * Predefined URLs and titles for reference links and images.
81
+     * @var array
82
+     */
83
+    public $predef_urls   = array();
84
+    public $predef_titles = array();
85
+
86
+    /**
87
+     * Optional filter function for URLs
88
+     * @var callable|null
89
+     */
90
+    public $url_filter_func = null;
91
+
92
+    /**
93
+     * Optional header id="" generation callback function.
94
+     * @var callable|null
95
+     */
96
+    public $header_id_func = null;
97
+
98
+    /**
99
+     * Optional function for converting code block content to HTML
100
+     * @var callable|null
101
+     */
102
+    public $code_block_content_func = null;
103
+
104
+    /**
105
+     * Optional function for converting code span content to HTML.
106
+     * @var callable|null
107
+     */
108
+    public $code_span_content_func = null;
109
+
110
+    /**
111
+     * Class attribute to toggle "enhanced ordered list" behaviour
112
+     * setting this to true will allow ordered lists to start from the index
113
+     * number that is defined first.
114
+     *
115
+     * For example:
116
+     * 2. List item two
117
+     * 3. List item three
118
+     *
119
+     * Becomes:
120
+     * <ol start="2">
121
+     * <li>List item two</li>
122
+     * <li>List item three</li>
123
+     * </ol>
124
+     *
125
+     * @var bool
126
+     */
127
+    public $enhanced_ordered_list = false;
128
+
129
+    /**
130
+     * Parser implementation
131
+     */
132
+
133
+    /**
134
+     * Regex to match balanced [brackets].
135
+     * Needed to insert a maximum bracked depth while converting to PHP.
136
+     * @var int
137
+     */
138
+    protected $nested_brackets_depth = 6;
139
+    protected $nested_brackets_re;
140
+
141
+    protected $nested_url_parenthesis_depth = 4;
142
+    protected $nested_url_parenthesis_re;
143
+
144
+    /**
145
+     * Table of hash values for escaped characters:
146
+     * @var string
147
+     */
148
+    protected $escape_chars = '\`*_{}[]()>#+-.!';
149
+    protected $escape_chars_re;
150
+
151
+    /**
152
+     * Constructor function. Initialize appropriate member variables.
153
+     * @return void
154
+     */
155
+    public function __construct() {
156
+        $this->_initDetab();
157
+        $this->prepareItalicsAndBold();
158
+
159
+        $this->nested_brackets_re =
160
+            str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
161
+            str_repeat('\])*', $this->nested_brackets_depth);
162
+
163
+        $this->nested_url_parenthesis_re =
164
+            str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
165
+            str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
166
+
167
+        $this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
168
+
169
+        // Sort document, block, and span gamut in ascendent priority order.
170
+        asort($this->document_gamut);
171
+        asort($this->block_gamut);
172
+        asort($this->span_gamut);
173
+    }
174
+
175
+
176
+    /**
177
+     * Internal hashes used during transformation.
178
+     * @var array
179
+     */
180
+    protected $urls        = array();
181
+    protected $titles      = array();
182
+    protected $html_hashes = array();
183
+
184
+    /**
185
+     * Status flag to avoid invalid nesting.
186
+     * @var boolean
187
+     */
188
+    protected $in_anchor = false;
189
+
190
+    /**
191
+     * Status flag to avoid invalid nesting.
192
+     * @var boolean
193
+     */
194
+    protected $in_emphasis_processing = false;
195
+
196
+    /**
197
+     * Called before the transformation process starts to setup parser states.
198
+     * @return void
199
+     */
200
+    protected function setup() {
201
+        // Clear global hashes.
202
+        $this->urls        = $this->predef_urls;
203
+        $this->titles      = $this->predef_titles;
204
+        $this->html_hashes = array();
205
+        $this->in_anchor   = false;
206
+        $this->in_emphasis_processing = false;
207
+    }
208
+
209
+    /**
210
+     * Called after the transformation process to clear any variable which may
211
+     * be taking up memory unnecessarly.
212
+     * @return void
213
+     */
214
+    protected function teardown() {
215
+        $this->urls        = array();
216
+        $this->titles      = array();
217
+        $this->html_hashes = array();
218
+    }
219
+
220
+    /**
221
+     * Main function. Performs some preprocessing on the input text and pass
222
+     * it through the document gamut.
223
+     *
224
+     * @api
225
+     *
226
+     * @param  string $text
227
+     * @return string
228
+     */
229
+    public function transform($text) {
230
+        $this->setup();
231
+
232
+        # Remove UTF-8 BOM and marker character in input, if present.
233
+        $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
234
+
235
+        # Standardize line endings:
236
+        #   DOS to Unix and Mac to Unix
237
+        $text = preg_replace('{\r\n?}', "\n", $text);
238
+
239
+        # Make sure $text ends with a couple of newlines:
240
+        $text .= "\n\n";
241
+
242
+        # Convert all tabs to spaces.
243
+        $text = $this->detab($text);
244
+
245
+        # Turn block-level HTML blocks into hash entries
246
+        $text = $this->hashHTMLBlocks($text);
247
+
248
+        # Strip any lines consisting only of spaces and tabs.
249
+        # This makes subsequent regexen easier to write, because we can
250
+        # match consecutive blank lines with /\n+/ instead of something
251
+        # contorted like /[ ]*\n+/ .
252
+        $text = preg_replace('/^[ ]+$/m', '', $text);
253
+
254
+        # Run document gamut methods.
255
+        foreach ($this->document_gamut as $method => $priority) {
256
+            $text = $this->$method($text);
257
+        }
258
+
259
+        $this->teardown();
260
+
261
+        return $text . "\n";
262
+    }
263
+
264
+    /**
265
+     * Define the document gamut
266
+     * @var array
267
+     */
268
+    protected $document_gamut = array(
269
+        // Strip link definitions, store in hashes.
270
+        "stripLinkDefinitions" => 20,
271
+        "runBasicBlockGamut"   => 30,
272
+    );
273
+
274
+    /**
275
+     * Strips link definitions from text, stores the URLs and titles in
276
+     * hash references
277
+     * @param  string $text
278
+     * @return string
279
+     */
280
+    protected function stripLinkDefinitions($text) {
281
+
282
+        $less_than_tab = $this->tab_width - 1;
283
+
284
+        // Link defs are in the form: ^[id]: url "optional title"
285
+        $text = preg_replace_callback('{
286 286
 							^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?:	# id = $1
287 287
 							  [ ]*
288 288
 							  \n?				# maybe *one* newline
@@ -304,61 +304,61 @@  discard block
 block discarded – undo
304 304
 							)?	# title is optional
305 305
 							(?:\n+|\Z)
306 306
 			}xm',
307
-			array($this, '_stripLinkDefinitions_callback'),
308
-			$text
309
-		);
310
-		return $text;
311
-	}
312
-
313
-	/**
314
-	 * The callback to strip link definitions
315
-	 * @param  array $matches
316
-	 * @return string
317
-	 */
318
-	protected function _stripLinkDefinitions_callback($matches) {
319
-		$link_id = strtolower($matches[1]);
320
-		$url = $matches[2] == '' ? $matches[3] : $matches[2];
321
-		$this->urls[$link_id] = $url;
322
-		$this->titles[$link_id] =& $matches[4];
323
-		return ''; // String that will replace the block
324
-	}
325
-
326
-	/**
327
-	 * Hashify HTML blocks
328
-	 * @param  string $text
329
-	 * @return string
330
-	 */
331
-	protected function hashHTMLBlocks($text) {
332
-		if ($this->no_markup) {
333
-			return $text;
334
-		}
335
-
336
-		$less_than_tab = $this->tab_width - 1;
337
-
338
-		/**
339
-		 * Hashify HTML blocks:
340
-		 *
341
-		 * We only want to do this for block-level HTML tags, such as headers,
342
-		 * lists, and tables. That's because we still want to wrap <p>s around
343
-		 * "paragraphs" that are wrapped in non-block-level tags, such as
344
-		 * anchors, phrase emphasis, and spans. The list of tags we're looking
345
-		 * for is hard-coded:
346
-		 *
347
-		 * *  List "a" is made of tags which can be both inline or block-level.
348
-		 *    These will be treated block-level when the start tag is alone on
349
-		 *    its line, otherwise they're not matched here and will be taken as
350
-		 *    inline later.
351
-		 * *  List "b" is made of tags which are always block-level;
352
-		 */
353
-		$block_tags_a_re = 'ins|del';
354
-		$block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
355
-						   'script|noscript|style|form|fieldset|iframe|math|svg|'.
356
-						   'article|section|nav|aside|hgroup|header|footer|'.
357
-						   'figure';
358
-
359
-		// Regular expression for the content of a block tag.
360
-		$nested_tags_level = 4;
361
-		$attr = '
307
+            array($this, '_stripLinkDefinitions_callback'),
308
+            $text
309
+        );
310
+        return $text;
311
+    }
312
+
313
+    /**
314
+     * The callback to strip link definitions
315
+     * @param  array $matches
316
+     * @return string
317
+     */
318
+    protected function _stripLinkDefinitions_callback($matches) {
319
+        $link_id = strtolower($matches[1]);
320
+        $url = $matches[2] == '' ? $matches[3] : $matches[2];
321
+        $this->urls[$link_id] = $url;
322
+        $this->titles[$link_id] =& $matches[4];
323
+        return ''; // String that will replace the block
324
+    }
325
+
326
+    /**
327
+     * Hashify HTML blocks
328
+     * @param  string $text
329
+     * @return string
330
+     */
331
+    protected function hashHTMLBlocks($text) {
332
+        if ($this->no_markup) {
333
+            return $text;
334
+        }
335
+
336
+        $less_than_tab = $this->tab_width - 1;
337
+
338
+        /**
339
+         * Hashify HTML blocks:
340
+         *
341
+         * We only want to do this for block-level HTML tags, such as headers,
342
+         * lists, and tables. That's because we still want to wrap <p>s around
343
+         * "paragraphs" that are wrapped in non-block-level tags, such as
344
+         * anchors, phrase emphasis, and spans. The list of tags we're looking
345
+         * for is hard-coded:
346
+         *
347
+         * *  List "a" is made of tags which can be both inline or block-level.
348
+         *    These will be treated block-level when the start tag is alone on
349
+         *    its line, otherwise they're not matched here and will be taken as
350
+         *    inline later.
351
+         * *  List "b" is made of tags which are always block-level;
352
+         */
353
+        $block_tags_a_re = 'ins|del';
354
+        $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
355
+                            'script|noscript|style|form|fieldset|iframe|math|svg|'.
356
+                            'article|section|nav|aside|hgroup|header|footer|'.
357
+                            'figure';
358
+
359
+        // Regular expression for the content of a block tag.
360
+        $nested_tags_level = 4;
361
+        $attr = '
362 362
 			(?>				# optional tag attributes
363 363
 			  \s			# starts with whitespace
364 364
 			  (?>
@@ -372,8 +372,8 @@  discard block
 block discarded – undo
372 372
 			  )*
373 373
 			)?
374 374
 			';
375
-		$content =
376
-			str_repeat('
375
+        $content =
376
+            str_repeat('
377 377
 				(?>
378 378
 				  [^<]+			# content without tag
379 379
 				|
@@ -383,32 +383,32 @@  discard block
 block discarded – undo
383 383
 					  />
384 384
 					|
385 385
 					  >', $nested_tags_level).	// end of opening tag
386
-					  '.*?'.					// last level nested tag content
387
-			str_repeat('
386
+                        '.*?'.					// last level nested tag content
387
+            str_repeat('
388 388
 					  </\2\s*>	# closing nested tag
389 389
 					)
390 390
 				  |
391 391
 					<(?!/\2\s*>	# other tags with a different name
392 392
 				  )
393 393
 				)*',
394
-				$nested_tags_level);
395
-		$content2 = str_replace('\2', '\3', $content);
396
-
397
-		/**
398
-		 * First, look for nested blocks, e.g.:
399
-		 * 	<div>
400
-		 * 		<div>
401
-		 * 		tags for inner block must be indented.
402
-		 * 		</div>
403
-		 * 	</div>
404
-		 *
405
-		 * The outermost tags must start at the left margin for this to match,
406
-		 * and the inner nested divs must be indented.
407
-		 * We need to do this before the next, more liberal match, because the
408
-		 * next match will start at the first `<div>` and stop at the
409
-		 * first `</div>`.
410
-		 */
411
-		$text = preg_replace_callback('{(?>
394
+                $nested_tags_level);
395
+        $content2 = str_replace('\2', '\3', $content);
396
+
397
+        /**
398
+         * First, look for nested blocks, e.g.:
399
+         * 	<div>
400
+         * 		<div>
401
+         * 		tags for inner block must be indented.
402
+         * 		</div>
403
+         * 	</div>
404
+         *
405
+         * The outermost tags must start at the left margin for this to match,
406
+         * and the inner nested divs must be indented.
407
+         * We need to do this before the next, more liberal match, because the
408
+         * next match will start at the first `<div>` and stop at the
409
+         * first `</div>`.
410
+         */
411
+        $text = preg_replace_callback('{(?>
412 412
 			(?>
413 413
 				(?<=\n)			# Starting on its own line
414 414
 				|				# or
@@ -469,117 +469,117 @@  discard block
 block discarded – undo
469 469
 
470 470
 			)
471 471
 			)}Sxmi',
472
-			array($this, '_hashHTMLBlocks_callback'),
473
-			$text
474
-		);
475
-
476
-		return $text;
477
-	}
478
-
479
-	/**
480
-	 * The callback for hashing HTML blocks
481
-	 * @param  string $matches
482
-	 * @return string
483
-	 */
484
-	protected function _hashHTMLBlocks_callback($matches) {
485
-		$text = $matches[1];
486
-		$key  = $this->hashBlock($text);
487
-		return "\n\n$key\n\n";
488
-	}
489
-
490
-	/**
491
-	 * Called whenever a tag must be hashed when a function insert an atomic
492
-	 * element in the text stream. Passing $text to through this function gives
493
-	 * a unique text-token which will be reverted back when calling unhash.
494
-	 *
495
-	 * The $boundary argument specify what character should be used to surround
496
-	 * the token. By convension, "B" is used for block elements that needs not
497
-	 * to be wrapped into paragraph tags at the end, ":" is used for elements
498
-	 * that are word separators and "X" is used in the general case.
499
-	 *
500
-	 * @param  string $text
501
-	 * @param  string $boundary
502
-	 * @return string
503
-	 */
504
-	protected function hashPart($text, $boundary = 'X') {
505
-		// Swap back any tag hash found in $text so we do not have to `unhash`
506
-		// multiple times at the end.
507
-		$text = $this->unhash($text);
508
-
509
-		// Then hash the block.
510
-		static $i = 0;
511
-		$key = "$boundary\x1A" . ++$i . $boundary;
512
-		$this->html_hashes[$key] = $text;
513
-		return $key; // String that will replace the tag.
514
-	}
515
-
516
-	/**
517
-	 * Shortcut function for hashPart with block-level boundaries.
518
-	 * @param  string $text
519
-	 * @return string
520
-	 */
521
-	protected function hashBlock($text) {
522
-		return $this->hashPart($text, 'B');
523
-	}
524
-
525
-	/**
526
-	 * Define the block gamut - these are all the transformations that form
527
-	 * block-level tags like paragraphs, headers, and list items.
528
-	 * @var array
529
-	 */
530
-	protected $block_gamut = array(
531
-		"doHeaders"         => 10,
532
-		"doHorizontalRules" => 20,
533
-		"doLists"           => 40,
534
-		"doCodeBlocks"      => 50,
535
-		"doBlockQuotes"     => 60,
536
-	);
537
-
538
-	/**
539
-	 * Run block gamut tranformations.
540
-	 *
541
-	 * We need to escape raw HTML in Markdown source before doing anything
542
-	 * else. This need to be done for each block, and not only at the
543
-	 * begining in the Markdown function since hashed blocks can be part of
544
-	 * list items and could have been indented. Indented blocks would have
545
-	 * been seen as a code block in a previous pass of hashHTMLBlocks.
546
-	 *
547
-	 * @param  string $text
548
-	 * @return string
549
-	 */
550
-	protected function runBlockGamut($text) {
551
-		$text = $this->hashHTMLBlocks($text);
552
-		return $this->runBasicBlockGamut($text);
553
-	}
554
-
555
-	/**
556
-	 * Run block gamut tranformations, without hashing HTML blocks. This is
557
-	 * useful when HTML blocks are known to be already hashed, like in the first
558
-	 * whole-document pass.
559
-	 *
560
-	 * @param  string $text
561
-	 * @return string
562
-	 */
563
-	protected function runBasicBlockGamut($text) {
564
-
565
-		foreach ($this->block_gamut as $method => $priority) {
566
-			$text = $this->$method($text);
567
-		}
568
-
569
-		// Finally form paragraph and restore hashed blocks.
570
-		$text = $this->formParagraphs($text);
571
-
572
-		return $text;
573
-	}
574
-
575
-	/**
576
-	 * Convert horizontal rules
577
-	 * @param  string $text
578
-	 * @return string
579
-	 */
580
-	protected function doHorizontalRules($text) {
581
-		return preg_replace(
582
-			'{
472
+            array($this, '_hashHTMLBlocks_callback'),
473
+            $text
474
+        );
475
+
476
+        return $text;
477
+    }
478
+
479
+    /**
480
+     * The callback for hashing HTML blocks
481
+     * @param  string $matches
482
+     * @return string
483
+     */
484
+    protected function _hashHTMLBlocks_callback($matches) {
485
+        $text = $matches[1];
486
+        $key  = $this->hashBlock($text);
487
+        return "\n\n$key\n\n";
488
+    }
489
+
490
+    /**
491
+     * Called whenever a tag must be hashed when a function insert an atomic
492
+     * element in the text stream. Passing $text to through this function gives
493
+     * a unique text-token which will be reverted back when calling unhash.
494
+     *
495
+     * The $boundary argument specify what character should be used to surround
496
+     * the token. By convension, "B" is used for block elements that needs not
497
+     * to be wrapped into paragraph tags at the end, ":" is used for elements
498
+     * that are word separators and "X" is used in the general case.
499
+     *
500
+     * @param  string $text
501
+     * @param  string $boundary
502
+     * @return string
503
+     */
504
+    protected function hashPart($text, $boundary = 'X') {
505
+        // Swap back any tag hash found in $text so we do not have to `unhash`
506
+        // multiple times at the end.
507
+        $text = $this->unhash($text);
508
+
509
+        // Then hash the block.
510
+        static $i = 0;
511
+        $key = "$boundary\x1A" . ++$i . $boundary;
512
+        $this->html_hashes[$key] = $text;
513
+        return $key; // String that will replace the tag.
514
+    }
515
+
516
+    /**
517
+     * Shortcut function for hashPart with block-level boundaries.
518
+     * @param  string $text
519
+     * @return string
520
+     */
521
+    protected function hashBlock($text) {
522
+        return $this->hashPart($text, 'B');
523
+    }
524
+
525
+    /**
526
+     * Define the block gamut - these are all the transformations that form
527
+     * block-level tags like paragraphs, headers, and list items.
528
+     * @var array
529
+     */
530
+    protected $block_gamut = array(
531
+        "doHeaders"         => 10,
532
+        "doHorizontalRules" => 20,
533
+        "doLists"           => 40,
534
+        "doCodeBlocks"      => 50,
535
+        "doBlockQuotes"     => 60,
536
+    );
537
+
538
+    /**
539
+     * Run block gamut tranformations.
540
+     *
541
+     * We need to escape raw HTML in Markdown source before doing anything
542
+     * else. This need to be done for each block, and not only at the
543
+     * begining in the Markdown function since hashed blocks can be part of
544
+     * list items and could have been indented. Indented blocks would have
545
+     * been seen as a code block in a previous pass of hashHTMLBlocks.
546
+     *
547
+     * @param  string $text
548
+     * @return string
549
+     */
550
+    protected function runBlockGamut($text) {
551
+        $text = $this->hashHTMLBlocks($text);
552
+        return $this->runBasicBlockGamut($text);
553
+    }
554
+
555
+    /**
556
+     * Run block gamut tranformations, without hashing HTML blocks. This is
557
+     * useful when HTML blocks are known to be already hashed, like in the first
558
+     * whole-document pass.
559
+     *
560
+     * @param  string $text
561
+     * @return string
562
+     */
563
+    protected function runBasicBlockGamut($text) {
564
+
565
+        foreach ($this->block_gamut as $method => $priority) {
566
+            $text = $this->$method($text);
567
+        }
568
+
569
+        // Finally form paragraph and restore hashed blocks.
570
+        $text = $this->formParagraphs($text);
571
+
572
+        return $text;
573
+    }
574
+
575
+    /**
576
+     * Convert horizontal rules
577
+     * @param  string $text
578
+     * @return string
579
+     */
580
+    protected function doHorizontalRules($text) {
581
+        return preg_replace(
582
+            '{
583 583
 				^[ ]{0,3}	# Leading space
584 584
 				([-*_])		# $1: First marker
585 585
 				(?>			# Repeated marker group
@@ -589,83 +589,83 @@  discard block
 block discarded – undo
589 589
 				[ ]*		# Tailing spaces
590 590
 				$			# End of line.
591 591
 			}mx',
592
-			"\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n",
593
-			$text
594
-		);
595
-	}
596
-
597
-	/**
598
-	 * These are all the transformations that occur *within* block-level
599
-	 * tags like paragraphs, headers, and list items.
600
-	 * @var array
601
-	 */
602
-	protected $span_gamut = array(
603
-		// Process character escapes, code spans, and inline HTML
604
-		// in one shot.
605
-		"parseSpan"           => -30,
606
-		// Process anchor and image tags. Images must come first,
607
-		// because ![foo][f] looks like an anchor.
608
-		"doImages"            =>  10,
609
-		"doAnchors"           =>  20,
610
-		// Make links out of things like `<https://example.com/>`
611
-		// Must come after doAnchors, because you can use < and >
612
-		// delimiters in inline links like [this](<url>).
613
-		"doAutoLinks"         =>  30,
614
-		"encodeAmpsAndAngles" =>  40,
615
-		"doItalicsAndBold"    =>  50,
616
-		"doHardBreaks"        =>  60,
617
-	);
618
-
619
-	/**
620
-	 * Run span gamut transformations
621
-	 * @param  string $text
622
-	 * @return string
623
-	 */
624
-	protected function runSpanGamut($text) {
625
-		foreach ($this->span_gamut as $method => $priority) {
626
-			$text = $this->$method($text);
627
-		}
628
-
629
-		return $text;
630
-	}
631
-
632
-	/**
633
-	 * Do hard breaks
634
-	 * @param  string $text
635
-	 * @return string
636
-	 */
637
-	protected function doHardBreaks($text) {
638
-		if ($this->hard_wrap) {
639
-			return preg_replace_callback('/ *\n/',
640
-				array($this, '_doHardBreaks_callback'), $text);
641
-		} else {
642
-			return preg_replace_callback('/ {2,}\n/',
643
-				array($this, '_doHardBreaks_callback'), $text);
644
-		}
645
-	}
646
-
647
-	/**
648
-	 * Trigger part hashing for the hard break (callback method)
649
-	 * @param  array $matches
650
-	 * @return string
651
-	 */
652
-	protected function _doHardBreaks_callback($matches) {
653
-		return $this->hashPart("<br$this->empty_element_suffix\n");
654
-	}
655
-
656
-	/**
657
-	 * Turn Markdown link shortcuts into XHTML <a> tags.
658
-	 * @param  string $text
659
-	 * @return string
660
-	 */
661
-	protected function doAnchors($text) {
662
-		if ($this->in_anchor) {
663
-			return $text;
664
-		}
665
-		$this->in_anchor = true;
666
-
667
-		// First, handle reference-style links: [link text] [id]
668
-		$text = preg_replace_callback('{
592
+            "\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n",
593
+            $text
594
+        );
595
+    }
596
+
597
+    /**
598
+     * These are all the transformations that occur *within* block-level
599
+     * tags like paragraphs, headers, and list items.
600
+     * @var array
601
+     */
602
+    protected $span_gamut = array(
603
+        // Process character escapes, code spans, and inline HTML
604
+        // in one shot.
605
+        "parseSpan"           => -30,
606
+        // Process anchor and image tags. Images must come first,
607
+        // because ![foo][f] looks like an anchor.
608
+        "doImages"            =>  10,
609
+        "doAnchors"           =>  20,
610
+        // Make links out of things like `<https://example.com/>`
611
+        // Must come after doAnchors, because you can use < and >
612
+        // delimiters in inline links like [this](<url>).
613
+        "doAutoLinks"         =>  30,
614
+        "encodeAmpsAndAngles" =>  40,
615
+        "doItalicsAndBold"    =>  50,
616
+        "doHardBreaks"        =>  60,
617
+    );
618
+
619
+    /**
620
+     * Run span gamut transformations
621
+     * @param  string $text
622
+     * @return string
623
+     */
624
+    protected function runSpanGamut($text) {
625
+        foreach ($this->span_gamut as $method => $priority) {
626
+            $text = $this->$method($text);
627
+        }
628
+
629
+        return $text;
630
+    }
631
+
632
+    /**
633
+     * Do hard breaks
634
+     * @param  string $text
635
+     * @return string
636
+     */
637
+    protected function doHardBreaks($text) {
638
+        if ($this->hard_wrap) {
639
+            return preg_replace_callback('/ *\n/',
640
+                array($this, '_doHardBreaks_callback'), $text);
641
+        } else {
642
+            return preg_replace_callback('/ {2,}\n/',
643
+                array($this, '_doHardBreaks_callback'), $text);
644
+        }
645
+    }
646
+
647
+    /**
648
+     * Trigger part hashing for the hard break (callback method)
649
+     * @param  array $matches
650
+     * @return string
651
+     */
652
+    protected function _doHardBreaks_callback($matches) {
653
+        return $this->hashPart("<br$this->empty_element_suffix\n");
654
+    }
655
+
656
+    /**
657
+     * Turn Markdown link shortcuts into XHTML <a> tags.
658
+     * @param  string $text
659
+     * @return string
660
+     */
661
+    protected function doAnchors($text) {
662
+        if ($this->in_anchor) {
663
+            return $text;
664
+        }
665
+        $this->in_anchor = true;
666
+
667
+        // First, handle reference-style links: [link text] [id]
668
+        $text = preg_replace_callback('{
669 669
 			(					# wrap whole match in $1
670 670
 			  \[
671 671
 				('.$this->nested_brackets_re.')	# link text = $2
@@ -679,10 +679,10 @@  discard block
 block discarded – undo
679 679
 			  \]
680 680
 			)
681 681
 			}xs',
682
-			array($this, '_doAnchors_reference_callback'), $text);
682
+            array($this, '_doAnchors_reference_callback'), $text);
683 683
 
684
-		// Next, inline-style links: [link text](url "optional title")
685
-		$text = preg_replace_callback('{
684
+        // Next, inline-style links: [link text](url "optional title")
685
+        $text = preg_replace_callback('{
686 686
 			(				# wrap whole match in $1
687 687
 			  \[
688 688
 				('.$this->nested_brackets_re.')	# link text = $2
@@ -704,102 +704,102 @@  discard block
 block discarded – undo
704 704
 			  \)
705 705
 			)
706 706
 			}xs',
707
-			array($this, '_doAnchors_inline_callback'), $text);
707
+            array($this, '_doAnchors_inline_callback'), $text);
708 708
 
709
-		// Last, handle reference-style shortcuts: [link text]
710
-		// These must come last in case you've also got [link text][1]
711
-		// or [link text](/foo)
712
-		$text = preg_replace_callback('{
709
+        // Last, handle reference-style shortcuts: [link text]
710
+        // These must come last in case you've also got [link text][1]
711
+        // or [link text](/foo)
712
+        $text = preg_replace_callback('{
713 713
 			(					# wrap whole match in $1
714 714
 			  \[
715 715
 				([^\[\]]+)		# link text = $2; can\'t contain [ or ]
716 716
 			  \]
717 717
 			)
718 718
 			}xs',
719
-			array($this, '_doAnchors_reference_callback'), $text);
720
-
721
-		$this->in_anchor = false;
722
-		return $text;
723
-	}
724
-
725
-	/**
726
-	 * Callback method to parse referenced anchors
727
-	 * @param  string $matches
728
-	 * @return string
729
-	 */
730
-	protected function _doAnchors_reference_callback($matches) {
731
-		$whole_match =  $matches[1];
732
-		$link_text   =  $matches[2];
733
-		$link_id     =& $matches[3];
734
-
735
-		if ($link_id == "") {
736
-			// for shortcut links like [this][] or [this].
737
-			$link_id = $link_text;
738
-		}
739
-
740
-		// lower-case and turn embedded newlines into spaces
741
-		$link_id = strtolower($link_id);
742
-		$link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
743
-
744
-		if (isset($this->urls[$link_id])) {
745
-			$url = $this->urls[$link_id];
746
-			$url = $this->encodeURLAttribute($url);
747
-
748
-			$result = "<a href=\"$url\"";
749
-			if ( isset( $this->titles[$link_id] ) ) {
750
-				$title = $this->titles[$link_id];
751
-				$title = $this->encodeAttribute($title);
752
-				$result .=  " title=\"$title\"";
753
-			}
754
-
755
-			$link_text = $this->runSpanGamut($link_text);
756
-			$result .= ">$link_text</a>";
757
-			$result = $this->hashPart($result);
758
-		} else {
759
-			$result = $whole_match;
760
-		}
761
-		return $result;
762
-	}
763
-
764
-	/**
765
-	 * Callback method to parse inline anchors
766
-	 * @param  string $matches
767
-	 * @return string
768
-	 */
769
-	protected function _doAnchors_inline_callback($matches) {
770
-		$link_text		=  $this->runSpanGamut($matches[2]);
771
-		$url			=  $matches[3] === '' ? $matches[4] : $matches[3];
772
-		$title			=& $matches[7];
773
-
774
-		// If the URL was of the form <s p a c e s> it got caught by the HTML
775
-		// tag parser and hashed. Need to reverse the process before using
776
-		// the URL.
777
-		$unhashed = $this->unhash($url);
778
-		if ($unhashed !== $url)
779
-			$url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
780
-
781
-		$url = $this->encodeURLAttribute($url);
782
-
783
-		$result = "<a href=\"$url\"";
784
-		if (isset($title)) {
785
-			$title = $this->encodeAttribute($title);
786
-			$result .=  " title=\"$title\"";
787
-		}
788
-
789
-		$link_text = $this->runSpanGamut($link_text);
790
-		$result .= ">$link_text</a>";
791
-
792
-		return $this->hashPart($result);
793
-	}
794
-
795
-	/**
796
-	 * Turn Markdown image shortcuts into <img> tags.
797
-	 * @param  string $text
798
-	 * @return string
799
-	 */
800
-	protected function doImages($text) {
801
-		// First, handle reference-style labeled images: ![alt text][id]
802
-		$text = preg_replace_callback('{
719
+            array($this, '_doAnchors_reference_callback'), $text);
720
+
721
+        $this->in_anchor = false;
722
+        return $text;
723
+    }
724
+
725
+    /**
726
+     * Callback method to parse referenced anchors
727
+     * @param  string $matches
728
+     * @return string
729
+     */
730
+    protected function _doAnchors_reference_callback($matches) {
731
+        $whole_match =  $matches[1];
732
+        $link_text   =  $matches[2];
733
+        $link_id     =& $matches[3];
734
+
735
+        if ($link_id == "") {
736
+            // for shortcut links like [this][] or [this].
737
+            $link_id = $link_text;
738
+        }
739
+
740
+        // lower-case and turn embedded newlines into spaces
741
+        $link_id = strtolower($link_id);
742
+        $link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
743
+
744
+        if (isset($this->urls[$link_id])) {
745
+            $url = $this->urls[$link_id];
746
+            $url = $this->encodeURLAttribute($url);
747
+
748
+            $result = "<a href=\"$url\"";
749
+            if ( isset( $this->titles[$link_id] ) ) {
750
+                $title = $this->titles[$link_id];
751
+                $title = $this->encodeAttribute($title);
752
+                $result .=  " title=\"$title\"";
753
+            }
754
+
755
+            $link_text = $this->runSpanGamut($link_text);
756
+            $result .= ">$link_text</a>";
757
+            $result = $this->hashPart($result);
758
+        } else {
759
+            $result = $whole_match;
760
+        }
761
+        return $result;
762
+    }
763
+
764
+    /**
765
+     * Callback method to parse inline anchors
766
+     * @param  string $matches
767
+     * @return string
768
+     */
769
+    protected function _doAnchors_inline_callback($matches) {
770
+        $link_text		=  $this->runSpanGamut($matches[2]);
771
+        $url			=  $matches[3] === '' ? $matches[4] : $matches[3];
772
+        $title			=& $matches[7];
773
+
774
+        // If the URL was of the form <s p a c e s> it got caught by the HTML
775
+        // tag parser and hashed. Need to reverse the process before using
776
+        // the URL.
777
+        $unhashed = $this->unhash($url);
778
+        if ($unhashed !== $url)
779
+            $url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
780
+
781
+        $url = $this->encodeURLAttribute($url);
782
+
783
+        $result = "<a href=\"$url\"";
784
+        if (isset($title)) {
785
+            $title = $this->encodeAttribute($title);
786
+            $result .=  " title=\"$title\"";
787
+        }
788
+
789
+        $link_text = $this->runSpanGamut($link_text);
790
+        $result .= ">$link_text</a>";
791
+
792
+        return $this->hashPart($result);
793
+    }
794
+
795
+    /**
796
+     * Turn Markdown image shortcuts into <img> tags.
797
+     * @param  string $text
798
+     * @return string
799
+     */
800
+    protected function doImages($text) {
801
+        // First, handle reference-style labeled images: ![alt text][id]
802
+        $text = preg_replace_callback('{
803 803
 			(				# wrap whole match in $1
804 804
 			  !\[
805 805
 				('.$this->nested_brackets_re.')		# alt text = $2
@@ -814,11 +814,11 @@  discard block
 block discarded – undo
814 814
 
815 815
 			)
816 816
 			}xs',
817
-			array($this, '_doImages_reference_callback'), $text);
817
+            array($this, '_doImages_reference_callback'), $text);
818 818
 
819
-		// Next, handle inline images:  ![alt text](url "optional title")
820
-		// Don't forget: encode * and _
821
-		$text = preg_replace_callback('{
819
+        // Next, handle inline images:  ![alt text](url "optional title")
820
+        // Don't forget: encode * and _
821
+        $text = preg_replace_callback('{
822 822
 			(				# wrap whole match in $1
823 823
 			  !\[
824 824
 				('.$this->nested_brackets_re.')		# alt text = $2
@@ -841,93 +841,93 @@  discard block
 block discarded – undo
841 841
 			  \)
842 842
 			)
843 843
 			}xs',
844
-			array($this, '_doImages_inline_callback'), $text);
845
-
846
-		return $text;
847
-	}
848
-
849
-	/**
850
-	 * Callback to parse references image tags
851
-	 * @param  array $matches
852
-	 * @return string
853
-	 */
854
-	protected function _doImages_reference_callback($matches) {
855
-		$whole_match = $matches[1];
856
-		$alt_text    = $matches[2];
857
-		$link_id     = strtolower($matches[3]);
858
-
859
-		if ($link_id == "") {
860
-			$link_id = strtolower($alt_text); // for shortcut links like ![this][].
861
-		}
862
-
863
-		$alt_text = $this->encodeAttribute($alt_text);
864
-		if (isset($this->urls[$link_id])) {
865
-			$url = $this->encodeURLAttribute($this->urls[$link_id]);
866
-			$result = "<img src=\"$url\" alt=\"$alt_text\"";
867
-			if (isset($this->titles[$link_id])) {
868
-				$title = $this->titles[$link_id];
869
-				$title = $this->encodeAttribute($title);
870
-				$result .=  " title=\"$title\"";
871
-			}
872
-			$result .= $this->empty_element_suffix;
873
-			$result = $this->hashPart($result);
874
-		} else {
875
-			// If there's no such link ID, leave intact:
876
-			$result = $whole_match;
877
-		}
878
-
879
-		return $result;
880
-	}
881
-
882
-	/**
883
-	 * Callback to parse inline image tags
884
-	 * @param  array $matches
885
-	 * @return string
886
-	 */
887
-	protected function _doImages_inline_callback($matches) {
888
-		$whole_match	= $matches[1];
889
-		$alt_text		= $matches[2];
890
-		$url			= $matches[3] == '' ? $matches[4] : $matches[3];
891
-		$title			=& $matches[7];
892
-
893
-		$alt_text = $this->encodeAttribute($alt_text);
894
-		$url = $this->encodeURLAttribute($url);
895
-		$result = "<img src=\"$url\" alt=\"$alt_text\"";
896
-		if (isset($title)) {
897
-			$title = $this->encodeAttribute($title);
898
-			$result .=  " title=\"$title\""; // $title already quoted
899
-		}
900
-		$result .= $this->empty_element_suffix;
901
-
902
-		return $this->hashPart($result);
903
-	}
904
-
905
-	/**
906
-	 * Parse Markdown heading elements to HTML
907
-	 * @param  string $text
908
-	 * @return string
909
-	 */
910
-	protected function doHeaders($text) {
911
-		/**
912
-		 * Setext-style headers:
913
-		 *	  Header 1
914
-		 *	  ========
915
-		 *
916
-		 *	  Header 2
917
-		 *	  --------
918
-		 */
919
-		$text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx',
920
-			array($this, '_doHeaders_callback_setext'), $text);
921
-
922
-		/**
923
-		 * atx-style headers:
924
-		 *   # Header 1
925
-		 *   ## Header 2
926
-		 *   ## Header 2 with closing hashes ##
927
-		 *   ...
928
-		 *   ###### Header 6
929
-		 */
930
-		$text = preg_replace_callback('{
844
+            array($this, '_doImages_inline_callback'), $text);
845
+
846
+        return $text;
847
+    }
848
+
849
+    /**
850
+     * Callback to parse references image tags
851
+     * @param  array $matches
852
+     * @return string
853
+     */
854
+    protected function _doImages_reference_callback($matches) {
855
+        $whole_match = $matches[1];
856
+        $alt_text    = $matches[2];
857
+        $link_id     = strtolower($matches[3]);
858
+
859
+        if ($link_id == "") {
860
+            $link_id = strtolower($alt_text); // for shortcut links like ![this][].
861
+        }
862
+
863
+        $alt_text = $this->encodeAttribute($alt_text);
864
+        if (isset($this->urls[$link_id])) {
865
+            $url = $this->encodeURLAttribute($this->urls[$link_id]);
866
+            $result = "<img src=\"$url\" alt=\"$alt_text\"";
867
+            if (isset($this->titles[$link_id])) {
868
+                $title = $this->titles[$link_id];
869
+                $title = $this->encodeAttribute($title);
870
+                $result .=  " title=\"$title\"";
871
+            }
872
+            $result .= $this->empty_element_suffix;
873
+            $result = $this->hashPart($result);
874
+        } else {
875
+            // If there's no such link ID, leave intact:
876
+            $result = $whole_match;
877
+        }
878
+
879
+        return $result;
880
+    }
881
+
882
+    /**
883
+     * Callback to parse inline image tags
884
+     * @param  array $matches
885
+     * @return string
886
+     */
887
+    protected function _doImages_inline_callback($matches) {
888
+        $whole_match	= $matches[1];
889
+        $alt_text		= $matches[2];
890
+        $url			= $matches[3] == '' ? $matches[4] : $matches[3];
891
+        $title			=& $matches[7];
892
+
893
+        $alt_text = $this->encodeAttribute($alt_text);
894
+        $url = $this->encodeURLAttribute($url);
895
+        $result = "<img src=\"$url\" alt=\"$alt_text\"";
896
+        if (isset($title)) {
897
+            $title = $this->encodeAttribute($title);
898
+            $result .=  " title=\"$title\""; // $title already quoted
899
+        }
900
+        $result .= $this->empty_element_suffix;
901
+
902
+        return $this->hashPart($result);
903
+    }
904
+
905
+    /**
906
+     * Parse Markdown heading elements to HTML
907
+     * @param  string $text
908
+     * @return string
909
+     */
910
+    protected function doHeaders($text) {
911
+        /**
912
+         * Setext-style headers:
913
+         *	  Header 1
914
+         *	  ========
915
+         *
916
+         *	  Header 2
917
+         *	  --------
918
+         */
919
+        $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx',
920
+            array($this, '_doHeaders_callback_setext'), $text);
921
+
922
+        /**
923
+         * atx-style headers:
924
+         *   # Header 1
925
+         *   ## Header 2
926
+         *   ## Header 2 with closing hashes ##
927
+         *   ...
928
+         *   ###### Header 6
929
+         */
930
+        $text = preg_replace_callback('{
931 931
 				^(\#{1,6})	# $1 = string of #\'s
932 932
 				[ ]*
933 933
 				(.+?)		# $2 = Header text
@@ -935,87 +935,87 @@  discard block
 block discarded – undo
935 935
 				\#*			# optional closing #\'s (not counted)
936 936
 				\n+
937 937
 			}xm',
938
-			array($this, '_doHeaders_callback_atx'), $text);
939
-
940
-		return $text;
941
-	}
942
-
943
-	/**
944
-	 * Setext header parsing callback
945
-	 * @param  array $matches
946
-	 * @return string
947
-	 */
948
-	protected function _doHeaders_callback_setext($matches) {
949
-		// Terrible hack to check we haven't found an empty list item.
950
-		if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1])) {
951
-			return $matches[0];
952
-		}
953
-
954
-		$level = $matches[2][0] == '=' ? 1 : 2;
955
-
956
-		// ID attribute generation
957
-		$idAtt = $this->_generateIdFromHeaderValue($matches[1]);
958
-
959
-		$block = "<h$level$idAtt>".$this->runSpanGamut($matches[1])."</h$level>";
960
-		return "\n" . $this->hashBlock($block) . "\n\n";
961
-	}
962
-
963
-	/**
964
-	 * ATX header parsing callback
965
-	 * @param  array $matches
966
-	 * @return string
967
-	 */
968
-	protected function _doHeaders_callback_atx($matches) {
969
-		// ID attribute generation
970
-		$idAtt = $this->_generateIdFromHeaderValue($matches[2]);
971
-
972
-		$level = strlen($matches[1]);
973
-		$block = "<h$level$idAtt>".$this->runSpanGamut($matches[2])."</h$level>";
974
-		return "\n" . $this->hashBlock($block) . "\n\n";
975
-	}
976
-
977
-	/**
978
-	 * If a header_id_func property is set, we can use it to automatically
979
-	 * generate an id attribute.
980
-	 *
981
-	 * This method returns a string in the form id="foo", or an empty string
982
-	 * otherwise.
983
-	 * @param  string $headerValue
984
-	 * @return string
985
-	 */
986
-	protected function _generateIdFromHeaderValue($headerValue) {
987
-		if (!is_callable($this->header_id_func)) {
988
-			return "";
989
-		}
990
-
991
-		$idValue = call_user_func($this->header_id_func, $headerValue);
992
-		if (!$idValue) {
993
-			return "";
994
-		}
995
-
996
-		return ' id="' . $this->encodeAttribute($idValue) . '"';
997
-	}
998
-
999
-	/**
1000
-	 * Form HTML ordered (numbered) and unordered (bulleted) lists.
1001
-	 * @param  string $text
1002
-	 * @return string
1003
-	 */
1004
-	protected function doLists($text) {
1005
-		$less_than_tab = $this->tab_width - 1;
1006
-
1007
-		// Re-usable patterns to match list item bullets and number markers:
1008
-		$marker_ul_re  = '[*+-]';
1009
-		$marker_ol_re  = '\d+[\.]';
1010
-
1011
-		$markers_relist = array(
1012
-			$marker_ul_re => $marker_ol_re,
1013
-			$marker_ol_re => $marker_ul_re,
1014
-			);
1015
-
1016
-		foreach ($markers_relist as $marker_re => $other_marker_re) {
1017
-			// Re-usable pattern to match any entirel ul or ol list:
1018
-			$whole_list_re = '
938
+            array($this, '_doHeaders_callback_atx'), $text);
939
+
940
+        return $text;
941
+    }
942
+
943
+    /**
944
+     * Setext header parsing callback
945
+     * @param  array $matches
946
+     * @return string
947
+     */
948
+    protected function _doHeaders_callback_setext($matches) {
949
+        // Terrible hack to check we haven't found an empty list item.
950
+        if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1])) {
951
+            return $matches[0];
952
+        }
953
+
954
+        $level = $matches[2][0] == '=' ? 1 : 2;
955
+
956
+        // ID attribute generation
957
+        $idAtt = $this->_generateIdFromHeaderValue($matches[1]);
958
+
959
+        $block = "<h$level$idAtt>".$this->runSpanGamut($matches[1])."</h$level>";
960
+        return "\n" . $this->hashBlock($block) . "\n\n";
961
+    }
962
+
963
+    /**
964
+     * ATX header parsing callback
965
+     * @param  array $matches
966
+     * @return string
967
+     */
968
+    protected function _doHeaders_callback_atx($matches) {
969
+        // ID attribute generation
970
+        $idAtt = $this->_generateIdFromHeaderValue($matches[2]);
971
+
972
+        $level = strlen($matches[1]);
973
+        $block = "<h$level$idAtt>".$this->runSpanGamut($matches[2])."</h$level>";
974
+        return "\n" . $this->hashBlock($block) . "\n\n";
975
+    }
976
+
977
+    /**
978
+     * If a header_id_func property is set, we can use it to automatically
979
+     * generate an id attribute.
980
+     *
981
+     * This method returns a string in the form id="foo", or an empty string
982
+     * otherwise.
983
+     * @param  string $headerValue
984
+     * @return string
985
+     */
986
+    protected function _generateIdFromHeaderValue($headerValue) {
987
+        if (!is_callable($this->header_id_func)) {
988
+            return "";
989
+        }
990
+
991
+        $idValue = call_user_func($this->header_id_func, $headerValue);
992
+        if (!$idValue) {
993
+            return "";
994
+        }
995
+
996
+        return ' id="' . $this->encodeAttribute($idValue) . '"';
997
+    }
998
+
999
+    /**
1000
+     * Form HTML ordered (numbered) and unordered (bulleted) lists.
1001
+     * @param  string $text
1002
+     * @return string
1003
+     */
1004
+    protected function doLists($text) {
1005
+        $less_than_tab = $this->tab_width - 1;
1006
+
1007
+        // Re-usable patterns to match list item bullets and number markers:
1008
+        $marker_ul_re  = '[*+-]';
1009
+        $marker_ol_re  = '\d+[\.]';
1010
+
1011
+        $markers_relist = array(
1012
+            $marker_ul_re => $marker_ol_re,
1013
+            $marker_ol_re => $marker_ul_re,
1014
+            );
1015
+
1016
+        foreach ($markers_relist as $marker_re => $other_marker_re) {
1017
+            // Re-usable pattern to match any entirel ul or ol list:
1018
+            $whole_list_re = '
1019 1019
 				(								# $1 = whole list
1020 1020
 				  (								# $2
1021 1021
 					([ ]{0,'.$less_than_tab.'})	# $3 = number of spaces
@@ -1042,109 +1042,109 @@  discard block
 block discarded – undo
1042 1042
 				)
1043 1043
 			'; // mx
1044 1044
 
1045
-			// We use a different prefix before nested lists than top-level lists.
1046
-			//See extended comment in _ProcessListItems().
1045
+            // We use a different prefix before nested lists than top-level lists.
1046
+            //See extended comment in _ProcessListItems().
1047 1047
 
1048
-			if ($this->list_level) {
1049
-				$text = preg_replace_callback('{
1048
+            if ($this->list_level) {
1049
+                $text = preg_replace_callback('{
1050 1050
 						^
1051 1051
 						'.$whole_list_re.'
1052 1052
 					}mx',
1053
-					array($this, '_doLists_callback'), $text);
1054
-			} else {
1055
-				$text = preg_replace_callback('{
1053
+                    array($this, '_doLists_callback'), $text);
1054
+            } else {
1055
+                $text = preg_replace_callback('{
1056 1056
 						(?:(?<=\n)\n|\A\n?) # Must eat the newline
1057 1057
 						'.$whole_list_re.'
1058 1058
 					}mx',
1059
-					array($this, '_doLists_callback'), $text);
1060
-			}
1061
-		}
1062
-
1063
-		return $text;
1064
-	}
1065
-
1066
-	/**
1067
-	 * List parsing callback
1068
-	 * @param  array $matches
1069
-	 * @return string
1070
-	 */
1071
-	protected function _doLists_callback($matches) {
1072
-		// Re-usable patterns to match list item bullets and number markers:
1073
-		$marker_ul_re  = '[*+-]';
1074
-		$marker_ol_re  = '\d+[\.]';
1075
-		$marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
1076
-		$marker_ol_start_re = '[0-9]+';
1077
-
1078
-		$list = $matches[1];
1079
-		$list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol";
1080
-
1081
-		$marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
1082
-
1083
-		$list .= "\n";
1084
-		$result = $this->processListItems($list, $marker_any_re);
1085
-
1086
-		$ol_start = 1;
1087
-		if ($this->enhanced_ordered_list) {
1088
-			// Get the start number for ordered list.
1089
-			if ($list_type == 'ol') {
1090
-				$ol_start_array = array();
1091
-				$ol_start_check = preg_match("/$marker_ol_start_re/", $matches[4], $ol_start_array);
1092
-				if ($ol_start_check){
1093
-					$ol_start = $ol_start_array[0];
1094
-				}
1095
-			}
1096
-		}
1097
-
1098
-		if ($ol_start > 1 && $list_type == 'ol'){
1099
-			$result = $this->hashBlock("<$list_type start=\"$ol_start\">\n" . $result . "</$list_type>");
1100
-		} else {
1101
-			$result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
1102
-		}
1103
-		return "\n". $result ."\n\n";
1104
-	}
1105
-
1106
-	/**
1107
-	 * Nesting tracker for list levels
1108
-	 * @var integer
1109
-	 */
1110
-	protected $list_level = 0;
1111
-
1112
-	/**
1113
-	 * Process the contents of a single ordered or unordered list, splitting it
1114
-	 * into individual list items.
1115
-	 * @param  string $list_str
1116
-	 * @param  string $marker_any_re
1117
-	 * @return string
1118
-	 */
1119
-	protected function processListItems($list_str, $marker_any_re) {
1120
-		/**
1121
-		 * The $this->list_level global keeps track of when we're inside a list.
1122
-		 * Each time we enter a list, we increment it; when we leave a list,
1123
-		 * we decrement. If it's zero, we're not in a list anymore.
1124
-		 *
1125
-		 * We do this because when we're not inside a list, we want to treat
1126
-		 * something like this:
1127
-		 *
1128
-		 *		I recommend upgrading to version
1129
-		 *		8. Oops, now this line is treated
1130
-		 *		as a sub-list.
1131
-		 *
1132
-		 * As a single paragraph, despite the fact that the second line starts
1133
-		 * with a digit-period-space sequence.
1134
-		 *
1135
-		 * Whereas when we're inside a list (or sub-list), that line will be
1136
-		 * treated as the start of a sub-list. What a kludge, huh? This is
1137
-		 * an aspect of Markdown's syntax that's hard to parse perfectly
1138
-		 * without resorting to mind-reading. Perhaps the solution is to
1139
-		 * change the syntax rules such that sub-lists must start with a
1140
-		 * starting cardinal number; e.g. "1." or "a.".
1141
-		 */
1142
-		$this->list_level++;
1143
-
1144
-		// Trim trailing blank lines:
1145
-		$list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
1146
-
1147
-		$list_str = preg_replace_callback('{
1059
+                    array($this, '_doLists_callback'), $text);
1060
+            }
1061
+        }
1062
+
1063
+        return $text;
1064
+    }
1065
+
1066
+    /**
1067
+     * List parsing callback
1068
+     * @param  array $matches
1069
+     * @return string
1070
+     */
1071
+    protected function _doLists_callback($matches) {
1072
+        // Re-usable patterns to match list item bullets and number markers:
1073
+        $marker_ul_re  = '[*+-]';
1074
+        $marker_ol_re  = '\d+[\.]';
1075
+        $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
1076
+        $marker_ol_start_re = '[0-9]+';
1077
+
1078
+        $list = $matches[1];
1079
+        $list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol";
1080
+
1081
+        $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
1082
+
1083
+        $list .= "\n";
1084
+        $result = $this->processListItems($list, $marker_any_re);
1085
+
1086
+        $ol_start = 1;
1087
+        if ($this->enhanced_ordered_list) {
1088
+            // Get the start number for ordered list.
1089
+            if ($list_type == 'ol') {
1090
+                $ol_start_array = array();
1091
+                $ol_start_check = preg_match("/$marker_ol_start_re/", $matches[4], $ol_start_array);
1092
+                if ($ol_start_check){
1093
+                    $ol_start = $ol_start_array[0];
1094
+                }
1095
+            }
1096
+        }
1097
+
1098
+        if ($ol_start > 1 && $list_type == 'ol'){
1099
+            $result = $this->hashBlock("<$list_type start=\"$ol_start\">\n" . $result . "</$list_type>");
1100
+        } else {
1101
+            $result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
1102
+        }
1103
+        return "\n". $result ."\n\n";
1104
+    }
1105
+
1106
+    /**
1107
+     * Nesting tracker for list levels
1108
+     * @var integer
1109
+     */
1110
+    protected $list_level = 0;
1111
+
1112
+    /**
1113
+     * Process the contents of a single ordered or unordered list, splitting it
1114
+     * into individual list items.
1115
+     * @param  string $list_str
1116
+     * @param  string $marker_any_re
1117
+     * @return string
1118
+     */
1119
+    protected function processListItems($list_str, $marker_any_re) {
1120
+        /**
1121
+         * The $this->list_level global keeps track of when we're inside a list.
1122
+         * Each time we enter a list, we increment it; when we leave a list,
1123
+         * we decrement. If it's zero, we're not in a list anymore.
1124
+         *
1125
+         * We do this because when we're not inside a list, we want to treat
1126
+         * something like this:
1127
+         *
1128
+         *		I recommend upgrading to version
1129
+         *		8. Oops, now this line is treated
1130
+         *		as a sub-list.
1131
+         *
1132
+         * As a single paragraph, despite the fact that the second line starts
1133
+         * with a digit-period-space sequence.
1134
+         *
1135
+         * Whereas when we're inside a list (or sub-list), that line will be
1136
+         * treated as the start of a sub-list. What a kludge, huh? This is
1137
+         * an aspect of Markdown's syntax that's hard to parse perfectly
1138
+         * without resorting to mind-reading. Perhaps the solution is to
1139
+         * change the syntax rules such that sub-lists must start with a
1140
+         * starting cardinal number; e.g. "1." or "a.".
1141
+         */
1142
+        $this->list_level++;
1143
+
1144
+        // Trim trailing blank lines:
1145
+        $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
1146
+
1147
+        $list_str = preg_replace_callback('{
1148 1148
 			(\n)?							# leading line = $1
1149 1149
 			(^[ ]*)							# leading whitespace = $2
1150 1150
 			('.$marker_any_re.'				# list marker and space = $3
@@ -1154,46 +1154,46 @@  discard block
 block discarded – undo
1154 1154
 			(?:(\n+(?=\n))|\n)				# tailing blank line = $5
1155 1155
 			(?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n))))
1156 1156
 			}xm',
1157
-			array($this, '_processListItems_callback'), $list_str);
1158
-
1159
-		$this->list_level--;
1160
-		return $list_str;
1161
-	}
1162
-
1163
-	/**
1164
-	 * List item parsing callback
1165
-	 * @param  array $matches
1166
-	 * @return string
1167
-	 */
1168
-	protected function _processListItems_callback($matches) {
1169
-		$item = $matches[4];
1170
-		$leading_line =& $matches[1];
1171
-		$leading_space =& $matches[2];
1172
-		$marker_space = $matches[3];
1173
-		$tailing_blank_line =& $matches[5];
1174
-
1175
-		if ($leading_line || $tailing_blank_line ||
1176
-			preg_match('/\n{2,}/', $item))
1177
-		{
1178
-			// Replace marker with the appropriate whitespace indentation
1179
-			$item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
1180
-			$item = $this->runBlockGamut($this->outdent($item)."\n");
1181
-		} else {
1182
-			// Recursion for sub-lists:
1183
-			$item = $this->doLists($this->outdent($item));
1184
-			$item = $this->formParagraphs($item, false);
1185
-		}
1186
-
1187
-		return "<li>" . $item . "</li>\n";
1188
-	}
1189
-
1190
-	/**
1191
-	 * Process Markdown `<pre><code>` blocks.
1192
-	 * @param  string $text
1193
-	 * @return string
1194
-	 */
1195
-	protected function doCodeBlocks($text) {
1196
-		$text = preg_replace_callback('{
1157
+            array($this, '_processListItems_callback'), $list_str);
1158
+
1159
+        $this->list_level--;
1160
+        return $list_str;
1161
+    }
1162
+
1163
+    /**
1164
+     * List item parsing callback
1165
+     * @param  array $matches
1166
+     * @return string
1167
+     */
1168
+    protected function _processListItems_callback($matches) {
1169
+        $item = $matches[4];
1170
+        $leading_line =& $matches[1];
1171
+        $leading_space =& $matches[2];
1172
+        $marker_space = $matches[3];
1173
+        $tailing_blank_line =& $matches[5];
1174
+
1175
+        if ($leading_line || $tailing_blank_line ||
1176
+            preg_match('/\n{2,}/', $item))
1177
+        {
1178
+            // Replace marker with the appropriate whitespace indentation
1179
+            $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
1180
+            $item = $this->runBlockGamut($this->outdent($item)."\n");
1181
+        } else {
1182
+            // Recursion for sub-lists:
1183
+            $item = $this->doLists($this->outdent($item));
1184
+            $item = $this->formParagraphs($item, false);
1185
+        }
1186
+
1187
+        return "<li>" . $item . "</li>\n";
1188
+    }
1189
+
1190
+    /**
1191
+     * Process Markdown `<pre><code>` blocks.
1192
+     * @param  string $text
1193
+     * @return string
1194
+     */
1195
+    protected function doCodeBlocks($text) {
1196
+        $text = preg_replace_callback('{
1197 1197
 				(?:\n\n|\A\n?)
1198 1198
 				(	            # $1 = the code block -- one or more lines, starting with a space/tab
1199 1199
 				  (?>
@@ -1203,243 +1203,243 @@  discard block
 block discarded – undo
1203 1203
 				)
1204 1204
 				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
1205 1205
 			}xm',
1206
-			array($this, '_doCodeBlocks_callback'), $text);
1207
-
1208
-		return $text;
1209
-	}
1210
-
1211
-	/**
1212
-	 * Code block parsing callback
1213
-	 * @param  array $matches
1214
-	 * @return string
1215
-	 */
1216
-	protected function _doCodeBlocks_callback($matches) {
1217
-		$codeblock = $matches[1];
1218
-
1219
-		$codeblock = $this->outdent($codeblock);
1220
-		if (is_callable($this->code_block_content_func)) {
1221
-			$codeblock = call_user_func($this->code_block_content_func, $codeblock, "");
1222
-		} else {
1223
-			$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
1224
-		}
1225
-
1226
-		# trim leading newlines and trailing newlines
1227
-		$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
1228
-
1229
-		$codeblock = "<pre><code>$codeblock\n</code></pre>";
1230
-		return "\n\n" . $this->hashBlock($codeblock) . "\n\n";
1231
-	}
1232
-
1233
-	/**
1234
-	 * Create a code span markup for $code. Called from handleSpanToken.
1235
-	 * @param  string $code
1236
-	 * @return string
1237
-	 */
1238
-	protected function makeCodeSpan($code) {
1239
-		if (is_callable($this->code_span_content_func)) {
1240
-			$code = call_user_func($this->code_span_content_func, $code);
1241
-		} else {
1242
-			$code = htmlspecialchars(trim($code), ENT_NOQUOTES);
1243
-		}
1244
-		return $this->hashPart("<code>$code</code>");
1245
-	}
1246
-
1247
-	/**
1248
-	 * Define the emphasis operators with their regex matches
1249
-	 * @var array
1250
-	 */
1251
-	protected $em_relist = array(
1252
-		''  => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?![\.,:;]?\s)',
1253
-		'*' => '(?<![\s*])\*(?!\*)',
1254
-		'_' => '(?<![\s_])_(?!_)',
1255
-	);
1256
-
1257
-	/**
1258
-	 * Define the strong operators with their regex matches
1259
-	 * @var array
1260
-	 */
1261
-	protected $strong_relist = array(
1262
-		''   => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?![\.,:;]?\s)',
1263
-		'**' => '(?<![\s*])\*\*(?!\*)',
1264
-		'__' => '(?<![\s_])__(?!_)',
1265
-	);
1266
-
1267
-	/**
1268
-	 * Define the emphasis + strong operators with their regex matches
1269
-	 * @var array
1270
-	 */
1271
-	protected $em_strong_relist = array(
1272
-		''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?![\.,:;]?\s)',
1273
-		'***' => '(?<![\s*])\*\*\*(?!\*)',
1274
-		'___' => '(?<![\s_])___(?!_)',
1275
-	);
1276
-
1277
-	/**
1278
-	 * Container for prepared regular expressions
1279
-	 * @var array
1280
-	 */
1281
-	protected $em_strong_prepared_relist;
1282
-
1283
-	/**
1284
-	 * Prepare regular expressions for searching emphasis tokens in any
1285
-	 * context.
1286
-	 * @return void
1287
-	 */
1288
-	protected function prepareItalicsAndBold() {
1289
-		foreach ($this->em_relist as $em => $em_re) {
1290
-			foreach ($this->strong_relist as $strong => $strong_re) {
1291
-				// Construct list of allowed token expressions.
1292
-				$token_relist = array();
1293
-				if (isset($this->em_strong_relist["$em$strong"])) {
1294
-					$token_relist[] = $this->em_strong_relist["$em$strong"];
1295
-				}
1296
-				$token_relist[] = $em_re;
1297
-				$token_relist[] = $strong_re;
1298
-
1299
-				// Construct master expression from list.
1300
-				$token_re = '{(' . implode('|', $token_relist) . ')}';
1301
-				$this->em_strong_prepared_relist["$em$strong"] = $token_re;
1302
-			}
1303
-		}
1304
-	}
1305
-
1306
-	/**
1307
-	 * Convert Markdown italics (emphasis) and bold (strong) to HTML
1308
-	 * @param  string $text
1309
-	 * @return string
1310
-	 */
1311
-	protected function doItalicsAndBold($text) {
1312
-		if ($this->in_emphasis_processing) {
1313
-			return $text; // avoid reentrency
1314
-		}
1315
-		$this->in_emphasis_processing = true;
1316
-
1317
-		$token_stack = array('');
1318
-		$text_stack = array('');
1319
-		$em = '';
1320
-		$strong = '';
1321
-		$tree_char_em = false;
1322
-
1323
-		while (1) {
1324
-			// Get prepared regular expression for seraching emphasis tokens
1325
-			// in current context.
1326
-			$token_re = $this->em_strong_prepared_relist["$em$strong"];
1327
-
1328
-			// Each loop iteration search for the next emphasis token.
1329
-			// Each token is then passed to handleSpanToken.
1330
-			$parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
1331
-			$text_stack[0] .= $parts[0];
1332
-			$token =& $parts[1];
1333
-			$text =& $parts[2];
1334
-
1335
-			if (empty($token)) {
1336
-				// Reached end of text span: empty stack without emitting.
1337
-				// any more emphasis.
1338
-				while ($token_stack[0]) {
1339
-					$text_stack[1] .= array_shift($token_stack);
1340
-					$text_stack[0] .= array_shift($text_stack);
1341
-				}
1342
-				break;
1343
-			}
1344
-
1345
-			$token_len = strlen($token);
1346
-			if ($tree_char_em) {
1347
-				// Reached closing marker while inside a three-char emphasis.
1348
-				if ($token_len == 3) {
1349
-					// Three-char closing marker, close em and strong.
1350
-					array_shift($token_stack);
1351
-					$span = array_shift($text_stack);
1352
-					$span = $this->runSpanGamut($span);
1353
-					$span = "<strong><em>$span</em></strong>";
1354
-					$text_stack[0] .= $this->hashPart($span);
1355
-					$em = '';
1356
-					$strong = '';
1357
-				} else {
1358
-					// Other closing marker: close one em or strong and
1359
-					// change current token state to match the other
1360
-					$token_stack[0] = str_repeat($token[0], 3-$token_len);
1361
-					$tag = $token_len == 2 ? "strong" : "em";
1362
-					$span = $text_stack[0];
1363
-					$span = $this->runSpanGamut($span);
1364
-					$span = "<$tag>$span</$tag>";
1365
-					$text_stack[0] = $this->hashPart($span);
1366
-					$$tag = ''; // $$tag stands for $em or $strong
1367
-				}
1368
-				$tree_char_em = false;
1369
-			} else if ($token_len == 3) {
1370
-				if ($em) {
1371
-					// Reached closing marker for both em and strong.
1372
-					// Closing strong marker:
1373
-					for ($i = 0; $i < 2; ++$i) {
1374
-						$shifted_token = array_shift($token_stack);
1375
-						$tag = strlen($shifted_token) == 2 ? "strong" : "em";
1376
-						$span = array_shift($text_stack);
1377
-						$span = $this->runSpanGamut($span);
1378
-						$span = "<$tag>$span</$tag>";
1379
-						$text_stack[0] .= $this->hashPart($span);
1380
-						$$tag = ''; // $$tag stands for $em or $strong
1381
-					}
1382
-				} else {
1383
-					// Reached opening three-char emphasis marker. Push on token
1384
-					// stack; will be handled by the special condition above.
1385
-					$em = $token[0];
1386
-					$strong = "$em$em";
1387
-					array_unshift($token_stack, $token);
1388
-					array_unshift($text_stack, '');
1389
-					$tree_char_em = true;
1390
-				}
1391
-			} else if ($token_len == 2) {
1392
-				if ($strong) {
1393
-					// Unwind any dangling emphasis marker:
1394
-					if (strlen($token_stack[0]) == 1) {
1395
-						$text_stack[1] .= array_shift($token_stack);
1396
-						$text_stack[0] .= array_shift($text_stack);
1397
-						$em = '';
1398
-					}
1399
-					// Closing strong marker:
1400
-					array_shift($token_stack);
1401
-					$span = array_shift($text_stack);
1402
-					$span = $this->runSpanGamut($span);
1403
-					$span = "<strong>$span</strong>";
1404
-					$text_stack[0] .= $this->hashPart($span);
1405
-					$strong = '';
1406
-				} else {
1407
-					array_unshift($token_stack, $token);
1408
-					array_unshift($text_stack, '');
1409
-					$strong = $token;
1410
-				}
1411
-			} else {
1412
-				// Here $token_len == 1
1413
-				if ($em) {
1414
-					if (strlen($token_stack[0]) == 1) {
1415
-						// Closing emphasis marker:
1416
-						array_shift($token_stack);
1417
-						$span = array_shift($text_stack);
1418
-						$span = $this->runSpanGamut($span);
1419
-						$span = "<em>$span</em>";
1420
-						$text_stack[0] .= $this->hashPart($span);
1421
-						$em = '';
1422
-					} else {
1423
-						$text_stack[0] .= $token;
1424
-					}
1425
-				} else {
1426
-					array_unshift($token_stack, $token);
1427
-					array_unshift($text_stack, '');
1428
-					$em = $token;
1429
-				}
1430
-			}
1431
-		}
1432
-		$this->in_emphasis_processing = false;
1433
-		return $text_stack[0];
1434
-	}
1435
-
1436
-	/**
1437
-	 * Parse Markdown blockquotes to HTML
1438
-	 * @param  string $text
1439
-	 * @return string
1440
-	 */
1441
-	protected function doBlockQuotes($text) {
1442
-		$text = preg_replace_callback('/
1206
+            array($this, '_doCodeBlocks_callback'), $text);
1207
+
1208
+        return $text;
1209
+    }
1210
+
1211
+    /**
1212
+     * Code block parsing callback
1213
+     * @param  array $matches
1214
+     * @return string
1215
+     */
1216
+    protected function _doCodeBlocks_callback($matches) {
1217
+        $codeblock = $matches[1];
1218
+
1219
+        $codeblock = $this->outdent($codeblock);
1220
+        if (is_callable($this->code_block_content_func)) {
1221
+            $codeblock = call_user_func($this->code_block_content_func, $codeblock, "");
1222
+        } else {
1223
+            $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
1224
+        }
1225
+
1226
+        # trim leading newlines and trailing newlines
1227
+        $codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
1228
+
1229
+        $codeblock = "<pre><code>$codeblock\n</code></pre>";
1230
+        return "\n\n" . $this->hashBlock($codeblock) . "\n\n";
1231
+    }
1232
+
1233
+    /**
1234
+     * Create a code span markup for $code. Called from handleSpanToken.
1235
+     * @param  string $code
1236
+     * @return string
1237
+     */
1238
+    protected function makeCodeSpan($code) {
1239
+        if (is_callable($this->code_span_content_func)) {
1240
+            $code = call_user_func($this->code_span_content_func, $code);
1241
+        } else {
1242
+            $code = htmlspecialchars(trim($code), ENT_NOQUOTES);
1243
+        }
1244
+        return $this->hashPart("<code>$code</code>");
1245
+    }
1246
+
1247
+    /**
1248
+     * Define the emphasis operators with their regex matches
1249
+     * @var array
1250
+     */
1251
+    protected $em_relist = array(
1252
+        ''  => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?![\.,:;]?\s)',
1253
+        '*' => '(?<![\s*])\*(?!\*)',
1254
+        '_' => '(?<![\s_])_(?!_)',
1255
+    );
1256
+
1257
+    /**
1258
+     * Define the strong operators with their regex matches
1259
+     * @var array
1260
+     */
1261
+    protected $strong_relist = array(
1262
+        ''   => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?![\.,:;]?\s)',
1263
+        '**' => '(?<![\s*])\*\*(?!\*)',
1264
+        '__' => '(?<![\s_])__(?!_)',
1265
+    );
1266
+
1267
+    /**
1268
+     * Define the emphasis + strong operators with their regex matches
1269
+     * @var array
1270
+     */
1271
+    protected $em_strong_relist = array(
1272
+        ''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?![\.,:;]?\s)',
1273
+        '***' => '(?<![\s*])\*\*\*(?!\*)',
1274
+        '___' => '(?<![\s_])___(?!_)',
1275
+    );
1276
+
1277
+    /**
1278
+     * Container for prepared regular expressions
1279
+     * @var array
1280
+     */
1281
+    protected $em_strong_prepared_relist;
1282
+
1283
+    /**
1284
+     * Prepare regular expressions for searching emphasis tokens in any
1285
+     * context.
1286
+     * @return void
1287
+     */
1288
+    protected function prepareItalicsAndBold() {
1289
+        foreach ($this->em_relist as $em => $em_re) {
1290
+            foreach ($this->strong_relist as $strong => $strong_re) {
1291
+                // Construct list of allowed token expressions.
1292
+                $token_relist = array();
1293
+                if (isset($this->em_strong_relist["$em$strong"])) {
1294
+                    $token_relist[] = $this->em_strong_relist["$em$strong"];
1295
+                }
1296
+                $token_relist[] = $em_re;
1297
+                $token_relist[] = $strong_re;
1298
+
1299
+                // Construct master expression from list.
1300
+                $token_re = '{(' . implode('|', $token_relist) . ')}';
1301
+                $this->em_strong_prepared_relist["$em$strong"] = $token_re;
1302
+            }
1303
+        }
1304
+    }
1305
+
1306
+    /**
1307
+     * Convert Markdown italics (emphasis) and bold (strong) to HTML
1308
+     * @param  string $text
1309
+     * @return string
1310
+     */
1311
+    protected function doItalicsAndBold($text) {
1312
+        if ($this->in_emphasis_processing) {
1313
+            return $text; // avoid reentrency
1314
+        }
1315
+        $this->in_emphasis_processing = true;
1316
+
1317
+        $token_stack = array('');
1318
+        $text_stack = array('');
1319
+        $em = '';
1320
+        $strong = '';
1321
+        $tree_char_em = false;
1322
+
1323
+        while (1) {
1324
+            // Get prepared regular expression for seraching emphasis tokens
1325
+            // in current context.
1326
+            $token_re = $this->em_strong_prepared_relist["$em$strong"];
1327
+
1328
+            // Each loop iteration search for the next emphasis token.
1329
+            // Each token is then passed to handleSpanToken.
1330
+            $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
1331
+            $text_stack[0] .= $parts[0];
1332
+            $token =& $parts[1];
1333
+            $text =& $parts[2];
1334
+
1335
+            if (empty($token)) {
1336
+                // Reached end of text span: empty stack without emitting.
1337
+                // any more emphasis.
1338
+                while ($token_stack[0]) {
1339
+                    $text_stack[1] .= array_shift($token_stack);
1340
+                    $text_stack[0] .= array_shift($text_stack);
1341
+                }
1342
+                break;
1343
+            }
1344
+
1345
+            $token_len = strlen($token);
1346
+            if ($tree_char_em) {
1347
+                // Reached closing marker while inside a three-char emphasis.
1348
+                if ($token_len == 3) {
1349
+                    // Three-char closing marker, close em and strong.
1350
+                    array_shift($token_stack);
1351
+                    $span = array_shift($text_stack);
1352
+                    $span = $this->runSpanGamut($span);
1353
+                    $span = "<strong><em>$span</em></strong>";
1354
+                    $text_stack[0] .= $this->hashPart($span);
1355
+                    $em = '';
1356
+                    $strong = '';
1357
+                } else {
1358
+                    // Other closing marker: close one em or strong and
1359
+                    // change current token state to match the other
1360
+                    $token_stack[0] = str_repeat($token[0], 3-$token_len);
1361
+                    $tag = $token_len == 2 ? "strong" : "em";
1362
+                    $span = $text_stack[0];
1363
+                    $span = $this->runSpanGamut($span);
1364
+                    $span = "<$tag>$span</$tag>";
1365
+                    $text_stack[0] = $this->hashPart($span);
1366
+                    $$tag = ''; // $$tag stands for $em or $strong
1367
+                }
1368
+                $tree_char_em = false;
1369
+            } else if ($token_len == 3) {
1370
+                if ($em) {
1371
+                    // Reached closing marker for both em and strong.
1372
+                    // Closing strong marker:
1373
+                    for ($i = 0; $i < 2; ++$i) {
1374
+                        $shifted_token = array_shift($token_stack);
1375
+                        $tag = strlen($shifted_token) == 2 ? "strong" : "em";
1376
+                        $span = array_shift($text_stack);
1377
+                        $span = $this->runSpanGamut($span);
1378
+                        $span = "<$tag>$span</$tag>";
1379
+                        $text_stack[0] .= $this->hashPart($span);
1380
+                        $$tag = ''; // $$tag stands for $em or $strong
1381
+                    }
1382
+                } else {
1383
+                    // Reached opening three-char emphasis marker. Push on token
1384
+                    // stack; will be handled by the special condition above.
1385
+                    $em = $token[0];
1386
+                    $strong = "$em$em";
1387
+                    array_unshift($token_stack, $token);
1388
+                    array_unshift($text_stack, '');
1389
+                    $tree_char_em = true;
1390
+                }
1391
+            } else if ($token_len == 2) {
1392
+                if ($strong) {
1393
+                    // Unwind any dangling emphasis marker:
1394
+                    if (strlen($token_stack[0]) == 1) {
1395
+                        $text_stack[1] .= array_shift($token_stack);
1396
+                        $text_stack[0] .= array_shift($text_stack);
1397
+                        $em = '';
1398
+                    }
1399
+                    // Closing strong marker:
1400
+                    array_shift($token_stack);
1401
+                    $span = array_shift($text_stack);
1402
+                    $span = $this->runSpanGamut($span);
1403
+                    $span = "<strong>$span</strong>";
1404
+                    $text_stack[0] .= $this->hashPart($span);
1405
+                    $strong = '';
1406
+                } else {
1407
+                    array_unshift($token_stack, $token);
1408
+                    array_unshift($text_stack, '');
1409
+                    $strong = $token;
1410
+                }
1411
+            } else {
1412
+                // Here $token_len == 1
1413
+                if ($em) {
1414
+                    if (strlen($token_stack[0]) == 1) {
1415
+                        // Closing emphasis marker:
1416
+                        array_shift($token_stack);
1417
+                        $span = array_shift($text_stack);
1418
+                        $span = $this->runSpanGamut($span);
1419
+                        $span = "<em>$span</em>";
1420
+                        $text_stack[0] .= $this->hashPart($span);
1421
+                        $em = '';
1422
+                    } else {
1423
+                        $text_stack[0] .= $token;
1424
+                    }
1425
+                } else {
1426
+                    array_unshift($token_stack, $token);
1427
+                    array_unshift($text_stack, '');
1428
+                    $em = $token;
1429
+                }
1430
+            }
1431
+        }
1432
+        $this->in_emphasis_processing = false;
1433
+        return $text_stack[0];
1434
+    }
1435
+
1436
+    /**
1437
+     * Parse Markdown blockquotes to HTML
1438
+     * @param  string $text
1439
+     * @return string
1440
+     */
1441
+    protected function doBlockQuotes($text) {
1442
+        $text = preg_replace_callback('/
1443 1443
 			  (								# Wrap whole match in $1
1444 1444
 				(?>
1445 1445
 				  ^[ ]*>[ ]?			# ">" at the start of a line
@@ -1449,71 +1449,71 @@  discard block
 block discarded – undo
1449 1449
 				)+
1450 1450
 			  )
1451 1451
 			/xm',
1452
-			array($this, '_doBlockQuotes_callback'), $text);
1453
-
1454
-		return $text;
1455
-	}
1456
-
1457
-	/**
1458
-	 * Blockquote parsing callback
1459
-	 * @param  array $matches
1460
-	 * @return string
1461
-	 */
1462
-	protected function _doBlockQuotes_callback($matches) {
1463
-		$bq = $matches[1];
1464
-		// trim one level of quoting - trim whitespace-only lines
1465
-		$bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
1466
-		$bq = $this->runBlockGamut($bq); // recurse
1467
-
1468
-		$bq = preg_replace('/^/m', "  ", $bq);
1469
-		// These leading spaces cause problem with <pre> content,
1470
-		// so we need to fix that:
1471
-		$bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx',
1472
-			array($this, '_doBlockQuotes_callback2'), $bq);
1473
-
1474
-		return "\n" . $this->hashBlock("<blockquote>\n$bq\n</blockquote>") . "\n\n";
1475
-	}
1476
-
1477
-	/**
1478
-	 * Blockquote parsing callback
1479
-	 * @param  array $matches
1480
-	 * @return string
1481
-	 */
1482
-	protected function _doBlockQuotes_callback2($matches) {
1483
-		$pre = $matches[1];
1484
-		$pre = preg_replace('/^  /m', '', $pre);
1485
-		return $pre;
1486
-	}
1487
-
1488
-	/**
1489
-	 * Parse paragraphs
1490
-	 *
1491
-	 * @param  string $text String to process in paragraphs
1492
-	 * @param  boolean $wrap_in_p Whether paragraphs should be wrapped in <p> tags
1493
-	 * @return string
1494
-	 */
1495
-	protected function formParagraphs($text, $wrap_in_p = true) {
1496
-		// Strip leading and trailing lines:
1497
-		$text = preg_replace('/\A\n+|\n+\z/', '', $text);
1498
-
1499
-		$grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
1500
-
1501
-		// Wrap <p> tags and unhashify HTML blocks
1502
-		foreach ($grafs as $key => $value) {
1503
-			if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
1504
-				// Is a paragraph.
1505
-				$value = $this->runSpanGamut($value);
1506
-				if ($wrap_in_p) {
1507
-					$value = preg_replace('/^([ ]*)/', "<p>", $value);
1508
-					$value .= "</p>";
1509
-				}
1510
-				$grafs[$key] = $this->unhash($value);
1511
-			} else {
1512
-				// Is a block.
1513
-				// Modify elements of @grafs in-place...
1514
-				$graf = $value;
1515
-				$block = $this->html_hashes[$graf];
1516
-				$graf = $block;
1452
+            array($this, '_doBlockQuotes_callback'), $text);
1453
+
1454
+        return $text;
1455
+    }
1456
+
1457
+    /**
1458
+     * Blockquote parsing callback
1459
+     * @param  array $matches
1460
+     * @return string
1461
+     */
1462
+    protected function _doBlockQuotes_callback($matches) {
1463
+        $bq = $matches[1];
1464
+        // trim one level of quoting - trim whitespace-only lines
1465
+        $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
1466
+        $bq = $this->runBlockGamut($bq); // recurse
1467
+
1468
+        $bq = preg_replace('/^/m', "  ", $bq);
1469
+        // These leading spaces cause problem with <pre> content,
1470
+        // so we need to fix that:
1471
+        $bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx',
1472
+            array($this, '_doBlockQuotes_callback2'), $bq);
1473
+
1474
+        return "\n" . $this->hashBlock("<blockquote>\n$bq\n</blockquote>") . "\n\n";
1475
+    }
1476
+
1477
+    /**
1478
+     * Blockquote parsing callback
1479
+     * @param  array $matches
1480
+     * @return string
1481
+     */
1482
+    protected function _doBlockQuotes_callback2($matches) {
1483
+        $pre = $matches[1];
1484
+        $pre = preg_replace('/^  /m', '', $pre);
1485
+        return $pre;
1486
+    }
1487
+
1488
+    /**
1489
+     * Parse paragraphs
1490
+     *
1491
+     * @param  string $text String to process in paragraphs
1492
+     * @param  boolean $wrap_in_p Whether paragraphs should be wrapped in <p> tags
1493
+     * @return string
1494
+     */
1495
+    protected function formParagraphs($text, $wrap_in_p = true) {
1496
+        // Strip leading and trailing lines:
1497
+        $text = preg_replace('/\A\n+|\n+\z/', '', $text);
1498
+
1499
+        $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
1500
+
1501
+        // Wrap <p> tags and unhashify HTML blocks
1502
+        foreach ($grafs as $key => $value) {
1503
+            if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
1504
+                // Is a paragraph.
1505
+                $value = $this->runSpanGamut($value);
1506
+                if ($wrap_in_p) {
1507
+                    $value = preg_replace('/^([ ]*)/', "<p>", $value);
1508
+                    $value .= "</p>";
1509
+                }
1510
+                $grafs[$key] = $this->unhash($value);
1511
+            } else {
1512
+                // Is a block.
1513
+                // Modify elements of @grafs in-place...
1514
+                $graf = $value;
1515
+                $block = $this->html_hashes[$graf];
1516
+                $graf = $block;
1517 1517
 //				if (preg_match('{
1518 1518
 //					\A
1519 1519
 //					(							# $1 = <div> tag
@@ -1549,86 +1549,86 @@  discard block
 block discarded – undo
1549 1549
 //
1550 1550
 //					$graf = $div_open . "\n" . $div_content . "\n" . $div_close;
1551 1551
 //				}
1552
-				$grafs[$key] = $graf;
1553
-			}
1554
-		}
1555
-
1556
-		return implode("\n\n", $grafs);
1557
-	}
1558
-
1559
-	/**
1560
-	 * Encode text for a double-quoted HTML attribute. This function
1561
-	 * is *not* suitable for attributes enclosed in single quotes.
1562
-	 * @param  string $text
1563
-	 * @return string
1564
-	 */
1565
-	protected function encodeAttribute($text) {
1566
-		$text = $this->encodeAmpsAndAngles($text);
1567
-		$text = str_replace('"', '&quot;', $text);
1568
-		return $text;
1569
-	}
1570
-
1571
-	/**
1572
-	 * Encode text for a double-quoted HTML attribute containing a URL,
1573
-	 * applying the URL filter if set. Also generates the textual
1574
-	 * representation for the URL (removing mailto: or tel:) storing it in $text.
1575
-	 * This function is *not* suitable for attributes enclosed in single quotes.
1576
-	 *
1577
-	 * @param  string $url
1578
-	 * @param  string $text Passed by reference
1579
-	 * @return string        URL
1580
-	 */
1581
-	protected function encodeURLAttribute($url, &$text = null) {
1582
-		if (is_callable($this->url_filter_func)) {
1583
-			$url = call_user_func($this->url_filter_func, $url);
1584
-		}
1585
-
1586
-		if (preg_match('{^mailto:}i', $url)) {
1587
-			$url = $this->encodeEntityObfuscatedAttribute($url, $text, 7);
1588
-		} else if (preg_match('{^tel:}i', $url)) {
1589
-			$url = $this->encodeAttribute($url);
1590
-			$text = substr($url, 4);
1591
-		} else {
1592
-			$url = $this->encodeAttribute($url);
1593
-			$text = $url;
1594
-		}
1595
-
1596
-		return $url;
1597
-	}
1598
-
1599
-	/**
1600
-	 * Smart processing for ampersands and angle brackets that need to
1601
-	 * be encoded. Valid character entities are left alone unless the
1602
-	 * no-entities mode is set.
1603
-	 * @param  string $text
1604
-	 * @return string
1605
-	 */
1606
-	protected function encodeAmpsAndAngles($text) {
1607
-		if ($this->no_entities) {
1608
-			$text = str_replace('&', '&amp;', $text);
1609
-		} else {
1610
-			// Ampersand-encoding based entirely on Nat Irons's Amputator
1611
-			// MT plugin: <http://bumppo.net/projects/amputator/>
1612
-			$text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/',
1613
-								'&amp;', $text);
1614
-		}
1615
-		// Encode remaining <'s
1616
-		$text = str_replace('<', '&lt;', $text);
1617
-
1618
-		return $text;
1619
-	}
1620
-
1621
-	/**
1622
-	 * Parse Markdown automatic links to anchor HTML tags
1623
-	 * @param  string $text
1624
-	 * @return string
1625
-	 */
1626
-	protected function doAutoLinks($text) {
1627
-		$text = preg_replace_callback('{<((https?|ftp|dict|tel):[^\'">\s]+)>}i',
1628
-			array($this, '_doAutoLinks_url_callback'), $text);
1629
-
1630
-		// Email addresses: <[email protected]>
1631
-		$text = preg_replace_callback('{
1552
+                $grafs[$key] = $graf;
1553
+            }
1554
+        }
1555
+
1556
+        return implode("\n\n", $grafs);
1557
+    }
1558
+
1559
+    /**
1560
+     * Encode text for a double-quoted HTML attribute. This function
1561
+     * is *not* suitable for attributes enclosed in single quotes.
1562
+     * @param  string $text
1563
+     * @return string
1564
+     */
1565
+    protected function encodeAttribute($text) {
1566
+        $text = $this->encodeAmpsAndAngles($text);
1567
+        $text = str_replace('"', '&quot;', $text);
1568
+        return $text;
1569
+    }
1570
+
1571
+    /**
1572
+     * Encode text for a double-quoted HTML attribute containing a URL,
1573
+     * applying the URL filter if set. Also generates the textual
1574
+     * representation for the URL (removing mailto: or tel:) storing it in $text.
1575
+     * This function is *not* suitable for attributes enclosed in single quotes.
1576
+     *
1577
+     * @param  string $url
1578
+     * @param  string $text Passed by reference
1579
+     * @return string        URL
1580
+     */
1581
+    protected function encodeURLAttribute($url, &$text = null) {
1582
+        if (is_callable($this->url_filter_func)) {
1583
+            $url = call_user_func($this->url_filter_func, $url);
1584
+        }
1585
+
1586
+        if (preg_match('{^mailto:}i', $url)) {
1587
+            $url = $this->encodeEntityObfuscatedAttribute($url, $text, 7);
1588
+        } else if (preg_match('{^tel:}i', $url)) {
1589
+            $url = $this->encodeAttribute($url);
1590
+            $text = substr($url, 4);
1591
+        } else {
1592
+            $url = $this->encodeAttribute($url);
1593
+            $text = $url;
1594
+        }
1595
+
1596
+        return $url;
1597
+    }
1598
+
1599
+    /**
1600
+     * Smart processing for ampersands and angle brackets that need to
1601
+     * be encoded. Valid character entities are left alone unless the
1602
+     * no-entities mode is set.
1603
+     * @param  string $text
1604
+     * @return string
1605
+     */
1606
+    protected function encodeAmpsAndAngles($text) {
1607
+        if ($this->no_entities) {
1608
+            $text = str_replace('&', '&amp;', $text);
1609
+        } else {
1610
+            // Ampersand-encoding based entirely on Nat Irons's Amputator
1611
+            // MT plugin: <http://bumppo.net/projects/amputator/>
1612
+            $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/',
1613
+                                '&amp;', $text);
1614
+        }
1615
+        // Encode remaining <'s
1616
+        $text = str_replace('<', '&lt;', $text);
1617
+
1618
+        return $text;
1619
+    }
1620
+
1621
+    /**
1622
+     * Parse Markdown automatic links to anchor HTML tags
1623
+     * @param  string $text
1624
+     * @return string
1625
+     */
1626
+    protected function doAutoLinks($text) {
1627
+        $text = preg_replace_callback('{<((https?|ftp|dict|tel):[^\'">\s]+)>}i',
1628
+            array($this, '_doAutoLinks_url_callback'), $text);
1629
+
1630
+        // Email addresses: <[email protected]>
1631
+        $text = preg_replace_callback('{
1632 1632
 			<
1633 1633
 			(?:mailto:)?
1634 1634
 			(
@@ -1646,99 +1646,99 @@  discard block
 block discarded – undo
1646 1646
 			)
1647 1647
 			>
1648 1648
 			}xi',
1649
-			array($this, '_doAutoLinks_email_callback'), $text);
1650
-
1651
-		return $text;
1652
-	}
1653
-
1654
-	/**
1655
-	 * Parse URL callback
1656
-	 * @param  array $matches
1657
-	 * @return string
1658
-	 */
1659
-	protected function _doAutoLinks_url_callback($matches) {
1660
-		$url = $this->encodeURLAttribute($matches[1], $text);
1661
-		$link = "<a href=\"$url\">$text</a>";
1662
-		return $this->hashPart($link);
1663
-	}
1664
-
1665
-	/**
1666
-	 * Parse email address callback
1667
-	 * @param  array $matches
1668
-	 * @return string
1669
-	 */
1670
-	protected function _doAutoLinks_email_callback($matches) {
1671
-		$addr = $matches[1];
1672
-		$url = $this->encodeURLAttribute("mailto:$addr", $text);
1673
-		$link = "<a href=\"$url\">$text</a>";
1674
-		return $this->hashPart($link);
1675
-	}
1676
-
1677
-	/**
1678
-	 * Input: some text to obfuscate, e.g. "mailto:[email protected]"
1679
-	 *
1680
-	 * Output: the same text but with most characters encoded as either a
1681
-	 *         decimal or hex entity, in the hopes of foiling most address
1682
-	 *         harvesting spam bots. E.g.:
1683
-	 *
1684
-	 *        &#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x66;o&#111;
1685
-	 *        &#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#111;
1686
-	 *        &#x6d;
1687
-	 *
1688
-	 * Note: the additional output $tail is assigned the same value as the
1689
-	 * ouput, minus the number of characters specified by $head_length.
1690
-	 *
1691
-	 * Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
1692
-	 * With some optimizations by Milian Wolff. Forced encoding of HTML
1693
-	 * attribute special characters by Allan Odgaard.
1694
-	 *
1695
-	 * @param  string  $text
1696
-	 * @param  string  $tail Passed by reference
1697
-	 * @param  integer $head_length
1698
-	 * @return string
1699
-	 */
1700
-	protected function encodeEntityObfuscatedAttribute($text, &$tail = null, $head_length = 0) {
1701
-		if ($text == "") {
1702
-			return $tail = "";
1703
-		}
1704
-
1705
-		$chars = preg_split('/(?<!^)(?!$)/', $text);
1706
-		$seed = (int)abs(crc32($text) / strlen($text)); // Deterministic seed.
1707
-
1708
-		foreach ($chars as $key => $char) {
1709
-			$ord = ord($char);
1710
-			// Ignore non-ascii chars.
1711
-			if ($ord < 128) {
1712
-				$r = ($seed * (1 + $key)) % 100; // Pseudo-random function.
1713
-				// roughly 10% raw, 45% hex, 45% dec
1714
-				// '@' *must* be encoded. I insist.
1715
-				// '"' and '>' have to be encoded inside the attribute
1716
-				if ($r > 90 && strpos('@"&>', $char) === false) {
1717
-					/* do nothing */
1718
-				} else if ($r < 45) {
1719
-					$chars[$key] = '&#x'.dechex($ord).';';
1720
-				} else {
1721
-					$chars[$key] = '&#'.$ord.';';
1722
-				}
1723
-			}
1724
-		}
1725
-
1726
-		$text = implode('', $chars);
1727
-		$tail = $head_length ? implode('', array_slice($chars, $head_length)) : $text;
1728
-
1729
-		return $text;
1730
-	}
1731
-
1732
-	/**
1733
-	 * Take the string $str and parse it into tokens, hashing embeded HTML,
1734
-	 * escaped characters and handling code spans.
1735
-	 * @param  string $str
1736
-	 * @return string
1737
-	 */
1738
-	protected function parseSpan($str) {
1739
-		$output = '';
1740
-
1741
-		$span_re = '{
1649
+            array($this, '_doAutoLinks_email_callback'), $text);
1650
+
1651
+        return $text;
1652
+    }
1653
+
1654
+    /**
1655
+     * Parse URL callback
1656
+     * @param  array $matches
1657
+     * @return string
1658
+     */
1659
+    protected function _doAutoLinks_url_callback($matches) {
1660
+        $url = $this->encodeURLAttribute($matches[1], $text);
1661
+        $link = "<a href=\"$url\">$text</a>";
1662
+        return $this->hashPart($link);
1663
+    }
1664
+
1665
+    /**
1666
+     * Parse email address callback
1667
+     * @param  array $matches
1668
+     * @return string
1669
+     */
1670
+    protected function _doAutoLinks_email_callback($matches) {
1671
+        $addr = $matches[1];
1672
+        $url = $this->encodeURLAttribute("mailto:$addr", $text);
1673
+        $link = "<a href=\"$url\">$text</a>";
1674
+        return $this->hashPart($link);
1675
+    }
1676
+
1677
+    /**
1678
+     * Input: some text to obfuscate, e.g. "mailto:[email protected]"
1679
+     *
1680
+     * Output: the same text but with most characters encoded as either a
1681
+     *         decimal or hex entity, in the hopes of foiling most address
1682
+     *         harvesting spam bots. E.g.:
1683
+     *
1684
+     *        &#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x66;o&#111;
1685
+     *        &#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#111;
1686
+     *        &#x6d;
1687
+     *
1688
+     * Note: the additional output $tail is assigned the same value as the
1689
+     * ouput, minus the number of characters specified by $head_length.
1690
+     *
1691
+     * Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
1692
+     * With some optimizations by Milian Wolff. Forced encoding of HTML
1693
+     * attribute special characters by Allan Odgaard.
1694
+     *
1695
+     * @param  string  $text
1696
+     * @param  string  $tail Passed by reference
1697
+     * @param  integer $head_length
1698
+     * @return string
1699
+     */
1700
+    protected function encodeEntityObfuscatedAttribute($text, &$tail = null, $head_length = 0) {
1701
+        if ($text == "") {
1702
+            return $tail = "";
1703
+        }
1704
+
1705
+        $chars = preg_split('/(?<!^)(?!$)/', $text);
1706
+        $seed = (int)abs(crc32($text) / strlen($text)); // Deterministic seed.
1707
+
1708
+        foreach ($chars as $key => $char) {
1709
+            $ord = ord($char);
1710
+            // Ignore non-ascii chars.
1711
+            if ($ord < 128) {
1712
+                $r = ($seed * (1 + $key)) % 100; // Pseudo-random function.
1713
+                // roughly 10% raw, 45% hex, 45% dec
1714
+                // '@' *must* be encoded. I insist.
1715
+                // '"' and '>' have to be encoded inside the attribute
1716
+                if ($r > 90 && strpos('@"&>', $char) === false) {
1717
+                    /* do nothing */
1718
+                } else if ($r < 45) {
1719
+                    $chars[$key] = '&#x'.dechex($ord).';';
1720
+                } else {
1721
+                    $chars[$key] = '&#'.$ord.';';
1722
+                }
1723
+            }
1724
+        }
1725
+
1726
+        $text = implode('', $chars);
1727
+        $tail = $head_length ? implode('', array_slice($chars, $head_length)) : $text;
1728
+
1729
+        return $text;
1730
+    }
1731
+
1732
+    /**
1733
+     * Take the string $str and parse it into tokens, hashing embeded HTML,
1734
+     * escaped characters and handling code spans.
1735
+     * @param  string $str
1736
+     * @return string
1737
+     */
1738
+    protected function parseSpan($str) {
1739
+        $output = '';
1740
+
1741
+        $span_re = '{
1742 1742
 				(
1743 1743
 					\\\\'.$this->escape_chars_re.'
1744 1744
 				|
@@ -1764,146 +1764,146 @@  discard block
 block discarded – undo
1764 1764
 				)
1765 1765
 				}xs';
1766 1766
 
1767
-		while (1) {
1768
-			// Each loop iteration seach for either the next tag, the next
1769
-			// openning code span marker, or the next escaped character.
1770
-			// Each token is then passed to handleSpanToken.
1771
-			$parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
1772
-
1773
-			// Create token from text preceding tag.
1774
-			if ($parts[0] != "") {
1775
-				$output .= $parts[0];
1776
-			}
1777
-
1778
-			// Check if we reach the end.
1779
-			if (isset($parts[1])) {
1780
-				$output .= $this->handleSpanToken($parts[1], $parts[2]);
1781
-				$str = $parts[2];
1782
-			} else {
1783
-				break;
1784
-			}
1785
-		}
1786
-
1787
-		return $output;
1788
-	}
1789
-
1790
-	/**
1791
-	 * Handle $token provided by parseSpan by determining its nature and
1792
-	 * returning the corresponding value that should replace it.
1793
-	 * @param  string $token
1794
-	 * @param  string $str Passed by reference
1795
-	 * @return string
1796
-	 */
1797
-	protected function handleSpanToken($token, &$str) {
1798
-		switch ($token[0]) {
1799
-			case "\\":
1800
-				return $this->hashPart("&#". ord($token[1]). ";");
1801
-			case "`":
1802
-				// Search for end marker in remaining text.
1803
-				if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm',
1804
-					$str, $matches))
1805
-				{
1806
-					$str = $matches[2];
1807
-					$codespan = $this->makeCodeSpan($matches[1]);
1808
-					return $this->hashPart($codespan);
1809
-				}
1810
-				return $token; // Return as text since no ending marker found.
1811
-			default:
1812
-				return $this->hashPart($token);
1813
-		}
1814
-	}
1815
-
1816
-	/**
1817
-	 * Remove one level of line-leading tabs or spaces
1818
-	 * @param  string $text
1819
-	 * @return string
1820
-	 */
1821
-	protected function outdent($text) {
1822
-		return preg_replace('/^(\t|[ ]{1,' . $this->tab_width . '})/m', '', $text);
1823
-	}
1824
-
1825
-
1826
-	/**
1827
-	 * String length function for detab. `_initDetab` will create a function to
1828
-	 * handle UTF-8 if the default function does not exist.
1829
-	 * @var string
1830
-	 */
1831
-	protected $utf8_strlen = 'mb_strlen';
1832
-
1833
-	/**
1834
-	 * Replace tabs with the appropriate amount of spaces.
1835
-	 *
1836
-	 * For each line we separate the line in blocks delemited by tab characters.
1837
-	 * Then we reconstruct every line by adding the  appropriate number of space
1838
-	 * between each blocks.
1839
-	 *
1840
-	 * @param  string $text
1841
-	 * @return string
1842
-	 */
1843
-	protected function detab($text) {
1844
-		$text = preg_replace_callback('/^.*\t.*$/m',
1845
-			array($this, '_detab_callback'), $text);
1846
-
1847
-		return $text;
1848
-	}
1849
-
1850
-	/**
1851
-	 * Replace tabs callback
1852
-	 * @param  string $matches
1853
-	 * @return string
1854
-	 */
1855
-	protected function _detab_callback($matches) {
1856
-		$line = $matches[0];
1857
-		$strlen = $this->utf8_strlen; // strlen function for UTF-8.
1858
-
1859
-		// Split in blocks.
1860
-		$blocks = explode("\t", $line);
1861
-		// Add each blocks to the line.
1862
-		$line = $blocks[0];
1863
-		unset($blocks[0]); // Do not add first block twice.
1864
-		foreach ($blocks as $block) {
1865
-			// Calculate amount of space, insert spaces, insert block.
1866
-			$amount = $this->tab_width -
1867
-				$strlen($line, 'UTF-8') % $this->tab_width;
1868
-			$line .= str_repeat(" ", $amount) . $block;
1869
-		}
1870
-		return $line;
1871
-	}
1872
-
1873
-	/**
1874
-	 * Check for the availability of the function in the `utf8_strlen` property
1875
-	 * (initially `mb_strlen`). If the function is not available, create a
1876
-	 * function that will loosely count the number of UTF-8 characters with a
1877
-	 * regular expression.
1878
-	 * @return void
1879
-	 */
1880
-	protected function _initDetab() {
1881
-
1882
-		if (function_exists($this->utf8_strlen)) {
1883
-			return;
1884
-		}
1885
-
1886
-		$this->utf8_strlen = function($text) {
1887
-			return preg_match_all('/[\x00-\xBF]|[\xC0-\xFF][\x80-\xBF]*/', $text, $m);
1888
-		};
1889
-	}
1890
-
1891
-	/**
1892
-	 * Swap back in all the tags hashed by _HashHTMLBlocks.
1893
-	 * @param  string $text
1894
-	 * @return string
1895
-	 */
1896
-	protected function unhash($text) {
1897
-		return preg_replace_callback('/(.)\x1A[0-9]+\1/',
1898
-			array($this, '_unhash_callback'), $text);
1899
-	}
1900
-
1901
-	/**
1902
-	 * Unhashing callback
1903
-	 * @param  array $matches
1904
-	 * @return string
1905
-	 */
1906
-	protected function _unhash_callback($matches) {
1907
-		return $this->html_hashes[$matches[0]];
1908
-	}
1767
+        while (1) {
1768
+            // Each loop iteration seach for either the next tag, the next
1769
+            // openning code span marker, or the next escaped character.
1770
+            // Each token is then passed to handleSpanToken.
1771
+            $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
1772
+
1773
+            // Create token from text preceding tag.
1774
+            if ($parts[0] != "") {
1775
+                $output .= $parts[0];
1776
+            }
1777
+
1778
+            // Check if we reach the end.
1779
+            if (isset($parts[1])) {
1780
+                $output .= $this->handleSpanToken($parts[1], $parts[2]);
1781
+                $str = $parts[2];
1782
+            } else {
1783
+                break;
1784
+            }
1785
+        }
1786
+
1787
+        return $output;
1788
+    }
1789
+
1790
+    /**
1791
+     * Handle $token provided by parseSpan by determining its nature and
1792
+     * returning the corresponding value that should replace it.
1793
+     * @param  string $token
1794
+     * @param  string $str Passed by reference
1795
+     * @return string
1796
+     */
1797
+    protected function handleSpanToken($token, &$str) {
1798
+        switch ($token[0]) {
1799
+            case "\\":
1800
+                return $this->hashPart("&#". ord($token[1]). ";");
1801
+            case "`":
1802
+                // Search for end marker in remaining text.
1803
+                if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm',
1804
+                    $str, $matches))
1805
+                {
1806
+                    $str = $matches[2];
1807
+                    $codespan = $this->makeCodeSpan($matches[1]);
1808
+                    return $this->hashPart($codespan);
1809
+                }
1810
+                return $token; // Return as text since no ending marker found.
1811
+            default:
1812
+                return $this->hashPart($token);
1813
+        }
1814
+    }
1815
+
1816
+    /**
1817
+     * Remove one level of line-leading tabs or spaces
1818
+     * @param  string $text
1819
+     * @return string
1820
+     */
1821
+    protected function outdent($text) {
1822
+        return preg_replace('/^(\t|[ ]{1,' . $this->tab_width . '})/m', '', $text);
1823
+    }
1824
+
1825
+
1826
+    /**
1827
+     * String length function for detab. `_initDetab` will create a function to
1828
+     * handle UTF-8 if the default function does not exist.
1829
+     * @var string
1830
+     */
1831
+    protected $utf8_strlen = 'mb_strlen';
1832
+
1833
+    /**
1834
+     * Replace tabs with the appropriate amount of spaces.
1835
+     *
1836
+     * For each line we separate the line in blocks delemited by tab characters.
1837
+     * Then we reconstruct every line by adding the  appropriate number of space
1838
+     * between each blocks.
1839
+     *
1840
+     * @param  string $text
1841
+     * @return string
1842
+     */
1843
+    protected function detab($text) {
1844
+        $text = preg_replace_callback('/^.*\t.*$/m',
1845
+            array($this, '_detab_callback'), $text);
1846
+
1847
+        return $text;
1848
+    }
1849
+
1850
+    /**
1851
+     * Replace tabs callback
1852
+     * @param  string $matches
1853
+     * @return string
1854
+     */
1855
+    protected function _detab_callback($matches) {
1856
+        $line = $matches[0];
1857
+        $strlen = $this->utf8_strlen; // strlen function for UTF-8.
1858
+
1859
+        // Split in blocks.
1860
+        $blocks = explode("\t", $line);
1861
+        // Add each blocks to the line.
1862
+        $line = $blocks[0];
1863
+        unset($blocks[0]); // Do not add first block twice.
1864
+        foreach ($blocks as $block) {
1865
+            // Calculate amount of space, insert spaces, insert block.
1866
+            $amount = $this->tab_width -
1867
+                $strlen($line, 'UTF-8') % $this->tab_width;
1868
+            $line .= str_repeat(" ", $amount) . $block;
1869
+        }
1870
+        return $line;
1871
+    }
1872
+
1873
+    /**
1874
+     * Check for the availability of the function in the `utf8_strlen` property
1875
+     * (initially `mb_strlen`). If the function is not available, create a
1876
+     * function that will loosely count the number of UTF-8 characters with a
1877
+     * regular expression.
1878
+     * @return void
1879
+     */
1880
+    protected function _initDetab() {
1881
+
1882
+        if (function_exists($this->utf8_strlen)) {
1883
+            return;
1884
+        }
1885
+
1886
+        $this->utf8_strlen = function($text) {
1887
+            return preg_match_all('/[\x00-\xBF]|[\xC0-\xFF][\x80-\xBF]*/', $text, $m);
1888
+        };
1889
+    }
1890
+
1891
+    /**
1892
+     * Swap back in all the tags hashed by _HashHTMLBlocks.
1893
+     * @param  string $text
1894
+     * @return string
1895
+     */
1896
+    protected function unhash($text) {
1897
+        return preg_replace_callback('/(.)\x1A[0-9]+\1/',
1898
+            array($this, '_unhash_callback'), $text);
1899
+    }
1900
+
1901
+    /**
1902
+     * Unhashing callback
1903
+     * @param  array $matches
1904
+     * @return string
1905
+     */
1906
+    protected function _unhash_callback($matches) {
1907
+        return $this->html_hashes[$matches[0]];
1908
+    }
1909 1909
 }
Please login to merge, or discard this patch.
Spacing   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -35,7 +35,7 @@  discard block
 block discarded – undo
35 35
 
36 36
 		// Try to take parser from the static parser list
37 37
 		static $parser_list;
38
-		$parser =& $parser_list[$parser_class];
38
+		$parser = & $parser_list[$parser_class];
39 39
 
40 40
 		// Create the parser it not already set
41 41
 		if (!$parser) {
@@ -157,14 +157,14 @@  discard block
 block discarded – undo
157 157
 		$this->prepareItalicsAndBold();
158 158
 
159 159
 		$this->nested_brackets_re =
160
-			str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
160
+			str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth) .
161 161
 			str_repeat('\])*', $this->nested_brackets_depth);
162 162
 
163 163
 		$this->nested_url_parenthesis_re =
164
-			str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
164
+			str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth) .
165 165
 			str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
166 166
 
167
-		$this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
167
+		$this->escape_chars_re = '[' . preg_quote($this->escape_chars) . ']';
168 168
 
169 169
 		// Sort document, block, and span gamut in ascendent priority order.
170 170
 		asort($this->document_gamut);
@@ -283,7 +283,7 @@  discard block
 block discarded – undo
283 283
 
284 284
 		// Link defs are in the form: ^[id]: url "optional title"
285 285
 		$text = preg_replace_callback('{
286
-							^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?:	# id = $1
286
+							^[ ]{0,'.$less_than_tab . '}\[(.+)\][ ]?:	# id = $1
287 287
 							  [ ]*
288 288
 							  \n?				# maybe *one* newline
289 289
 							  [ ]*
@@ -319,7 +319,7 @@  discard block
 block discarded – undo
319 319
 		$link_id = strtolower($matches[1]);
320 320
 		$url = $matches[2] == '' ? $matches[3] : $matches[2];
321 321
 		$this->urls[$link_id] = $url;
322
-		$this->titles[$link_id] =& $matches[4];
322
+		$this->titles[$link_id] = & $matches[4];
323 323
 		return ''; // String that will replace the block
324 324
 	}
325 325
 
@@ -351,9 +351,9 @@  discard block
 block discarded – undo
351 351
 		 * *  List "b" is made of tags which are always block-level;
352 352
 		 */
353 353
 		$block_tags_a_re = 'ins|del';
354
-		$block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
355
-						   'script|noscript|style|form|fieldset|iframe|math|svg|'.
356
-						   'article|section|nav|aside|hgroup|header|footer|'.
354
+		$block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|' .
355
+						   'script|noscript|style|form|fieldset|iframe|math|svg|' .
356
+						   'article|section|nav|aside|hgroup|header|footer|' .
357 357
 						   'figure';
358 358
 
359 359
 		// Regular expression for the content of a block tag.
@@ -378,12 +378,12 @@  discard block
 block discarded – undo
378 378
 				  [^<]+			# content without tag
379 379
 				|
380 380
 				  <\2			# nested opening tag
381
-					'.$attr.'	# attributes
381
+					'.$attr . '	# attributes
382 382
 					(?>
383 383
 					  />
384 384
 					|
385
-					  >', $nested_tags_level).	// end of opening tag
386
-					  '.*?'.					// last level nested tag content
385
+					  >', $nested_tags_level) . // end of opening tag
386
+					  '.*?' . // last level nested tag content
387 387
 			str_repeat('
388 388
 					  </\2\s*>	# closing nested tag
389 389
 					)
@@ -419,20 +419,20 @@  discard block
 block discarded – undo
419 419
 			  # Match from `\n<tag>` to `</tag>\n`, handling nested tags
420 420
 			  # in between.
421 421
 
422
-						[ ]{0,'.$less_than_tab.'}
423
-						<('.$block_tags_b_re.')# start tag = $2
424
-						'.$attr.'>			# attributes followed by > and \n
425
-						'.$content.'		# content, support nesting
422
+						[ ]{0,'.$less_than_tab . '}
423
+						<('.$block_tags_b_re . ')# start tag = $2
424
+						'.$attr . '>			# attributes followed by > and \n
425
+						'.$content . '		# content, support nesting
426 426
 						</\2>				# the matching end tag
427 427
 						[ ]*				# trailing spaces/tabs
428 428
 						(?=\n+|\Z)	# followed by a newline or end of document
429 429
 
430 430
 			| # Special version for tags of group a.
431 431
 
432
-						[ ]{0,'.$less_than_tab.'}
433
-						<('.$block_tags_a_re.')# start tag = $3
434
-						'.$attr.'>[ ]*\n	# attributes followed by >
435
-						'.$content2.'		# content, support nesting
432
+						[ ]{0,'.$less_than_tab . '}
433
+						<('.$block_tags_a_re . ')# start tag = $3
434
+						'.$attr . '>[ ]*\n	# attributes followed by >
435
+						'.$content2 . '		# content, support nesting
436 436
 						</\3>				# the matching end tag
437 437
 						[ ]*				# trailing spaces/tabs
438 438
 						(?=\n+|\Z)	# followed by a newline or end of document
@@ -440,16 +440,16 @@  discard block
 block discarded – undo
440 440
 			| # Special case just for <hr />. It was easier to make a special
441 441
 			  # case than to make the other regex more complicated.
442 442
 
443
-						[ ]{0,'.$less_than_tab.'}
443
+						[ ]{0,'.$less_than_tab . '}
444 444
 						<(hr)				# start tag = $2
445
-						'.$attr.'			# attributes
445
+						'.$attr . '			# attributes
446 446
 						/?>					# the matching end tag
447 447
 						[ ]*
448 448
 						(?=\n{2,}|\Z)		# followed by a blank line or end of document
449 449
 
450 450
 			| # Special case for standalone HTML comments:
451 451
 
452
-					[ ]{0,'.$less_than_tab.'}
452
+					[ ]{0,'.$less_than_tab . '}
453 453
 					(?s:
454 454
 						<!-- .*? -->
455 455
 					)
@@ -458,7 +458,7 @@  discard block
 block discarded – undo
458 458
 
459 459
 			| # PHP and ASP-style processor instructions (<? and <%)
460 460
 
461
-					[ ]{0,'.$less_than_tab.'}
461
+					[ ]{0,'.$less_than_tab . '}
462 462
 					(?s:
463 463
 						<([?%])			# $2
464 464
 						.*?
@@ -589,7 +589,7 @@  discard block
 block discarded – undo
589 589
 				[ ]*		# Tailing spaces
590 590
 				$			# End of line.
591 591
 			}mx',
592
-			"\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n",
592
+			"\n" . $this->hashBlock("<hr$this->empty_element_suffix") . "\n",
593 593
 			$text
594 594
 		);
595 595
 	}
@@ -668,7 +668,7 @@  discard block
 block discarded – undo
668 668
 		$text = preg_replace_callback('{
669 669
 			(					# wrap whole match in $1
670 670
 			  \[
671
-				('.$this->nested_brackets_re.')	# link text = $2
671
+				('.$this->nested_brackets_re . ')	# link text = $2
672 672
 			  \]
673 673
 
674 674
 			  [ ]?				# one optional space
@@ -685,14 +685,14 @@  discard block
 block discarded – undo
685 685
 		$text = preg_replace_callback('{
686 686
 			(				# wrap whole match in $1
687 687
 			  \[
688
-				('.$this->nested_brackets_re.')	# link text = $2
688
+				('.$this->nested_brackets_re . ')	# link text = $2
689 689
 			  \]
690 690
 			  \(			# literal paren
691 691
 				[ \n]*
692 692
 				(?:
693 693
 					<(.+?)>	# href = $3
694 694
 				|
695
-					('.$this->nested_url_parenthesis_re.')	# href = $4
695
+					('.$this->nested_url_parenthesis_re . ')	# href = $4
696 696
 				)
697 697
 				[ \n]*
698 698
 				(			# $5
@@ -728,9 +728,9 @@  discard block
 block discarded – undo
728 728
 	 * @return string
729 729
 	 */
730 730
 	protected function _doAnchors_reference_callback($matches) {
731
-		$whole_match =  $matches[1];
732
-		$link_text   =  $matches[2];
733
-		$link_id     =& $matches[3];
731
+		$whole_match = $matches[1];
732
+		$link_text   = $matches[2];
733
+		$link_id     = & $matches[3];
734 734
 
735 735
 		if ($link_id == "") {
736 736
 			// for shortcut links like [this][] or [this].
@@ -746,10 +746,10 @@  discard block
 block discarded – undo
746 746
 			$url = $this->encodeURLAttribute($url);
747 747
 
748 748
 			$result = "<a href=\"$url\"";
749
-			if ( isset( $this->titles[$link_id] ) ) {
749
+			if (isset($this->titles[$link_id])) {
750 750
 				$title = $this->titles[$link_id];
751 751
 				$title = $this->encodeAttribute($title);
752
-				$result .=  " title=\"$title\"";
752
+				$result .= " title=\"$title\"";
753 753
 			}
754 754
 
755 755
 			$link_text = $this->runSpanGamut($link_text);
@@ -767,9 +767,9 @@  discard block
 block discarded – undo
767 767
 	 * @return string
768 768
 	 */
769 769
 	protected function _doAnchors_inline_callback($matches) {
770
-		$link_text		=  $this->runSpanGamut($matches[2]);
771
-		$url			=  $matches[3] === '' ? $matches[4] : $matches[3];
772
-		$title			=& $matches[7];
770
+		$link_text = $this->runSpanGamut($matches[2]);
771
+		$url = $matches[3] === '' ? $matches[4] : $matches[3];
772
+		$title = & $matches[7];
773 773
 
774 774
 		// If the URL was of the form <s p a c e s> it got caught by the HTML
775 775
 		// tag parser and hashed. Need to reverse the process before using
@@ -783,7 +783,7 @@  discard block
 block discarded – undo
783 783
 		$result = "<a href=\"$url\"";
784 784
 		if (isset($title)) {
785 785
 			$title = $this->encodeAttribute($title);
786
-			$result .=  " title=\"$title\"";
786
+			$result .= " title=\"$title\"";
787 787
 		}
788 788
 
789 789
 		$link_text = $this->runSpanGamut($link_text);
@@ -802,7 +802,7 @@  discard block
 block discarded – undo
802 802
 		$text = preg_replace_callback('{
803 803
 			(				# wrap whole match in $1
804 804
 			  !\[
805
-				('.$this->nested_brackets_re.')		# alt text = $2
805
+				('.$this->nested_brackets_re . ')		# alt text = $2
806 806
 			  \]
807 807
 
808 808
 			  [ ]?				# one optional space
@@ -821,7 +821,7 @@  discard block
 block discarded – undo
821 821
 		$text = preg_replace_callback('{
822 822
 			(				# wrap whole match in $1
823 823
 			  !\[
824
-				('.$this->nested_brackets_re.')		# alt text = $2
824
+				('.$this->nested_brackets_re . ')		# alt text = $2
825 825
 			  \]
826 826
 			  \s?			# One optional whitespace character
827 827
 			  \(			# literal paren
@@ -829,7 +829,7 @@  discard block
 block discarded – undo
829 829
 				(?:
830 830
 					<(\S*)>	# src url = $3
831 831
 				|
832
-					('.$this->nested_url_parenthesis_re.')	# src url = $4
832
+					('.$this->nested_url_parenthesis_re . ')	# src url = $4
833 833
 				)
834 834
 				[ \n]*
835 835
 				(			# $5
@@ -867,7 +867,7 @@  discard block
 block discarded – undo
867 867
 			if (isset($this->titles[$link_id])) {
868 868
 				$title = $this->titles[$link_id];
869 869
 				$title = $this->encodeAttribute($title);
870
-				$result .=  " title=\"$title\"";
870
+				$result .= " title=\"$title\"";
871 871
 			}
872 872
 			$result .= $this->empty_element_suffix;
873 873
 			$result = $this->hashPart($result);
@@ -885,17 +885,17 @@  discard block
 block discarded – undo
885 885
 	 * @return string
886 886
 	 */
887 887
 	protected function _doImages_inline_callback($matches) {
888
-		$whole_match	= $matches[1];
889
-		$alt_text		= $matches[2];
890
-		$url			= $matches[3] == '' ? $matches[4] : $matches[3];
891
-		$title			=& $matches[7];
888
+		$whole_match = $matches[1];
889
+		$alt_text = $matches[2];
890
+		$url = $matches[3] == '' ? $matches[4] : $matches[3];
891
+		$title = & $matches[7];
892 892
 
893 893
 		$alt_text = $this->encodeAttribute($alt_text);
894 894
 		$url = $this->encodeURLAttribute($url);
895 895
 		$result = "<img src=\"$url\" alt=\"$alt_text\"";
896 896
 		if (isset($title)) {
897 897
 			$title = $this->encodeAttribute($title);
898
-			$result .=  " title=\"$title\""; // $title already quoted
898
+			$result .= " title=\"$title\""; // $title already quoted
899 899
 		}
900 900
 		$result .= $this->empty_element_suffix;
901 901
 
@@ -956,7 +956,7 @@  discard block
 block discarded – undo
956 956
 		// ID attribute generation
957 957
 		$idAtt = $this->_generateIdFromHeaderValue($matches[1]);
958 958
 
959
-		$block = "<h$level$idAtt>".$this->runSpanGamut($matches[1])."</h$level>";
959
+		$block = "<h$level$idAtt>" . $this->runSpanGamut($matches[1]) . "</h$level>";
960 960
 		return "\n" . $this->hashBlock($block) . "\n\n";
961 961
 	}
962 962
 
@@ -970,7 +970,7 @@  discard block
 block discarded – undo
970 970
 		$idAtt = $this->_generateIdFromHeaderValue($matches[2]);
971 971
 
972 972
 		$level = strlen($matches[1]);
973
-		$block = "<h$level$idAtt>".$this->runSpanGamut($matches[2])."</h$level>";
973
+		$block = "<h$level$idAtt>" . $this->runSpanGamut($matches[2]) . "</h$level>";
974 974
 		return "\n" . $this->hashBlock($block) . "\n\n";
975 975
 	}
976 976
 
@@ -1018,8 +1018,8 @@  discard block
 block discarded – undo
1018 1018
 			$whole_list_re = '
1019 1019
 				(								# $1 = whole list
1020 1020
 				  (								# $2
1021
-					([ ]{0,'.$less_than_tab.'})	# $3 = number of spaces
1022
-					('.$marker_re.')			# $4 = first list item marker
1021
+					([ ]{0,'.$less_than_tab . '})	# $3 = number of spaces
1022
+					('.$marker_re . ')			# $4 = first list item marker
1023 1023
 					[ ]+
1024 1024
 				  )
1025 1025
 				  (?s:.+?)
@@ -1030,13 +1030,13 @@  discard block
 block discarded – undo
1030 1030
 					  (?=\S)
1031 1031
 					  (?!						# Negative lookahead for another list item marker
1032 1032
 						[ ]*
1033
-						'.$marker_re.'[ ]+
1033
+						'.$marker_re . '[ ]+
1034 1034
 					  )
1035 1035
 					|
1036 1036
 					  (?=						# Lookahead for another kind of list
1037 1037
 					    \n
1038 1038
 						\3						# Must have the same indentation
1039
-						'.$other_marker_re.'[ ]+
1039
+						'.$other_marker_re . '[ ]+
1040 1040
 					  )
1041 1041
 				  )
1042 1042
 				)
@@ -1048,13 +1048,13 @@  discard block
 block discarded – undo
1048 1048
 			if ($this->list_level) {
1049 1049
 				$text = preg_replace_callback('{
1050 1050
 						^
1051
-						'.$whole_list_re.'
1051
+						'.$whole_list_re . '
1052 1052
 					}mx',
1053 1053
 					array($this, '_doLists_callback'), $text);
1054 1054
 			} else {
1055 1055
 				$text = preg_replace_callback('{
1056 1056
 						(?:(?<=\n)\n|\A\n?) # Must eat the newline
1057
-						'.$whole_list_re.'
1057
+						'.$whole_list_re . '
1058 1058
 					}mx',
1059 1059
 					array($this, '_doLists_callback'), $text);
1060 1060
 			}
@@ -1078,7 +1078,7 @@  discard block
 block discarded – undo
1078 1078
 		$list = $matches[1];
1079 1079
 		$list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol";
1080 1080
 
1081
-		$marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
1081
+		$marker_any_re = ($list_type == "ul" ? $marker_ul_re : $marker_ol_re);
1082 1082
 
1083 1083
 		$list .= "\n";
1084 1084
 		$result = $this->processListItems($list, $marker_any_re);
@@ -1089,18 +1089,18 @@  discard block
 block discarded – undo
1089 1089
 			if ($list_type == 'ol') {
1090 1090
 				$ol_start_array = array();
1091 1091
 				$ol_start_check = preg_match("/$marker_ol_start_re/", $matches[4], $ol_start_array);
1092
-				if ($ol_start_check){
1092
+				if ($ol_start_check) {
1093 1093
 					$ol_start = $ol_start_array[0];
1094 1094
 				}
1095 1095
 			}
1096 1096
 		}
1097 1097
 
1098
-		if ($ol_start > 1 && $list_type == 'ol'){
1098
+		if ($ol_start > 1 && $list_type == 'ol') {
1099 1099
 			$result = $this->hashBlock("<$list_type start=\"$ol_start\">\n" . $result . "</$list_type>");
1100 1100
 		} else {
1101 1101
 			$result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
1102 1102
 		}
1103
-		return "\n". $result ."\n\n";
1103
+		return "\n" . $result . "\n\n";
1104 1104
 	}
1105 1105
 
1106 1106
 	/**
@@ -1147,12 +1147,12 @@  discard block
 block discarded – undo
1147 1147
 		$list_str = preg_replace_callback('{
1148 1148
 			(\n)?							# leading line = $1
1149 1149
 			(^[ ]*)							# leading whitespace = $2
1150
-			('.$marker_any_re.'				# list marker and space = $3
1150
+			('.$marker_any_re . '				# list marker and space = $3
1151 1151
 				(?:[ ]+|(?=\n))	# space only required if item is not empty
1152 1152
 			)
1153 1153
 			((?s:.*?))						# list item text   = $4
1154 1154
 			(?:(\n+(?=\n))|\n)				# tailing blank line = $5
1155
-			(?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n))))
1155
+			(?= \n* (\z | \2 ('.$marker_any_re . ') (?:[ ]+|(?=\n))))
1156 1156
 			}xm',
1157 1157
 			array($this, '_processListItems_callback'), $list_str);
1158 1158
 
@@ -1167,17 +1167,17 @@  discard block
 block discarded – undo
1167 1167
 	 */
1168 1168
 	protected function _processListItems_callback($matches) {
1169 1169
 		$item = $matches[4];
1170
-		$leading_line =& $matches[1];
1171
-		$leading_space =& $matches[2];
1170
+		$leading_line = & $matches[1];
1171
+		$leading_space = & $matches[2];
1172 1172
 		$marker_space = $matches[3];
1173
-		$tailing_blank_line =& $matches[5];
1173
+		$tailing_blank_line = & $matches[5];
1174 1174
 
1175 1175
 		if ($leading_line || $tailing_blank_line ||
1176 1176
 			preg_match('/\n{2,}/', $item))
1177 1177
 		{
1178 1178
 			// Replace marker with the appropriate whitespace indentation
1179 1179
 			$item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
1180
-			$item = $this->runBlockGamut($this->outdent($item)."\n");
1180
+			$item = $this->runBlockGamut($this->outdent($item) . "\n");
1181 1181
 		} else {
1182 1182
 			// Recursion for sub-lists:
1183 1183
 			$item = $this->doLists($this->outdent($item));
@@ -1197,11 +1197,11 @@  discard block
 block discarded – undo
1197 1197
 				(?:\n\n|\A\n?)
1198 1198
 				(	            # $1 = the code block -- one or more lines, starting with a space/tab
1199 1199
 				  (?>
1200
-					[ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces
1200
+					[ ]{'.$this->tab_width . '}  # Lines must start with a tab or a tab-width of spaces
1201 1201
 					.*\n+
1202 1202
 				  )+
1203 1203
 				)
1204
-				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
1204
+				((?=^[ ]{0,'.$this->tab_width . '}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
1205 1205
 			}xm',
1206 1206
 			array($this, '_doCodeBlocks_callback'), $text);
1207 1207
 
@@ -1329,8 +1329,8 @@  discard block
 block discarded – undo
1329 1329
 			// Each token is then passed to handleSpanToken.
1330 1330
 			$parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
1331 1331
 			$text_stack[0] .= $parts[0];
1332
-			$token =& $parts[1];
1333
-			$text =& $parts[2];
1332
+			$token = & $parts[1];
1333
+			$text = & $parts[2];
1334 1334
 
1335 1335
 			if (empty($token)) {
1336 1336
 				// Reached end of text span: empty stack without emitting.
@@ -1357,7 +1357,7 @@  discard block
 block discarded – undo
1357 1357
 				} else {
1358 1358
 					// Other closing marker: close one em or strong and
1359 1359
 					// change current token state to match the other
1360
-					$token_stack[0] = str_repeat($token[0], 3-$token_len);
1360
+					$token_stack[0] = str_repeat($token[0], 3 - $token_len);
1361 1361
 					$tag = $token_len == 2 ? "strong" : "em";
1362 1362
 					$span = $text_stack[0];
1363 1363
 					$span = $this->runSpanGamut($span);
@@ -1703,22 +1703,22 @@  discard block
 block discarded – undo
1703 1703
 		}
1704 1704
 
1705 1705
 		$chars = preg_split('/(?<!^)(?!$)/', $text);
1706
-		$seed = (int)abs(crc32($text) / strlen($text)); // Deterministic seed.
1706
+		$seed = (int)abs(crc32($text)/strlen($text)); // Deterministic seed.
1707 1707
 
1708 1708
 		foreach ($chars as $key => $char) {
1709 1709
 			$ord = ord($char);
1710 1710
 			// Ignore non-ascii chars.
1711 1711
 			if ($ord < 128) {
1712
-				$r = ($seed * (1 + $key)) % 100; // Pseudo-random function.
1712
+				$r = ($seed*(1 + $key))%100; // Pseudo-random function.
1713 1713
 				// roughly 10% raw, 45% hex, 45% dec
1714 1714
 				// '@' *must* be encoded. I insist.
1715 1715
 				// '"' and '>' have to be encoded inside the attribute
1716 1716
 				if ($r > 90 && strpos('@"&>', $char) === false) {
1717 1717
 					/* do nothing */
1718 1718
 				} else if ($r < 45) {
1719
-					$chars[$key] = '&#x'.dechex($ord).';';
1719
+					$chars[$key] = '&#x' . dechex($ord) . ';';
1720 1720
 				} else {
1721
-					$chars[$key] = '&#'.$ord.';';
1721
+					$chars[$key] = '&#' . $ord . ';';
1722 1722
 				}
1723 1723
 			}
1724 1724
 		}
@@ -1740,11 +1740,11 @@  discard block
 block discarded – undo
1740 1740
 
1741 1741
 		$span_re = '{
1742 1742
 				(
1743
-					\\\\'.$this->escape_chars_re.'
1743
+					\\\\'.$this->escape_chars_re . '
1744 1744
 				|
1745 1745
 					(?<![`\\\\])
1746 1746
 					`+						# code span marker
1747
-			'.( $this->no_markup ? '' : '
1747
+			'.($this->no_markup ? '' : '
1748 1748
 				|
1749 1749
 					<!--    .*?     -->		# comment
1750 1750
 				|
@@ -1760,7 +1760,7 @@  discard block
 block discarded – undo
1760 1760
 					<[-a-zA-Z0-9:_]+\s*/> # xml-style empty tag
1761 1761
 				|
1762 1762
 					</[-a-zA-Z0-9:_]+\s*> # closing tag
1763
-			').'
1763
+			') . '
1764 1764
 				)
1765 1765
 				}xs';
1766 1766
 
@@ -1797,10 +1797,10 @@  discard block
 block discarded – undo
1797 1797
 	protected function handleSpanToken($token, &$str) {
1798 1798
 		switch ($token[0]) {
1799 1799
 			case "\\":
1800
-				return $this->hashPart("&#". ord($token[1]). ";");
1800
+				return $this->hashPart("&#" . ord($token[1]) . ";");
1801 1801
 			case "`":
1802 1802
 				// Search for end marker in remaining text.
1803
-				if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm',
1803
+				if (preg_match('/^(.*?[^`])' . preg_quote($token) . '(?!`)(.*)$/sm',
1804 1804
 					$str, $matches))
1805 1805
 				{
1806 1806
 					$str = $matches[2];
@@ -1864,7 +1864,7 @@  discard block
 block discarded – undo
1864 1864
 		foreach ($blocks as $block) {
1865 1865
 			// Calculate amount of space, insert spaces, insert block.
1866 1866
 			$amount = $this->tab_width -
1867
-				$strlen($line, 'UTF-8') % $this->tab_width;
1867
+				$strlen($line, 'UTF-8')%$this->tab_width;
1868 1868
 			$line .= str_repeat(" ", $amount) . $block;
1869 1869
 		}
1870 1870
 		return $line;
Please login to merge, or discard this patch.
Braces   +3 added lines, -2 removed lines patch added patch discarded remove patch
@@ -775,8 +775,9 @@
 block discarded – undo
775 775
 		// tag parser and hashed. Need to reverse the process before using
776 776
 		// the URL.
777 777
 		$unhashed = $this->unhash($url);
778
-		if ($unhashed !== $url)
779
-			$url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
778
+		if ($unhashed !== $url) {
779
+					$url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
780
+		}
780 781
 
781 782
 		$url = $this->encodeURLAttribute($url);
782 783
 
Please login to merge, or discard this patch.
a/vendor/michelf/php-markdown/Michelf/MarkdownExtra.php 3 patches
Indentation   +1535 added lines, -1535 removed lines patch added patch discarded remove patch
@@ -14,287 +14,287 @@  discard block
 block discarded – undo
14 14
  * Markdown Extra Parser Class
15 15
  */
16 16
 class MarkdownExtra extends \Michelf\Markdown {
17
-	/**
18
-	 * Configuration variables
19
-	 */
20
-
21
-	/**
22
-	 * Prefix for footnote ids.
23
-	 * @var string
24
-	 */
25
-	public $fn_id_prefix = "";
26
-
27
-	/**
28
-	 * Optional title attribute for footnote links.
29
-	 * @var string
30
-	 */
31
-	public $fn_link_title = "";
32
-
33
-	/**
34
-	 * Optional class attribute for footnote links and backlinks.
35
-	 * @var string
36
-	 */
37
-	public $fn_link_class     = "footnote-ref";
38
-	public $fn_backlink_class = "footnote-backref";
39
-
40
-	/**
41
-	 * Content to be displayed within footnote backlinks. The default is '↩';
42
-	 * the U+FE0E on the end is a Unicode variant selector used to prevent iOS
43
-	 * from displaying the arrow character as an emoji.
44
-	 * Optionally use '^^' and '%%' to refer to the footnote number and
45
-	 * reference number respectively. {@see parseFootnotePlaceholders()}
46
-	 * @var string
47
-	 */
48
-	public $fn_backlink_html = '&#8617;&#xFE0E;';
49
-
50
-	/**
51
-	 * Optional title and aria-label attributes for footnote backlinks for
52
-	 * added accessibility (to ensure backlink uniqueness).
53
-	 * Use '^^' and '%%' to refer to the footnote number and reference number
54
-	 * respectively. {@see parseFootnotePlaceholders()}
55
-	 * @var string
56
-	 */
57
-	public $fn_backlink_title = "";
58
-	public $fn_backlink_label = "";
59
-
60
-	/**
61
-	 * Class name for table cell alignment (%% replaced left/center/right)
62
-	 * For instance: 'go-%%' becomes 'go-left' or 'go-right' or 'go-center'
63
-	 * If empty, the align attribute is used instead of a class name.
64
-	 * @var string
65
-	 */
66
-	public $table_align_class_tmpl = '';
67
-
68
-	/**
69
-	 * Optional class prefix for fenced code block.
70
-	 * @var string
71
-	 */
72
-	public $code_class_prefix = "";
73
-
74
-	/**
75
-	 * Class attribute for code blocks goes on the `code` tag;
76
-	 * setting this to true will put attributes on the `pre` tag instead.
77
-	 * @var boolean
78
-	 */
79
-	public $code_attr_on_pre = false;
80
-
81
-	/**
82
-	 * Predefined abbreviations.
83
-	 * @var array
84
-	 */
85
-	public $predef_abbr = array();
86
-
87
-	/**
88
-	 * Only convert atx-style headers if there's a space between the header and #
89
-	 * @var boolean
90
-	 */
91
-	public $hashtag_protection = false;
92
-
93
-	/**
94
-	 * Determines whether footnotes should be appended to the end of the document.
95
-	 * If true, footnote html can be retrieved from $this->footnotes_assembled.
96
-	 * @var boolean
97
-	 */
98
-	public $omit_footnotes = false;
99
-
100
-
101
-	/**
102
-	 * After parsing, the HTML for the list of footnotes appears here.
103
-	 * This is available only if $omit_footnotes == true.
104
-	 *
105
-	 * Note: when placing the content of `footnotes_assembled` on the page,
106
-	 * consider adding the attribute `role="doc-endnotes"` to the `div` or
107
-	 * `section` that will enclose the list of footnotes so they are
108
-	 * reachable to accessibility tools the same way they would be with the
109
-	 * default HTML output.
110
-	 * @var null|string
111
-	 */
112
-	public $footnotes_assembled = null;
113
-
114
-	/**
115
-	 * Parser implementation
116
-	 */
117
-
118
-	/**
119
-	 * Constructor function. Initialize the parser object.
120
-	 * @return void
121
-	 */
122
-	public function __construct() {
123
-		// Add extra escapable characters before parent constructor
124
-		// initialize the table.
125
-		$this->escape_chars .= ':|';
126
-
127
-		// Insert extra document, block, and span transformations.
128
-		// Parent constructor will do the sorting.
129
-		$this->document_gamut += array(
130
-			"doFencedCodeBlocks" => 5,
131
-			"stripFootnotes"     => 15,
132
-			"stripAbbreviations" => 25,
133
-			"appendFootnotes"    => 50,
134
-		);
135
-		$this->block_gamut += array(
136
-			"doFencedCodeBlocks" => 5,
137
-			"doTables"           => 15,
138
-			"doDefLists"         => 45,
139
-		);
140
-		$this->span_gamut += array(
141
-			"doFootnotes"        => 5,
142
-			"doAbbreviations"    => 70,
143
-		);
144
-
145
-		$this->enhanced_ordered_list = true;
146
-		parent::__construct();
147
-	}
148
-
149
-
150
-	/**
151
-	 * Extra variables used during extra transformations.
152
-	 * @var array
153
-	 */
154
-	protected $footnotes = array();
155
-	protected $footnotes_ordered = array();
156
-	protected $footnotes_ref_count = array();
157
-	protected $footnotes_numbers = array();
158
-	protected $abbr_desciptions = array();
159
-	/** @var string */
160
-	protected $abbr_word_re = '';
161
-
162
-	/**
163
-	 * Give the current footnote number.
164
-	 * @var integer
165
-	 */
166
-	protected $footnote_counter = 1;
17
+    /**
18
+     * Configuration variables
19
+     */
20
+
21
+    /**
22
+     * Prefix for footnote ids.
23
+     * @var string
24
+     */
25
+    public $fn_id_prefix = "";
26
+
27
+    /**
28
+     * Optional title attribute for footnote links.
29
+     * @var string
30
+     */
31
+    public $fn_link_title = "";
32
+
33
+    /**
34
+     * Optional class attribute for footnote links and backlinks.
35
+     * @var string
36
+     */
37
+    public $fn_link_class     = "footnote-ref";
38
+    public $fn_backlink_class = "footnote-backref";
39
+
40
+    /**
41
+     * Content to be displayed within footnote backlinks. The default is '↩';
42
+     * the U+FE0E on the end is a Unicode variant selector used to prevent iOS
43
+     * from displaying the arrow character as an emoji.
44
+     * Optionally use '^^' and '%%' to refer to the footnote number and
45
+     * reference number respectively. {@see parseFootnotePlaceholders()}
46
+     * @var string
47
+     */
48
+    public $fn_backlink_html = '&#8617;&#xFE0E;';
49
+
50
+    /**
51
+     * Optional title and aria-label attributes for footnote backlinks for
52
+     * added accessibility (to ensure backlink uniqueness).
53
+     * Use '^^' and '%%' to refer to the footnote number and reference number
54
+     * respectively. {@see parseFootnotePlaceholders()}
55
+     * @var string
56
+     */
57
+    public $fn_backlink_title = "";
58
+    public $fn_backlink_label = "";
59
+
60
+    /**
61
+     * Class name for table cell alignment (%% replaced left/center/right)
62
+     * For instance: 'go-%%' becomes 'go-left' or 'go-right' or 'go-center'
63
+     * If empty, the align attribute is used instead of a class name.
64
+     * @var string
65
+     */
66
+    public $table_align_class_tmpl = '';
67
+
68
+    /**
69
+     * Optional class prefix for fenced code block.
70
+     * @var string
71
+     */
72
+    public $code_class_prefix = "";
73
+
74
+    /**
75
+     * Class attribute for code blocks goes on the `code` tag;
76
+     * setting this to true will put attributes on the `pre` tag instead.
77
+     * @var boolean
78
+     */
79
+    public $code_attr_on_pre = false;
80
+
81
+    /**
82
+     * Predefined abbreviations.
83
+     * @var array
84
+     */
85
+    public $predef_abbr = array();
86
+
87
+    /**
88
+     * Only convert atx-style headers if there's a space between the header and #
89
+     * @var boolean
90
+     */
91
+    public $hashtag_protection = false;
92
+
93
+    /**
94
+     * Determines whether footnotes should be appended to the end of the document.
95
+     * If true, footnote html can be retrieved from $this->footnotes_assembled.
96
+     * @var boolean
97
+     */
98
+    public $omit_footnotes = false;
99
+
100
+
101
+    /**
102
+     * After parsing, the HTML for the list of footnotes appears here.
103
+     * This is available only if $omit_footnotes == true.
104
+     *
105
+     * Note: when placing the content of `footnotes_assembled` on the page,
106
+     * consider adding the attribute `role="doc-endnotes"` to the `div` or
107
+     * `section` that will enclose the list of footnotes so they are
108
+     * reachable to accessibility tools the same way they would be with the
109
+     * default HTML output.
110
+     * @var null|string
111
+     */
112
+    public $footnotes_assembled = null;
113
+
114
+    /**
115
+     * Parser implementation
116
+     */
117
+
118
+    /**
119
+     * Constructor function. Initialize the parser object.
120
+     * @return void
121
+     */
122
+    public function __construct() {
123
+        // Add extra escapable characters before parent constructor
124
+        // initialize the table.
125
+        $this->escape_chars .= ':|';
126
+
127
+        // Insert extra document, block, and span transformations.
128
+        // Parent constructor will do the sorting.
129
+        $this->document_gamut += array(
130
+            "doFencedCodeBlocks" => 5,
131
+            "stripFootnotes"     => 15,
132
+            "stripAbbreviations" => 25,
133
+            "appendFootnotes"    => 50,
134
+        );
135
+        $this->block_gamut += array(
136
+            "doFencedCodeBlocks" => 5,
137
+            "doTables"           => 15,
138
+            "doDefLists"         => 45,
139
+        );
140
+        $this->span_gamut += array(
141
+            "doFootnotes"        => 5,
142
+            "doAbbreviations"    => 70,
143
+        );
144
+
145
+        $this->enhanced_ordered_list = true;
146
+        parent::__construct();
147
+    }
148
+
149
+
150
+    /**
151
+     * Extra variables used during extra transformations.
152
+     * @var array
153
+     */
154
+    protected $footnotes = array();
155
+    protected $footnotes_ordered = array();
156
+    protected $footnotes_ref_count = array();
157
+    protected $footnotes_numbers = array();
158
+    protected $abbr_desciptions = array();
159
+    /** @var string */
160
+    protected $abbr_word_re = '';
161
+
162
+    /**
163
+     * Give the current footnote number.
164
+     * @var integer
165
+     */
166
+    protected $footnote_counter = 1;
167 167
 
168 168
     /**
169 169
      * Ref attribute for links
170 170
      * @var array
171 171
      */
172
-	protected $ref_attr = array();
173
-
174
-	/**
175
-	 * Setting up Extra-specific variables.
176
-	 */
177
-	protected function setup() {
178
-		parent::setup();
179
-
180
-		$this->footnotes = array();
181
-		$this->footnotes_ordered = array();
182
-		$this->footnotes_ref_count = array();
183
-		$this->footnotes_numbers = array();
184
-		$this->abbr_desciptions = array();
185
-		$this->abbr_word_re = '';
186
-		$this->footnote_counter = 1;
187
-		$this->footnotes_assembled = null;
188
-
189
-		foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
190
-			if ($this->abbr_word_re)
191
-				$this->abbr_word_re .= '|';
192
-			$this->abbr_word_re .= preg_quote($abbr_word);
193
-			$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
194
-		}
195
-	}
196
-
197
-	/**
198
-	 * Clearing Extra-specific variables.
199
-	 */
200
-	protected function teardown() {
201
-		$this->footnotes = array();
202
-		$this->footnotes_ordered = array();
203
-		$this->footnotes_ref_count = array();
204
-		$this->footnotes_numbers = array();
205
-		$this->abbr_desciptions = array();
206
-		$this->abbr_word_re = '';
207
-
208
-		if ( ! $this->omit_footnotes )
209
-			$this->footnotes_assembled = null;
210
-
211
-		parent::teardown();
212
-	}
213
-
214
-
215
-	/**
216
-	 * Extra attribute parser
217
-	 */
218
-
219
-	/**
220
-	 * Expression to use to catch attributes (includes the braces)
221
-	 * @var string
222
-	 */
223
-	protected $id_class_attr_catch_re = '\{((?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,})[ ]*\}';
224
-
225
-	/**
226
-	 * Expression to use when parsing in a context when no capture is desired
227
-	 * @var string
228
-	 */
229
-	protected $id_class_attr_nocatch_re = '\{(?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}';
230
-
231
-	/**
232
-	 * Parse attributes caught by the $this->id_class_attr_catch_re expression
233
-	 * and return the HTML-formatted list of attributes.
234
-	 *
235
-	 * Currently supported attributes are .class and #id.
236
-	 *
237
-	 * In addition, this method also supports supplying a default Id value,
238
-	 * which will be used to populate the id attribute in case it was not
239
-	 * overridden.
240
-	 * @param  string $tag_name
241
-	 * @param  string $attr
242
-	 * @param  mixed  $defaultIdValue
243
-	 * @param  array  $classes
244
-	 * @return string
245
-	 */
246
-	protected function doExtraAttributes($tag_name, $attr, $defaultIdValue = null, $classes = array()) {
247
-		if (empty($attr) && !$defaultIdValue && empty($classes)) {
248
-			return "";
249
-		}
250
-
251
-		// Split on components
252
-		preg_match_all('/[#.a-z][-_:a-zA-Z0-9=]+/', $attr, $matches);
253
-		$elements = $matches[0];
254
-
255
-		// Handle classes and IDs (only first ID taken into account)
256
-		$attributes = array();
257
-		$id = false;
258
-		foreach ($elements as $element) {
259
-			if ($element[0] === '.') {
260
-				$classes[] = substr($element, 1);
261
-			} else if ($element[0] === '#') {
262
-				if ($id === false) $id = substr($element, 1);
263
-			} else if (strpos($element, '=') > 0) {
264
-				$parts = explode('=', $element, 2);
265
-				$attributes[] = $parts[0] . '="' . $parts[1] . '"';
266
-			}
267
-		}
268
-
269
-		if ($id === false || $id === '') {
270
-			$id = $defaultIdValue;
271
-		}
272
-
273
-		// Compose attributes as string
274
-		$attr_str = "";
275
-		if (!empty($id)) {
276
-			$attr_str .= ' id="'.$this->encodeAttribute($id) .'"';
277
-		}
278
-		if (!empty($classes)) {
279
-			$attr_str .= ' class="'. implode(" ", $classes) . '"';
280
-		}
281
-		if (!$this->no_markup && !empty($attributes)) {
282
-			$attr_str .= ' '.implode(" ", $attributes);
283
-		}
284
-		return $attr_str;
285
-	}
286
-
287
-	/**
288
-	 * Strips link definitions from text, stores the URLs and titles in
289
-	 * hash references.
290
-	 * @param  string $text
291
-	 * @return string
292
-	 */
293
-	protected function stripLinkDefinitions($text) {
294
-		$less_than_tab = $this->tab_width - 1;
295
-
296
-		// Link defs are in the form: ^[id]: url "optional title"
297
-		$text = preg_replace_callback('{
172
+    protected $ref_attr = array();
173
+
174
+    /**
175
+     * Setting up Extra-specific variables.
176
+     */
177
+    protected function setup() {
178
+        parent::setup();
179
+
180
+        $this->footnotes = array();
181
+        $this->footnotes_ordered = array();
182
+        $this->footnotes_ref_count = array();
183
+        $this->footnotes_numbers = array();
184
+        $this->abbr_desciptions = array();
185
+        $this->abbr_word_re = '';
186
+        $this->footnote_counter = 1;
187
+        $this->footnotes_assembled = null;
188
+
189
+        foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
190
+            if ($this->abbr_word_re)
191
+                $this->abbr_word_re .= '|';
192
+            $this->abbr_word_re .= preg_quote($abbr_word);
193
+            $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
194
+        }
195
+    }
196
+
197
+    /**
198
+     * Clearing Extra-specific variables.
199
+     */
200
+    protected function teardown() {
201
+        $this->footnotes = array();
202
+        $this->footnotes_ordered = array();
203
+        $this->footnotes_ref_count = array();
204
+        $this->footnotes_numbers = array();
205
+        $this->abbr_desciptions = array();
206
+        $this->abbr_word_re = '';
207
+
208
+        if ( ! $this->omit_footnotes )
209
+            $this->footnotes_assembled = null;
210
+
211
+        parent::teardown();
212
+    }
213
+
214
+
215
+    /**
216
+     * Extra attribute parser
217
+     */
218
+
219
+    /**
220
+     * Expression to use to catch attributes (includes the braces)
221
+     * @var string
222
+     */
223
+    protected $id_class_attr_catch_re = '\{((?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,})[ ]*\}';
224
+
225
+    /**
226
+     * Expression to use when parsing in a context when no capture is desired
227
+     * @var string
228
+     */
229
+    protected $id_class_attr_nocatch_re = '\{(?>[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}';
230
+
231
+    /**
232
+     * Parse attributes caught by the $this->id_class_attr_catch_re expression
233
+     * and return the HTML-formatted list of attributes.
234
+     *
235
+     * Currently supported attributes are .class and #id.
236
+     *
237
+     * In addition, this method also supports supplying a default Id value,
238
+     * which will be used to populate the id attribute in case it was not
239
+     * overridden.
240
+     * @param  string $tag_name
241
+     * @param  string $attr
242
+     * @param  mixed  $defaultIdValue
243
+     * @param  array  $classes
244
+     * @return string
245
+     */
246
+    protected function doExtraAttributes($tag_name, $attr, $defaultIdValue = null, $classes = array()) {
247
+        if (empty($attr) && !$defaultIdValue && empty($classes)) {
248
+            return "";
249
+        }
250
+
251
+        // Split on components
252
+        preg_match_all('/[#.a-z][-_:a-zA-Z0-9=]+/', $attr, $matches);
253
+        $elements = $matches[0];
254
+
255
+        // Handle classes and IDs (only first ID taken into account)
256
+        $attributes = array();
257
+        $id = false;
258
+        foreach ($elements as $element) {
259
+            if ($element[0] === '.') {
260
+                $classes[] = substr($element, 1);
261
+            } else if ($element[0] === '#') {
262
+                if ($id === false) $id = substr($element, 1);
263
+            } else if (strpos($element, '=') > 0) {
264
+                $parts = explode('=', $element, 2);
265
+                $attributes[] = $parts[0] . '="' . $parts[1] . '"';
266
+            }
267
+        }
268
+
269
+        if ($id === false || $id === '') {
270
+            $id = $defaultIdValue;
271
+        }
272
+
273
+        // Compose attributes as string
274
+        $attr_str = "";
275
+        if (!empty($id)) {
276
+            $attr_str .= ' id="'.$this->encodeAttribute($id) .'"';
277
+        }
278
+        if (!empty($classes)) {
279
+            $attr_str .= ' class="'. implode(" ", $classes) . '"';
280
+        }
281
+        if (!$this->no_markup && !empty($attributes)) {
282
+            $attr_str .= ' '.implode(" ", $attributes);
283
+        }
284
+        return $attr_str;
285
+    }
286
+
287
+    /**
288
+     * Strips link definitions from text, stores the URLs and titles in
289
+     * hash references.
290
+     * @param  string $text
291
+     * @return string
292
+     */
293
+    protected function stripLinkDefinitions($text) {
294
+        $less_than_tab = $this->tab_width - 1;
295
+
296
+        // Link defs are in the form: ^[id]: url "optional title"
297
+        $text = preg_replace_callback('{
298 298
 							^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?:	# id = $1
299 299
 							  [ ]*
300 300
 							  \n?				# maybe *one* newline
@@ -317,138 +317,138 @@  discard block
 block discarded – undo
317 317
 					(?:[ ]* '.$this->id_class_attr_catch_re.' )?  # $5 = extra id & class attr
318 318
 							(?:\n+|\Z)
319 319
 			}xm',
320
-			array($this, '_stripLinkDefinitions_callback'),
321
-			$text);
322
-		return $text;
323
-	}
324
-
325
-	/**
326
-	 * Strip link definition callback
327
-	 * @param  array $matches
328
-	 * @return string
329
-	 */
330
-	protected function _stripLinkDefinitions_callback($matches) {
331
-		$link_id = strtolower($matches[1]);
332
-		$url = $matches[2] == '' ? $matches[3] : $matches[2];
333
-		$this->urls[$link_id] = $url;
334
-		$this->titles[$link_id] =& $matches[4];
335
-		$this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]);
336
-		return ''; // String that will replace the block
337
-	}
338
-
339
-
340
-	/**
341
-	 * HTML block parser
342
-	 */
343
-
344
-	/**
345
-	 * Tags that are always treated as block tags
346
-	 * @var string
347
-	 */
348
-	protected $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption|figure';
349
-
350
-	/**
351
-	 * Tags treated as block tags only if the opening tag is alone on its line
352
-	 * @var string
353
-	 */
354
-	protected $context_block_tags_re = 'script|noscript|style|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video';
355
-
356
-	/**
357
-	 * Tags where markdown="1" default to span mode:
358
-	 * @var string
359
-	 */
360
-	protected $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
361
-
362
-	/**
363
-	 * Tags which must not have their contents modified, no matter where
364
-	 * they appear
365
-	 * @var string
366
-	 */
367
-	protected $clean_tags_re = 'script|style|math|svg';
368
-
369
-	/**
370
-	 * Tags that do not need to be closed.
371
-	 * @var string
372
-	 */
373
-	protected $auto_close_tags_re = 'hr|img|param|source|track';
374
-
375
-	/**
376
-	 * Hashify HTML Blocks and "clean tags".
377
-	 *
378
-	 * We only want to do this for block-level HTML tags, such as headers,
379
-	 * lists, and tables. That's because we still want to wrap <p>s around
380
-	 * "paragraphs" that are wrapped in non-block-level tags, such as anchors,
381
-	 * phrase emphasis, and spans. The list of tags we're looking for is
382
-	 * hard-coded.
383
-	 *
384
-	 * This works by calling _HashHTMLBlocks_InMarkdown, which then calls
385
-	 * _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1"
386
-	 * attribute is found within a tag, _HashHTMLBlocks_InHTML calls back
387
-	 *  _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
388
-	 * These two functions are calling each other. It's recursive!
389
-	 * @param  string $text
390
-	 * @return string
391
-	 */
392
-	protected function hashHTMLBlocks($text) {
393
-		if ($this->no_markup) {
394
-			return $text;
395
-		}
396
-
397
-		// Call the HTML-in-Markdown hasher.
398
-		list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
399
-
400
-		return $text;
401
-	}
402
-
403
-	/**
404
-	 * Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
405
-	 *
406
-	 * *   $indent is the number of space to be ignored when checking for code
407
-	 *     blocks. This is important because if we don't take the indent into
408
-	 *     account, something like this (which looks right) won't work as expected:
409
-	 *
410
-	 *     <div>
411
-	 *         <div markdown="1">
412
-	 *         Hello World.  <-- Is this a Markdown code block or text?
413
-	 *         </div>  <-- Is this a Markdown code block or a real tag?
414
-	 *     <div>
415
-	 *
416
-	 *     If you don't like this, just don't indent the tag on which
417
-	 *     you apply the markdown="1" attribute.
418
-	 *
419
-	 * *   If $enclosing_tag_re is not empty, stops at the first unmatched closing
420
-	 *     tag with that name. Nested tags supported.
421
-	 *
422
-	 * *   If $span is true, text inside must treated as span. So any double
423
-	 *     newline will be replaced by a single newline so that it does not create
424
-	 *     paragraphs.
425
-	 *
426
-	 * Returns an array of that form: ( processed text , remaining text )
427
-	 *
428
-	 * @param  string  $text
429
-	 * @param  integer $indent
430
-	 * @param  string  $enclosing_tag_re
431
-	 * @param  boolean $span
432
-	 * @return array
433
-	 */
434
-	protected function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
435
-										$enclosing_tag_re = '', $span = false)
436
-	{
437
-
438
-		if ($text === '') return array('', '');
439
-
440
-		// Regex to check for the presense of newlines around a block tag.
441
-		$newline_before_re = '/(?:^\n?|\n\n)*$/';
442
-		$newline_after_re =
443
-			'{
320
+            array($this, '_stripLinkDefinitions_callback'),
321
+            $text);
322
+        return $text;
323
+    }
324
+
325
+    /**
326
+     * Strip link definition callback
327
+     * @param  array $matches
328
+     * @return string
329
+     */
330
+    protected function _stripLinkDefinitions_callback($matches) {
331
+        $link_id = strtolower($matches[1]);
332
+        $url = $matches[2] == '' ? $matches[3] : $matches[2];
333
+        $this->urls[$link_id] = $url;
334
+        $this->titles[$link_id] =& $matches[4];
335
+        $this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]);
336
+        return ''; // String that will replace the block
337
+    }
338
+
339
+
340
+    /**
341
+     * HTML block parser
342
+     */
343
+
344
+    /**
345
+     * Tags that are always treated as block tags
346
+     * @var string
347
+     */
348
+    protected $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption|figure';
349
+
350
+    /**
351
+     * Tags treated as block tags only if the opening tag is alone on its line
352
+     * @var string
353
+     */
354
+    protected $context_block_tags_re = 'script|noscript|style|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video';
355
+
356
+    /**
357
+     * Tags where markdown="1" default to span mode:
358
+     * @var string
359
+     */
360
+    protected $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
361
+
362
+    /**
363
+     * Tags which must not have their contents modified, no matter where
364
+     * they appear
365
+     * @var string
366
+     */
367
+    protected $clean_tags_re = 'script|style|math|svg';
368
+
369
+    /**
370
+     * Tags that do not need to be closed.
371
+     * @var string
372
+     */
373
+    protected $auto_close_tags_re = 'hr|img|param|source|track';
374
+
375
+    /**
376
+     * Hashify HTML Blocks and "clean tags".
377
+     *
378
+     * We only want to do this for block-level HTML tags, such as headers,
379
+     * lists, and tables. That's because we still want to wrap <p>s around
380
+     * "paragraphs" that are wrapped in non-block-level tags, such as anchors,
381
+     * phrase emphasis, and spans. The list of tags we're looking for is
382
+     * hard-coded.
383
+     *
384
+     * This works by calling _HashHTMLBlocks_InMarkdown, which then calls
385
+     * _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1"
386
+     * attribute is found within a tag, _HashHTMLBlocks_InHTML calls back
387
+     *  _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
388
+     * These two functions are calling each other. It's recursive!
389
+     * @param  string $text
390
+     * @return string
391
+     */
392
+    protected function hashHTMLBlocks($text) {
393
+        if ($this->no_markup) {
394
+            return $text;
395
+        }
396
+
397
+        // Call the HTML-in-Markdown hasher.
398
+        list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
399
+
400
+        return $text;
401
+    }
402
+
403
+    /**
404
+     * Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
405
+     *
406
+     * *   $indent is the number of space to be ignored when checking for code
407
+     *     blocks. This is important because if we don't take the indent into
408
+     *     account, something like this (which looks right) won't work as expected:
409
+     *
410
+     *     <div>
411
+     *         <div markdown="1">
412
+     *         Hello World.  <-- Is this a Markdown code block or text?
413
+     *         </div>  <-- Is this a Markdown code block or a real tag?
414
+     *     <div>
415
+     *
416
+     *     If you don't like this, just don't indent the tag on which
417
+     *     you apply the markdown="1" attribute.
418
+     *
419
+     * *   If $enclosing_tag_re is not empty, stops at the first unmatched closing
420
+     *     tag with that name. Nested tags supported.
421
+     *
422
+     * *   If $span is true, text inside must treated as span. So any double
423
+     *     newline will be replaced by a single newline so that it does not create
424
+     *     paragraphs.
425
+     *
426
+     * Returns an array of that form: ( processed text , remaining text )
427
+     *
428
+     * @param  string  $text
429
+     * @param  integer $indent
430
+     * @param  string  $enclosing_tag_re
431
+     * @param  boolean $span
432
+     * @return array
433
+     */
434
+    protected function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
435
+                                        $enclosing_tag_re = '', $span = false)
436
+    {
437
+
438
+        if ($text === '') return array('', '');
439
+
440
+        // Regex to check for the presense of newlines around a block tag.
441
+        $newline_before_re = '/(?:^\n?|\n\n)*$/';
442
+        $newline_after_re =
443
+            '{
444 444
 				^						# Start of text following the tag.
445 445
 				(?>[ ]*<!--.*?-->)?		# Optional comment.
446 446
 				[ ]*\n					# Must be followed by newline.
447 447
 			}xs';
448 448
 
449
-		// Regex to match any tag.
450
-		$block_tag_re =
451
-			'{
449
+        // Regex to match any tag.
450
+        $block_tag_re =
451
+            '{
452 452
 				(					# $2: Capture whole tag.
453 453
 					</?					# Any opening or closing tag.
454 454
 						(?>				# Tag name.
@@ -501,156 +501,156 @@  discard block
 block discarded – undo
501 501
 			}xs';
502 502
 
503 503
 
504
-		$depth = 0;		// Current depth inside the tag tree.
505
-		$parsed = "";	// Parsed text that will be returned.
506
-
507
-		// Loop through every tag until we find the closing tag of the parent
508
-		// or loop until reaching the end of text if no parent tag specified.
509
-		do {
510
-			// Split the text using the first $tag_match pattern found.
511
-			// Text before  pattern will be first in the array, text after
512
-			// pattern will be at the end, and between will be any catches made
513
-			// by the pattern.
514
-			$parts = preg_split($block_tag_re, $text, 2,
515
-								PREG_SPLIT_DELIM_CAPTURE);
516
-
517
-			// If in Markdown span mode, add a empty-string span-level hash
518
-			// after each newline to prevent triggering any block element.
519
-			if ($span) {
520
-				$void = $this->hashPart("", ':');
521
-				$newline = "\n$void";
522
-				$parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
523
-			}
524
-
525
-			$parsed .= $parts[0]; // Text before current tag.
526
-
527
-			// If end of $text has been reached. Stop loop.
528
-			if (count($parts) < 3) {
529
-				$text = "";
530
-				break;
531
-			}
532
-
533
-			$tag  = $parts[1]; // Tag to handle.
534
-			$text = $parts[2]; // Remaining text after current tag.
535
-
536
-			// Check for: Fenced code block marker.
537
-			// Note: need to recheck the whole tag to disambiguate backtick
538
-			// fences from code spans
539
-			if (preg_match('{^\n?([ ]{0,' . ($indent + 3) . '})(~{3,}|`{3,})[ ]*(?:\.?[-_:a-zA-Z0-9]+)?[ ]*(?:' . $this->id_class_attr_nocatch_re . ')?[ ]*\n?$}', $tag, $capture)) {
540
-				// Fenced code block marker: find matching end marker.
541
-				$fence_indent = strlen($capture[1]); // use captured indent in re
542
-				$fence_re = $capture[2]; // use captured fence in re
543
-				if (preg_match('{^(?>.*\n)*?[ ]{' . ($fence_indent) . '}' . $fence_re . '[ ]*(?:\n|$)}', $text,
544
-					$matches))
545
-				{
546
-					// End marker found: pass text unchanged until marker.
547
-					$parsed .= $tag . $matches[0];
548
-					$text = substr($text, strlen($matches[0]));
549
-				}
550
-				else {
551
-					// No end marker: just skip it.
552
-					$parsed .= $tag;
553
-				}
554
-			}
555
-			// Check for: Indented code block.
556
-			else if ($tag[0] === "\n" || $tag[0] === " ") {
557
-				// Indented code block: pass it unchanged, will be handled
558
-				// later.
559
-				$parsed .= $tag;
560
-			}
561
-			// Check for: Code span marker
562
-			// Note: need to check this after backtick fenced code blocks
563
-			else if ($tag[0] === "`") {
564
-				// Find corresponding end marker.
565
-				$tag_re = preg_quote($tag);
566
-				if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)' . $tag_re . '(?!`)}',
567
-					$text, $matches))
568
-				{
569
-					// End marker found: pass text unchanged until marker.
570
-					$parsed .= $tag . $matches[0];
571
-					$text = substr($text, strlen($matches[0]));
572
-				}
573
-				else {
574
-					// Unmatched marker: just skip it.
575
-					$parsed .= $tag;
576
-				}
577
-			}
578
-			// Check for: Opening Block level tag or
579
-			//            Opening Context Block tag (like ins and del)
580
-			//               used as a block tag (tag is alone on it's line).
581
-			else if (preg_match('{^<(?:' . $this->block_tags_re . ')\b}', $tag) ||
582
-				(	preg_match('{^<(?:' . $this->context_block_tags_re . ')\b}', $tag) &&
583
-					preg_match($newline_before_re, $parsed) &&
584
-					preg_match($newline_after_re, $text)	)
585
-				)
586
-			{
587
-				// Need to parse tag and following text using the HTML parser.
588
-				list($block_text, $text) =
589
-					$this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
590
-
591
-				// Make sure it stays outside of any paragraph by adding newlines.
592
-				$parsed .= "\n\n$block_text\n\n";
593
-			}
594
-			// Check for: Clean tag (like script, math)
595
-			//            HTML Comments, processing instructions.
596
-			else if (preg_match('{^<(?:' . $this->clean_tags_re . ')\b}', $tag) ||
597
-				$tag[1] === '!' || $tag[1] === '?')
598
-			{
599
-				// Need to parse tag and following text using the HTML parser.
600
-				// (don't check for markdown attribute)
601
-				list($block_text, $text) =
602
-					$this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
603
-
604
-				$parsed .= $block_text;
605
-			}
606
-			// Check for: Tag with same name as enclosing tag.
607
-			else if ($enclosing_tag_re !== '' &&
608
-				// Same name as enclosing tag.
609
-				preg_match('{^</?(?:' . $enclosing_tag_re . ')\b}', $tag))
610
-			{
611
-				// Increase/decrease nested tag count.
612
-				if ($tag[1] === '/') {
613
-					$depth--;
614
-				} else if ($tag[strlen($tag)-2] !== '/') {
615
-					$depth++;
616
-				}
617
-
618
-				if ($depth < 0) {
619
-					// Going out of parent element. Clean up and break so we
620
-					// return to the calling function.
621
-					$text = $tag . $text;
622
-					break;
623
-				}
624
-
625
-				$parsed .= $tag;
626
-			}
627
-			else {
628
-				$parsed .= $tag;
629
-			}
630
-		} while ($depth >= 0);
631
-
632
-		return array($parsed, $text);
633
-	}
634
-
635
-	/**
636
-	 * Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
637
-	 *
638
-	 * *   Calls $hash_method to convert any blocks.
639
-	 * *   Stops when the first opening tag closes.
640
-	 * *   $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
641
-	 *     (it is not inside clean tags)
642
-	 *
643
-	 * Returns an array of that form: ( processed text , remaining text )
644
-	 * @param  string $text
645
-	 * @param  string $hash_method
646
-	 * @param  bool $md_attr Handle `markdown="1"` attribute
647
-	 * @return array
648
-	 */
649
-	protected function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
650
-		if ($text === '') return array('', '');
651
-
652
-		// Regex to match `markdown` attribute inside of a tag.
653
-		$markdown_attr_re = '
504
+        $depth = 0;		// Current depth inside the tag tree.
505
+        $parsed = "";	// Parsed text that will be returned.
506
+
507
+        // Loop through every tag until we find the closing tag of the parent
508
+        // or loop until reaching the end of text if no parent tag specified.
509
+        do {
510
+            // Split the text using the first $tag_match pattern found.
511
+            // Text before  pattern will be first in the array, text after
512
+            // pattern will be at the end, and between will be any catches made
513
+            // by the pattern.
514
+            $parts = preg_split($block_tag_re, $text, 2,
515
+                                PREG_SPLIT_DELIM_CAPTURE);
516
+
517
+            // If in Markdown span mode, add a empty-string span-level hash
518
+            // after each newline to prevent triggering any block element.
519
+            if ($span) {
520
+                $void = $this->hashPart("", ':');
521
+                $newline = "\n$void";
522
+                $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
523
+            }
524
+
525
+            $parsed .= $parts[0]; // Text before current tag.
526
+
527
+            // If end of $text has been reached. Stop loop.
528
+            if (count($parts) < 3) {
529
+                $text = "";
530
+                break;
531
+            }
532
+
533
+            $tag  = $parts[1]; // Tag to handle.
534
+            $text = $parts[2]; // Remaining text after current tag.
535
+
536
+            // Check for: Fenced code block marker.
537
+            // Note: need to recheck the whole tag to disambiguate backtick
538
+            // fences from code spans
539
+            if (preg_match('{^\n?([ ]{0,' . ($indent + 3) . '})(~{3,}|`{3,})[ ]*(?:\.?[-_:a-zA-Z0-9]+)?[ ]*(?:' . $this->id_class_attr_nocatch_re . ')?[ ]*\n?$}', $tag, $capture)) {
540
+                // Fenced code block marker: find matching end marker.
541
+                $fence_indent = strlen($capture[1]); // use captured indent in re
542
+                $fence_re = $capture[2]; // use captured fence in re
543
+                if (preg_match('{^(?>.*\n)*?[ ]{' . ($fence_indent) . '}' . $fence_re . '[ ]*(?:\n|$)}', $text,
544
+                    $matches))
545
+                {
546
+                    // End marker found: pass text unchanged until marker.
547
+                    $parsed .= $tag . $matches[0];
548
+                    $text = substr($text, strlen($matches[0]));
549
+                }
550
+                else {
551
+                    // No end marker: just skip it.
552
+                    $parsed .= $tag;
553
+                }
554
+            }
555
+            // Check for: Indented code block.
556
+            else if ($tag[0] === "\n" || $tag[0] === " ") {
557
+                // Indented code block: pass it unchanged, will be handled
558
+                // later.
559
+                $parsed .= $tag;
560
+            }
561
+            // Check for: Code span marker
562
+            // Note: need to check this after backtick fenced code blocks
563
+            else if ($tag[0] === "`") {
564
+                // Find corresponding end marker.
565
+                $tag_re = preg_quote($tag);
566
+                if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)' . $tag_re . '(?!`)}',
567
+                    $text, $matches))
568
+                {
569
+                    // End marker found: pass text unchanged until marker.
570
+                    $parsed .= $tag . $matches[0];
571
+                    $text = substr($text, strlen($matches[0]));
572
+                }
573
+                else {
574
+                    // Unmatched marker: just skip it.
575
+                    $parsed .= $tag;
576
+                }
577
+            }
578
+            // Check for: Opening Block level tag or
579
+            //            Opening Context Block tag (like ins and del)
580
+            //               used as a block tag (tag is alone on it's line).
581
+            else if (preg_match('{^<(?:' . $this->block_tags_re . ')\b}', $tag) ||
582
+                (	preg_match('{^<(?:' . $this->context_block_tags_re . ')\b}', $tag) &&
583
+                    preg_match($newline_before_re, $parsed) &&
584
+                    preg_match($newline_after_re, $text)	)
585
+                )
586
+            {
587
+                // Need to parse tag and following text using the HTML parser.
588
+                list($block_text, $text) =
589
+                    $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
590
+
591
+                // Make sure it stays outside of any paragraph by adding newlines.
592
+                $parsed .= "\n\n$block_text\n\n";
593
+            }
594
+            // Check for: Clean tag (like script, math)
595
+            //            HTML Comments, processing instructions.
596
+            else if (preg_match('{^<(?:' . $this->clean_tags_re . ')\b}', $tag) ||
597
+                $tag[1] === '!' || $tag[1] === '?')
598
+            {
599
+                // Need to parse tag and following text using the HTML parser.
600
+                // (don't check for markdown attribute)
601
+                list($block_text, $text) =
602
+                    $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
603
+
604
+                $parsed .= $block_text;
605
+            }
606
+            // Check for: Tag with same name as enclosing tag.
607
+            else if ($enclosing_tag_re !== '' &&
608
+                // Same name as enclosing tag.
609
+                preg_match('{^</?(?:' . $enclosing_tag_re . ')\b}', $tag))
610
+            {
611
+                // Increase/decrease nested tag count.
612
+                if ($tag[1] === '/') {
613
+                    $depth--;
614
+                } else if ($tag[strlen($tag)-2] !== '/') {
615
+                    $depth++;
616
+                }
617
+
618
+                if ($depth < 0) {
619
+                    // Going out of parent element. Clean up and break so we
620
+                    // return to the calling function.
621
+                    $text = $tag . $text;
622
+                    break;
623
+                }
624
+
625
+                $parsed .= $tag;
626
+            }
627
+            else {
628
+                $parsed .= $tag;
629
+            }
630
+        } while ($depth >= 0);
631
+
632
+        return array($parsed, $text);
633
+    }
634
+
635
+    /**
636
+     * Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
637
+     *
638
+     * *   Calls $hash_method to convert any blocks.
639
+     * *   Stops when the first opening tag closes.
640
+     * *   $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
641
+     *     (it is not inside clean tags)
642
+     *
643
+     * Returns an array of that form: ( processed text , remaining text )
644
+     * @param  string $text
645
+     * @param  string $hash_method
646
+     * @param  bool $md_attr Handle `markdown="1"` attribute
647
+     * @return array
648
+     */
649
+    protected function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
650
+        if ($text === '') return array('', '');
651
+
652
+        // Regex to match `markdown` attribute inside of a tag.
653
+        $markdown_attr_re = '
654 654
 			{
655 655
 				\s*			# Eat whitespace before the `markdown` attribute
656 656
 				markdown
@@ -665,8 +665,8 @@  discard block
 block discarded – undo
665 665
 				()				# $4: make $3 always defined (avoid warnings)
666 666
 			}xs';
667 667
 
668
-		// Regex to match any tag.
669
-		$tag_re = '{
668
+        // Regex to match any tag.
669
+        $tag_re = '{
670 670
 				(					# $2: Capture whole tag.
671 671
 					</?					# Any opening or closing tag.
672 672
 						[\w:$]+			# Tag name.
@@ -688,143 +688,143 @@  discard block
 block discarded – undo
688 688
 				)
689 689
 			}xs';
690 690
 
691
-		$original_text = $text;		// Save original text in case of faliure.
692
-
693
-		$depth		= 0;	// Current depth inside the tag tree.
694
-		$block_text	= "";	// Temporary text holder for current text.
695
-		$parsed		= "";	// Parsed text that will be returned.
696
-		$base_tag_name_re = '';
697
-
698
-		// Get the name of the starting tag.
699
-		// (This pattern makes $base_tag_name_re safe without quoting.)
700
-		if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
701
-			$base_tag_name_re = $matches[1];
702
-
703
-		// Loop through every tag until we find the corresponding closing tag.
704
-		do {
705
-			// Split the text using the first $tag_match pattern found.
706
-			// Text before  pattern will be first in the array, text after
707
-			// pattern will be at the end, and between will be any catches made
708
-			// by the pattern.
709
-			$parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
710
-
711
-			if (count($parts) < 3) {
712
-				// End of $text reached with unbalenced tag(s).
713
-				// In that case, we return original text unchanged and pass the
714
-				// first character as filtered to prevent an infinite loop in the
715
-				// parent function.
716
-				return array($original_text[0], substr($original_text, 1));
717
-			}
718
-
719
-			$block_text .= $parts[0]; // Text before current tag.
720
-			$tag         = $parts[1]; // Tag to handle.
721
-			$text        = $parts[2]; // Remaining text after current tag.
722
-
723
-			// Check for: Auto-close tag (like <hr/>)
724
-			//			 Comments and Processing Instructions.
725
-			if (preg_match('{^</?(?:' . $this->auto_close_tags_re . ')\b}', $tag) ||
726
-				$tag[1] === '!' || $tag[1] === '?')
727
-			{
728
-				// Just add the tag to the block as if it was text.
729
-				$block_text .= $tag;
730
-			}
731
-			else {
732
-				// Increase/decrease nested tag count. Only do so if
733
-				// the tag's name match base tag's.
734
-				if (preg_match('{^</?' . $base_tag_name_re . '\b}', $tag)) {
735
-					if ($tag[1] === '/') {
736
-						$depth--;
737
-					} else if ($tag[strlen($tag)-2] !== '/') {
738
-						$depth++;
739
-					}
740
-				}
741
-
742
-				// Check for `markdown="1"` attribute and handle it.
743
-				if ($md_attr &&
744
-					preg_match($markdown_attr_re, $tag, $attr_m) &&
745
-					preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
746
-				{
747
-					// Remove `markdown` attribute from opening tag.
748
-					$tag = preg_replace($markdown_attr_re, '', $tag);
749
-
750
-					// Check if text inside this tag must be parsed in span mode.
751
-					$mode = $attr_m[2] . $attr_m[3];
752
-					$span_mode = $mode === 'span' || ($mode !== 'block' &&
753
-						preg_match('{^<(?:' . $this->contain_span_tags_re . ')\b}', $tag));
754
-
755
-					// Calculate indent before tag.
756
-					if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
757
-						$strlen = $this->utf8_strlen;
758
-						$indent = $strlen($matches[1], 'UTF-8');
759
-					} else {
760
-						$indent = 0;
761
-					}
762
-
763
-					// End preceding block with this tag.
764
-					$block_text .= $tag;
765
-					$parsed .= $this->$hash_method($block_text);
766
-
767
-					// Get enclosing tag name for the ParseMarkdown function.
768
-					// (This pattern makes $tag_name_re safe without quoting.)
769
-					preg_match('/^<([\w:$]*)\b/', $tag, $matches);
770
-					$tag_name_re = $matches[1];
771
-
772
-					// Parse the content using the HTML-in-Markdown parser.
773
-					list ($block_text, $text)
774
-						= $this->_hashHTMLBlocks_inMarkdown($text, $indent,
775
-							$tag_name_re, $span_mode);
776
-
777
-					// Outdent markdown text.
778
-					if ($indent > 0) {
779
-						$block_text = preg_replace("/^[ ]{1,$indent}/m", "",
780
-													$block_text);
781
-					}
782
-
783
-					// Append tag content to parsed text.
784
-					if (!$span_mode) {
785
-						$parsed .= "\n\n$block_text\n\n";
786
-					} else {
787
-						$parsed .= (string) $block_text;
788
-					}
789
-
790
-					// Start over with a new block.
791
-					$block_text = "";
792
-				}
793
-				else $block_text .= $tag;
794
-			}
795
-
796
-		} while ($depth > 0);
797
-
798
-		// Hash last block text that wasn't processed inside the loop.
799
-		$parsed .= $this->$hash_method($block_text);
800
-
801
-		return array($parsed, $text);
802
-	}
803
-
804
-	/**
805
-	 * Called whenever a tag must be hashed when a function inserts a "clean" tag
806
-	 * in $text, it passes through this function and is automaticaly escaped,
807
-	 * blocking invalid nested overlap.
808
-	 * @param  string $text
809
-	 * @return string
810
-	 */
811
-	protected function hashClean($text) {
812
-		return $this->hashPart($text, 'C');
813
-	}
814
-
815
-	/**
816
-	 * Turn Markdown link shortcuts into XHTML <a> tags.
817
-	 * @param  string $text
818
-	 * @return string
819
-	 */
820
-	protected function doAnchors($text) {
821
-		if ($this->in_anchor) {
822
-			return $text;
823
-		}
824
-		$this->in_anchor = true;
825
-
826
-		// First, handle reference-style links: [link text] [id]
827
-		$text = preg_replace_callback('{
691
+        $original_text = $text;		// Save original text in case of faliure.
692
+
693
+        $depth		= 0;	// Current depth inside the tag tree.
694
+        $block_text	= "";	// Temporary text holder for current text.
695
+        $parsed		= "";	// Parsed text that will be returned.
696
+        $base_tag_name_re = '';
697
+
698
+        // Get the name of the starting tag.
699
+        // (This pattern makes $base_tag_name_re safe without quoting.)
700
+        if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
701
+            $base_tag_name_re = $matches[1];
702
+
703
+        // Loop through every tag until we find the corresponding closing tag.
704
+        do {
705
+            // Split the text using the first $tag_match pattern found.
706
+            // Text before  pattern will be first in the array, text after
707
+            // pattern will be at the end, and between will be any catches made
708
+            // by the pattern.
709
+            $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
710
+
711
+            if (count($parts) < 3) {
712
+                // End of $text reached with unbalenced tag(s).
713
+                // In that case, we return original text unchanged and pass the
714
+                // first character as filtered to prevent an infinite loop in the
715
+                // parent function.
716
+                return array($original_text[0], substr($original_text, 1));
717
+            }
718
+
719
+            $block_text .= $parts[0]; // Text before current tag.
720
+            $tag         = $parts[1]; // Tag to handle.
721
+            $text        = $parts[2]; // Remaining text after current tag.
722
+
723
+            // Check for: Auto-close tag (like <hr/>)
724
+            //			 Comments and Processing Instructions.
725
+            if (preg_match('{^</?(?:' . $this->auto_close_tags_re . ')\b}', $tag) ||
726
+                $tag[1] === '!' || $tag[1] === '?')
727
+            {
728
+                // Just add the tag to the block as if it was text.
729
+                $block_text .= $tag;
730
+            }
731
+            else {
732
+                // Increase/decrease nested tag count. Only do so if
733
+                // the tag's name match base tag's.
734
+                if (preg_match('{^</?' . $base_tag_name_re . '\b}', $tag)) {
735
+                    if ($tag[1] === '/') {
736
+                        $depth--;
737
+                    } else if ($tag[strlen($tag)-2] !== '/') {
738
+                        $depth++;
739
+                    }
740
+                }
741
+
742
+                // Check for `markdown="1"` attribute and handle it.
743
+                if ($md_attr &&
744
+                    preg_match($markdown_attr_re, $tag, $attr_m) &&
745
+                    preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
746
+                {
747
+                    // Remove `markdown` attribute from opening tag.
748
+                    $tag = preg_replace($markdown_attr_re, '', $tag);
749
+
750
+                    // Check if text inside this tag must be parsed in span mode.
751
+                    $mode = $attr_m[2] . $attr_m[3];
752
+                    $span_mode = $mode === 'span' || ($mode !== 'block' &&
753
+                        preg_match('{^<(?:' . $this->contain_span_tags_re . ')\b}', $tag));
754
+
755
+                    // Calculate indent before tag.
756
+                    if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
757
+                        $strlen = $this->utf8_strlen;
758
+                        $indent = $strlen($matches[1], 'UTF-8');
759
+                    } else {
760
+                        $indent = 0;
761
+                    }
762
+
763
+                    // End preceding block with this tag.
764
+                    $block_text .= $tag;
765
+                    $parsed .= $this->$hash_method($block_text);
766
+
767
+                    // Get enclosing tag name for the ParseMarkdown function.
768
+                    // (This pattern makes $tag_name_re safe without quoting.)
769
+                    preg_match('/^<([\w:$]*)\b/', $tag, $matches);
770
+                    $tag_name_re = $matches[1];
771
+
772
+                    // Parse the content using the HTML-in-Markdown parser.
773
+                    list ($block_text, $text)
774
+                        = $this->_hashHTMLBlocks_inMarkdown($text, $indent,
775
+                            $tag_name_re, $span_mode);
776
+
777
+                    // Outdent markdown text.
778
+                    if ($indent > 0) {
779
+                        $block_text = preg_replace("/^[ ]{1,$indent}/m", "",
780
+                                                    $block_text);
781
+                    }
782
+
783
+                    // Append tag content to parsed text.
784
+                    if (!$span_mode) {
785
+                        $parsed .= "\n\n$block_text\n\n";
786
+                    } else {
787
+                        $parsed .= (string) $block_text;
788
+                    }
789
+
790
+                    // Start over with a new block.
791
+                    $block_text = "";
792
+                }
793
+                else $block_text .= $tag;
794
+            }
795
+
796
+        } while ($depth > 0);
797
+
798
+        // Hash last block text that wasn't processed inside the loop.
799
+        $parsed .= $this->$hash_method($block_text);
800
+
801
+        return array($parsed, $text);
802
+    }
803
+
804
+    /**
805
+     * Called whenever a tag must be hashed when a function inserts a "clean" tag
806
+     * in $text, it passes through this function and is automaticaly escaped,
807
+     * blocking invalid nested overlap.
808
+     * @param  string $text
809
+     * @return string
810
+     */
811
+    protected function hashClean($text) {
812
+        return $this->hashPart($text, 'C');
813
+    }
814
+
815
+    /**
816
+     * Turn Markdown link shortcuts into XHTML <a> tags.
817
+     * @param  string $text
818
+     * @return string
819
+     */
820
+    protected function doAnchors($text) {
821
+        if ($this->in_anchor) {
822
+            return $text;
823
+        }
824
+        $this->in_anchor = true;
825
+
826
+        // First, handle reference-style links: [link text] [id]
827
+        $text = preg_replace_callback('{
828 828
 			(					# wrap whole match in $1
829 829
 			  \[
830 830
 				(' . $this->nested_brackets_re . ')	# link text = $2
@@ -838,10 +838,10 @@  discard block
 block discarded – undo
838 838
 			  \]
839 839
 			)
840 840
 			}xs',
841
-			array($this, '_doAnchors_reference_callback'), $text);
841
+            array($this, '_doAnchors_reference_callback'), $text);
842 842
 
843
-		// Next, inline-style links: [link text](url "optional title")
844
-		$text = preg_replace_callback('{
843
+        // Next, inline-style links: [link text](url "optional title")
844
+        $text = preg_replace_callback('{
845 845
 			(				# wrap whole match in $1
846 846
 			  \[
847 847
 				(' . $this->nested_brackets_re . ')	# link text = $2
@@ -864,106 +864,106 @@  discard block
 block discarded – undo
864 864
 			  (?:[ ]? ' . $this->id_class_attr_catch_re . ' )?	 # $8 = id/class attributes
865 865
 			)
866 866
 			}xs',
867
-			array($this, '_doAnchors_inline_callback'), $text);
867
+            array($this, '_doAnchors_inline_callback'), $text);
868 868
 
869
-		// Last, handle reference-style shortcuts: [link text]
870
-		// These must come last in case you've also got [link text][1]
871
-		// or [link text](/foo)
872
-		$text = preg_replace_callback('{
869
+        // Last, handle reference-style shortcuts: [link text]
870
+        // These must come last in case you've also got [link text][1]
871
+        // or [link text](/foo)
872
+        $text = preg_replace_callback('{
873 873
 			(					# wrap whole match in $1
874 874
 			  \[
875 875
 				([^\[\]]+)		# link text = $2; can\'t contain [ or ]
876 876
 			  \]
877 877
 			)
878 878
 			}xs',
879
-			array($this, '_doAnchors_reference_callback'), $text);
880
-
881
-		$this->in_anchor = false;
882
-		return $text;
883
-	}
884
-
885
-	/**
886
-	 * Callback for reference anchors
887
-	 * @param  array $matches
888
-	 * @return string
889
-	 */
890
-	protected function _doAnchors_reference_callback($matches) {
891
-		$whole_match =  $matches[1];
892
-		$link_text   =  $matches[2];
893
-		$link_id     =& $matches[3];
894
-
895
-		if ($link_id == "") {
896
-			// for shortcut links like [this][] or [this].
897
-			$link_id = $link_text;
898
-		}
899
-
900
-		// lower-case and turn embedded newlines into spaces
901
-		$link_id = strtolower($link_id);
902
-		$link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
903
-
904
-		if (isset($this->urls[$link_id])) {
905
-			$url = $this->urls[$link_id];
906
-			$url = $this->encodeURLAttribute($url);
907
-
908
-			$result = "<a href=\"$url\"";
909
-			if ( isset( $this->titles[$link_id] ) ) {
910
-				$title = $this->titles[$link_id];
911
-				$title = $this->encodeAttribute($title);
912
-				$result .=  " title=\"$title\"";
913
-			}
914
-			if (isset($this->ref_attr[$link_id]))
915
-				$result .= $this->ref_attr[$link_id];
916
-
917
-			$link_text = $this->runSpanGamut($link_text);
918
-			$result .= ">$link_text</a>";
919
-			$result = $this->hashPart($result);
920
-		}
921
-		else {
922
-			$result = $whole_match;
923
-		}
924
-		return $result;
925
-	}
926
-
927
-	/**
928
-	 * Callback for inline anchors
929
-	 * @param  array $matches
930
-	 * @return string
931
-	 */
932
-	protected function _doAnchors_inline_callback($matches) {
933
-		$link_text		=  $this->runSpanGamut($matches[2]);
934
-		$url			=  $matches[3] === '' ? $matches[4] : $matches[3];
935
-		$title			=& $matches[7];
936
-		$attr  = $this->doExtraAttributes("a", $dummy =& $matches[8]);
937
-
938
-		// if the URL was of the form <s p a c e s> it got caught by the HTML
939
-		// tag parser and hashed. Need to reverse the process before using the URL.
940
-		$unhashed = $this->unhash($url);
941
-		if ($unhashed !== $url)
942
-			$url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
943
-
944
-		$url = $this->encodeURLAttribute($url);
945
-
946
-		$result = "<a href=\"$url\"";
947
-		if (isset($title)) {
948
-			$title = $this->encodeAttribute($title);
949
-			$result .=  " title=\"$title\"";
950
-		}
951
-		$result .= $attr;
952
-
953
-		$link_text = $this->runSpanGamut($link_text);
954
-		$result .= ">$link_text</a>";
955
-
956
-		return $this->hashPart($result);
957
-	}
958
-
959
-	/**
960
-	 * Turn Markdown image shortcuts into <img> tags.
961
-	 * @param  string $text
962
-	 * @return string
963
-	 */
964
-	protected function doImages($text) {
965
-		// First, handle reference-style labeled images: ![alt text][id]
966
-		$text = preg_replace_callback('{
879
+            array($this, '_doAnchors_reference_callback'), $text);
880
+
881
+        $this->in_anchor = false;
882
+        return $text;
883
+    }
884
+
885
+    /**
886
+     * Callback for reference anchors
887
+     * @param  array $matches
888
+     * @return string
889
+     */
890
+    protected function _doAnchors_reference_callback($matches) {
891
+        $whole_match =  $matches[1];
892
+        $link_text   =  $matches[2];
893
+        $link_id     =& $matches[3];
894
+
895
+        if ($link_id == "") {
896
+            // for shortcut links like [this][] or [this].
897
+            $link_id = $link_text;
898
+        }
899
+
900
+        // lower-case and turn embedded newlines into spaces
901
+        $link_id = strtolower($link_id);
902
+        $link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
903
+
904
+        if (isset($this->urls[$link_id])) {
905
+            $url = $this->urls[$link_id];
906
+            $url = $this->encodeURLAttribute($url);
907
+
908
+            $result = "<a href=\"$url\"";
909
+            if ( isset( $this->titles[$link_id] ) ) {
910
+                $title = $this->titles[$link_id];
911
+                $title = $this->encodeAttribute($title);
912
+                $result .=  " title=\"$title\"";
913
+            }
914
+            if (isset($this->ref_attr[$link_id]))
915
+                $result .= $this->ref_attr[$link_id];
916
+
917
+            $link_text = $this->runSpanGamut($link_text);
918
+            $result .= ">$link_text</a>";
919
+            $result = $this->hashPart($result);
920
+        }
921
+        else {
922
+            $result = $whole_match;
923
+        }
924
+        return $result;
925
+    }
926
+
927
+    /**
928
+     * Callback for inline anchors
929
+     * @param  array $matches
930
+     * @return string
931
+     */
932
+    protected function _doAnchors_inline_callback($matches) {
933
+        $link_text		=  $this->runSpanGamut($matches[2]);
934
+        $url			=  $matches[3] === '' ? $matches[4] : $matches[3];
935
+        $title			=& $matches[7];
936
+        $attr  = $this->doExtraAttributes("a", $dummy =& $matches[8]);
937
+
938
+        // if the URL was of the form <s p a c e s> it got caught by the HTML
939
+        // tag parser and hashed. Need to reverse the process before using the URL.
940
+        $unhashed = $this->unhash($url);
941
+        if ($unhashed !== $url)
942
+            $url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
943
+
944
+        $url = $this->encodeURLAttribute($url);
945
+
946
+        $result = "<a href=\"$url\"";
947
+        if (isset($title)) {
948
+            $title = $this->encodeAttribute($title);
949
+            $result .=  " title=\"$title\"";
950
+        }
951
+        $result .= $attr;
952
+
953
+        $link_text = $this->runSpanGamut($link_text);
954
+        $result .= ">$link_text</a>";
955
+
956
+        return $this->hashPart($result);
957
+    }
958
+
959
+    /**
960
+     * Turn Markdown image shortcuts into <img> tags.
961
+     * @param  string $text
962
+     * @return string
963
+     */
964
+    protected function doImages($text) {
965
+        // First, handle reference-style labeled images: ![alt text][id]
966
+        $text = preg_replace_callback('{
967 967
 			(				# wrap whole match in $1
968 968
 			  !\[
969 969
 				(' . $this->nested_brackets_re . ')		# alt text = $2
@@ -978,11 +978,11 @@  discard block
 block discarded – undo
978 978
 
979 979
 			)
980 980
 			}xs',
981
-			array($this, '_doImages_reference_callback'), $text);
981
+            array($this, '_doImages_reference_callback'), $text);
982 982
 
983
-		// Next, handle inline images:  ![alt text](url "optional title")
984
-		// Don't forget: encode * and _
985
-		$text = preg_replace_callback('{
983
+        // Next, handle inline images:  ![alt text](url "optional title")
984
+        // Don't forget: encode * and _
985
+        $text = preg_replace_callback('{
986 986
 			(				# wrap whole match in $1
987 987
 			  !\[
988 988
 				(' . $this->nested_brackets_re . ')		# alt text = $2
@@ -1006,101 +1006,101 @@  discard block
 block discarded – undo
1006 1006
 			  (?:[ ]? ' . $this->id_class_attr_catch_re . ' )?	 # $8 = id/class attributes
1007 1007
 			)
1008 1008
 			}xs',
1009
-			array($this, '_doImages_inline_callback'), $text);
1010
-
1011
-		return $text;
1012
-	}
1013
-
1014
-	/**
1015
-	 * Callback for referenced images
1016
-	 * @param  array $matches
1017
-	 * @return string
1018
-	 */
1019
-	protected function _doImages_reference_callback($matches) {
1020
-		$whole_match = $matches[1];
1021
-		$alt_text    = $matches[2];
1022
-		$link_id     = strtolower($matches[3]);
1023
-
1024
-		if ($link_id === "") {
1025
-			$link_id = strtolower($alt_text); // for shortcut links like ![this][].
1026
-		}
1027
-
1028
-		$alt_text = $this->encodeAttribute($alt_text);
1029
-		if (isset($this->urls[$link_id])) {
1030
-			$url = $this->encodeURLAttribute($this->urls[$link_id]);
1031
-			$result = "<img src=\"$url\" alt=\"$alt_text\"";
1032
-			if (isset($this->titles[$link_id])) {
1033
-				$title = $this->titles[$link_id];
1034
-				$title = $this->encodeAttribute($title);
1035
-				$result .=  " title=\"$title\"";
1036
-			}
1037
-			if (isset($this->ref_attr[$link_id])) {
1038
-				$result .= $this->ref_attr[$link_id];
1039
-			}
1040
-			$result .= $this->empty_element_suffix;
1041
-			$result = $this->hashPart($result);
1042
-		}
1043
-		else {
1044
-			// If there's no such link ID, leave intact:
1045
-			$result = $whole_match;
1046
-		}
1047
-
1048
-		return $result;
1049
-	}
1050
-
1051
-	/**
1052
-	 * Callback for inline images
1053
-	 * @param  array $matches
1054
-	 * @return string
1055
-	 */
1056
-	protected function _doImages_inline_callback($matches) {
1057
-		$alt_text		= $matches[2];
1058
-		$url			= $matches[3] === '' ? $matches[4] : $matches[3];
1059
-		$title			=& $matches[7];
1060
-		$attr  = $this->doExtraAttributes("img", $dummy =& $matches[8]);
1061
-
1062
-		$alt_text = $this->encodeAttribute($alt_text);
1063
-		$url = $this->encodeURLAttribute($url);
1064
-		$result = "<img src=\"$url\" alt=\"$alt_text\"";
1065
-		if (isset($title)) {
1066
-			$title = $this->encodeAttribute($title);
1067
-			$result .=  " title=\"$title\""; // $title already quoted
1068
-		}
1069
-		$result .= $attr;
1070
-		$result .= $this->empty_element_suffix;
1071
-
1072
-		return $this->hashPart($result);
1073
-	}
1074
-
1075
-	/**
1076
-	 * Process markdown headers. Redefined to add ID and class attribute support.
1077
-	 * @param  string $text
1078
-	 * @return string
1079
-	 */
1080
-	protected function doHeaders($text) {
1081
-		// Setext-style headers:
1082
-		//  Header 1  {#header1}
1083
-		//	  ========
1084
-		//
1085
-		//	  Header 2  {#header2 .class1 .class2}
1086
-		//	  --------
1087
-		//
1088
-		$text = preg_replace_callback(
1089
-			'{
1009
+            array($this, '_doImages_inline_callback'), $text);
1010
+
1011
+        return $text;
1012
+    }
1013
+
1014
+    /**
1015
+     * Callback for referenced images
1016
+     * @param  array $matches
1017
+     * @return string
1018
+     */
1019
+    protected function _doImages_reference_callback($matches) {
1020
+        $whole_match = $matches[1];
1021
+        $alt_text    = $matches[2];
1022
+        $link_id     = strtolower($matches[3]);
1023
+
1024
+        if ($link_id === "") {
1025
+            $link_id = strtolower($alt_text); // for shortcut links like ![this][].
1026
+        }
1027
+
1028
+        $alt_text = $this->encodeAttribute($alt_text);
1029
+        if (isset($this->urls[$link_id])) {
1030
+            $url = $this->encodeURLAttribute($this->urls[$link_id]);
1031
+            $result = "<img src=\"$url\" alt=\"$alt_text\"";
1032
+            if (isset($this->titles[$link_id])) {
1033
+                $title = $this->titles[$link_id];
1034
+                $title = $this->encodeAttribute($title);
1035
+                $result .=  " title=\"$title\"";
1036
+            }
1037
+            if (isset($this->ref_attr[$link_id])) {
1038
+                $result .= $this->ref_attr[$link_id];
1039
+            }
1040
+            $result .= $this->empty_element_suffix;
1041
+            $result = $this->hashPart($result);
1042
+        }
1043
+        else {
1044
+            // If there's no such link ID, leave intact:
1045
+            $result = $whole_match;
1046
+        }
1047
+
1048
+        return $result;
1049
+    }
1050
+
1051
+    /**
1052
+     * Callback for inline images
1053
+     * @param  array $matches
1054
+     * @return string
1055
+     */
1056
+    protected function _doImages_inline_callback($matches) {
1057
+        $alt_text		= $matches[2];
1058
+        $url			= $matches[3] === '' ? $matches[4] : $matches[3];
1059
+        $title			=& $matches[7];
1060
+        $attr  = $this->doExtraAttributes("img", $dummy =& $matches[8]);
1061
+
1062
+        $alt_text = $this->encodeAttribute($alt_text);
1063
+        $url = $this->encodeURLAttribute($url);
1064
+        $result = "<img src=\"$url\" alt=\"$alt_text\"";
1065
+        if (isset($title)) {
1066
+            $title = $this->encodeAttribute($title);
1067
+            $result .=  " title=\"$title\""; // $title already quoted
1068
+        }
1069
+        $result .= $attr;
1070
+        $result .= $this->empty_element_suffix;
1071
+
1072
+        return $this->hashPart($result);
1073
+    }
1074
+
1075
+    /**
1076
+     * Process markdown headers. Redefined to add ID and class attribute support.
1077
+     * @param  string $text
1078
+     * @return string
1079
+     */
1080
+    protected function doHeaders($text) {
1081
+        // Setext-style headers:
1082
+        //  Header 1  {#header1}
1083
+        //	  ========
1084
+        //
1085
+        //	  Header 2  {#header2 .class1 .class2}
1086
+        //	  --------
1087
+        //
1088
+        $text = preg_replace_callback(
1089
+            '{
1090 1090
 				(^.+?)								# $1: Header text
1091 1091
 				(?:[ ]+ ' . $this->id_class_attr_catch_re . ' )?	 # $3 = id/class attributes
1092 1092
 				[ ]*\n(=+|-+)[ ]*\n+				# $3: Header footer
1093 1093
 			}mx',
1094
-			array($this, '_doHeaders_callback_setext'), $text);
1095
-
1096
-		// atx-style headers:
1097
-		//	# Header 1        {#header1}
1098
-		//	## Header 2       {#header2}
1099
-		//	## Header 2 with closing hashes ##  {#header3.class1.class2}
1100
-		//	...
1101
-		//	###### Header 6   {.class2}
1102
-		//
1103
-		$text = preg_replace_callback('{
1094
+            array($this, '_doHeaders_callback_setext'), $text);
1095
+
1096
+        // atx-style headers:
1097
+        //	# Header 1        {#header1}
1098
+        //	## Header 2       {#header2}
1099
+        //	## Header 2 with closing hashes ##  {#header3.class1.class2}
1100
+        //	...
1101
+        //	###### Header 6   {.class2}
1102
+        //
1103
+        $text = preg_replace_callback('{
1104 1104
 				^(\#{1,6})	# $1 = string of #\'s
1105 1105
 				[ ]'.($this->hashtag_protection ? '+' : '*').'
1106 1106
 				(.+?)		# $2 = Header text
@@ -1110,58 +1110,58 @@  discard block
 block discarded – undo
1110 1110
 				[ ]*
1111 1111
 				\n+
1112 1112
 			}xm',
1113
-			array($this, '_doHeaders_callback_atx'), $text);
1114
-
1115
-		return $text;
1116
-	}
1117
-
1118
-	/**
1119
-	 * Callback for setext headers
1120
-	 * @param  array $matches
1121
-	 * @return string
1122
-	 */
1123
-	protected function _doHeaders_callback_setext($matches) {
1124
-		if ($matches[3] === '-' && preg_match('{^- }', $matches[1])) {
1125
-			return $matches[0];
1126
-		}
1127
-
1128
-		$level = $matches[3][0] === '=' ? 1 : 2;
1129
-
1130
-		$defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[1]) : null;
1131
-
1132
-		$attr  = $this->doExtraAttributes("h$level", $dummy =& $matches[2], $defaultId);
1133
-		$block = "<h$level$attr>" . $this->runSpanGamut($matches[1]) . "</h$level>";
1134
-		return "\n" . $this->hashBlock($block) . "\n\n";
1135
-	}
1136
-
1137
-	/**
1138
-	 * Callback for atx headers
1139
-	 * @param  array $matches
1140
-	 * @return string
1141
-	 */
1142
-	protected function _doHeaders_callback_atx($matches) {
1143
-		$level = strlen($matches[1]);
1144
-
1145
-		$defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[2]) : null;
1146
-		$attr  = $this->doExtraAttributes("h$level", $dummy =& $matches[3], $defaultId);
1147
-		$block = "<h$level$attr>" . $this->runSpanGamut($matches[2]) . "</h$level>";
1148
-		return "\n" . $this->hashBlock($block) . "\n\n";
1149
-	}
1150
-
1151
-	/**
1152
-	 * Form HTML tables.
1153
-	 * @param  string $text
1154
-	 * @return string
1155
-	 */
1156
-	protected function doTables($text) {
1157
-		$less_than_tab = $this->tab_width - 1;
1158
-		// Find tables with leading pipe.
1159
-		//
1160
-		//	| Header 1 | Header 2
1161
-		//	| -------- | --------
1162
-		//	| Cell 1   | Cell 2
1163
-		//	| Cell 3   | Cell 4
1164
-		$text = preg_replace_callback('
1113
+            array($this, '_doHeaders_callback_atx'), $text);
1114
+
1115
+        return $text;
1116
+    }
1117
+
1118
+    /**
1119
+     * Callback for setext headers
1120
+     * @param  array $matches
1121
+     * @return string
1122
+     */
1123
+    protected function _doHeaders_callback_setext($matches) {
1124
+        if ($matches[3] === '-' && preg_match('{^- }', $matches[1])) {
1125
+            return $matches[0];
1126
+        }
1127
+
1128
+        $level = $matches[3][0] === '=' ? 1 : 2;
1129
+
1130
+        $defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[1]) : null;
1131
+
1132
+        $attr  = $this->doExtraAttributes("h$level", $dummy =& $matches[2], $defaultId);
1133
+        $block = "<h$level$attr>" . $this->runSpanGamut($matches[1]) . "</h$level>";
1134
+        return "\n" . $this->hashBlock($block) . "\n\n";
1135
+    }
1136
+
1137
+    /**
1138
+     * Callback for atx headers
1139
+     * @param  array $matches
1140
+     * @return string
1141
+     */
1142
+    protected function _doHeaders_callback_atx($matches) {
1143
+        $level = strlen($matches[1]);
1144
+
1145
+        $defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[2]) : null;
1146
+        $attr  = $this->doExtraAttributes("h$level", $dummy =& $matches[3], $defaultId);
1147
+        $block = "<h$level$attr>" . $this->runSpanGamut($matches[2]) . "</h$level>";
1148
+        return "\n" . $this->hashBlock($block) . "\n\n";
1149
+    }
1150
+
1151
+    /**
1152
+     * Form HTML tables.
1153
+     * @param  string $text
1154
+     * @return string
1155
+     */
1156
+    protected function doTables($text) {
1157
+        $less_than_tab = $this->tab_width - 1;
1158
+        // Find tables with leading pipe.
1159
+        //
1160
+        //	| Header 1 | Header 2
1161
+        //	| -------- | --------
1162
+        //	| Cell 1   | Cell 2
1163
+        //	| Cell 3   | Cell 4
1164
+        $text = preg_replace_callback('
1165 1165
 			{
1166 1166
 				^							# Start of a line
1167 1167
 				[ ]{0,' . $less_than_tab . '}	# Allowed whitespace.
@@ -1179,15 +1179,15 @@  discard block
 block discarded – undo
1179 1179
 				)
1180 1180
 				(?=\n|\Z)					# Stop at final double newline.
1181 1181
 			}xm',
1182
-			array($this, '_doTable_leadingPipe_callback'), $text);
1183
-
1184
-		// Find tables without leading pipe.
1185
-		//
1186
-		//	Header 1 | Header 2
1187
-		//	-------- | --------
1188
-		//	Cell 1   | Cell 2
1189
-		//	Cell 3   | Cell 4
1190
-		$text = preg_replace_callback('
1182
+            array($this, '_doTable_leadingPipe_callback'), $text);
1183
+
1184
+        // Find tables without leading pipe.
1185
+        //
1186
+        //	Header 1 | Header 2
1187
+        //	-------- | --------
1188
+        //	Cell 1   | Cell 2
1189
+        //	Cell 3   | Cell 4
1190
+        $text = preg_replace_callback('
1191 1191
 			{
1192 1192
 				^							# Start of a line
1193 1193
 				[ ]{0,' . $less_than_tab . '}	# Allowed whitespace.
@@ -1203,120 +1203,120 @@  discard block
 block discarded – undo
1203 1203
 				)
1204 1204
 				(?=\n|\Z)					# Stop at final double newline.
1205 1205
 			}xm',
1206
-			array($this, '_DoTable_callback'), $text);
1207
-
1208
-		return $text;
1209
-	}
1210
-
1211
-	/**
1212
-	 * Callback for removing the leading pipe for each row
1213
-	 * @param  array $matches
1214
-	 * @return string
1215
-	 */
1216
-	protected function _doTable_leadingPipe_callback($matches) {
1217
-		$head		= $matches[1];
1218
-		$underline	= $matches[2];
1219
-		$content	= $matches[3];
1220
-
1221
-		$content	= preg_replace('/^ *[|]/m', '', $content);
1222
-
1223
-		return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
1224
-	}
1225
-
1226
-	/**
1227
-	 * Make the align attribute in a table
1228
-	 * @param  string $alignname
1229
-	 * @return string
1230
-	 */
1231
-	protected function _doTable_makeAlignAttr($alignname) {
1232
-		if (empty($this->table_align_class_tmpl)) {
1233
-			return " align=\"$alignname\"";
1234
-		}
1235
-
1236
-		$classname = str_replace('%%', $alignname, $this->table_align_class_tmpl);
1237
-		return " class=\"$classname\"";
1238
-	}
1239
-
1240
-	/**
1241
-	 * Calback for processing tables
1242
-	 * @param  array $matches
1243
-	 * @return string
1244
-	 */
1245
-	protected function _doTable_callback($matches) {
1246
-		$head		= $matches[1];
1247
-		$underline	= $matches[2];
1248
-		$content	= $matches[3];
1249
-
1250
-		// Remove any tailing pipes for each line.
1251
-		$head		= preg_replace('/[|] *$/m', '', $head);
1252
-		$underline	= preg_replace('/[|] *$/m', '', $underline);
1253
-		$content	= preg_replace('/[|] *$/m', '', $content);
1254
-
1255
-		// Reading alignement from header underline.
1256
-		$separators	= preg_split('/ *[|] */', $underline);
1257
-		foreach ($separators as $n => $s) {
1258
-			if (preg_match('/^ *-+: *$/', $s))
1259
-				$attr[$n] = $this->_doTable_makeAlignAttr('right');
1260
-			else if (preg_match('/^ *:-+: *$/', $s))
1261
-				$attr[$n] = $this->_doTable_makeAlignAttr('center');
1262
-			else if (preg_match('/^ *:-+ *$/', $s))
1263
-				$attr[$n] = $this->_doTable_makeAlignAttr('left');
1264
-			else
1265
-				$attr[$n] = '';
1266
-		}
1267
-
1268
-		// Parsing span elements, including code spans, character escapes,
1269
-		// and inline HTML tags, so that pipes inside those gets ignored.
1270
-		$head		= $this->parseSpan($head);
1271
-		$headers	= preg_split('/ *[|] */', $head);
1272
-		$col_count	= count($headers);
1273
-		$attr       = array_pad($attr, $col_count, '');
1274
-
1275
-		// Write column headers.
1276
-		$text = "<table>\n";
1277
-		$text .= "<thead>\n";
1278
-		$text .= "<tr>\n";
1279
-		foreach ($headers as $n => $header) {
1280
-			$text .= "  <th$attr[$n]>" . $this->runSpanGamut(trim($header)) . "</th>\n";
1281
-		}
1282
-		$text .= "</tr>\n";
1283
-		$text .= "</thead>\n";
1284
-
1285
-		// Split content by row.
1286
-		$rows = explode("\n", trim($content, "\n"));
1287
-
1288
-		$text .= "<tbody>\n";
1289
-		foreach ($rows as $row) {
1290
-			// Parsing span elements, including code spans, character escapes,
1291
-			// and inline HTML tags, so that pipes inside those gets ignored.
1292
-			$row = $this->parseSpan($row);
1293
-
1294
-			// Split row by cell.
1295
-			$row_cells = preg_split('/ *[|] */', $row, $col_count);
1296
-			$row_cells = array_pad($row_cells, $col_count, '');
1297
-
1298
-			$text .= "<tr>\n";
1299
-			foreach ($row_cells as $n => $cell) {
1300
-				$text .= "  <td$attr[$n]>" . $this->runSpanGamut(trim($cell)) . "</td>\n";
1301
-			}
1302
-			$text .= "</tr>\n";
1303
-		}
1304
-		$text .= "</tbody>\n";
1305
-		$text .= "</table>";
1306
-
1307
-		return $this->hashBlock($text) . "\n";
1308
-	}
1309
-
1310
-	/**
1311
-	 * Form HTML definition lists.
1312
-	 * @param  string $text
1313
-	 * @return string
1314
-	 */
1315
-	protected function doDefLists($text) {
1316
-		$less_than_tab = $this->tab_width - 1;
1317
-
1318
-		// Re-usable pattern to match any entire dl list:
1319
-		$whole_list_re = '(?>
1206
+            array($this, '_DoTable_callback'), $text);
1207
+
1208
+        return $text;
1209
+    }
1210
+
1211
+    /**
1212
+     * Callback for removing the leading pipe for each row
1213
+     * @param  array $matches
1214
+     * @return string
1215
+     */
1216
+    protected function _doTable_leadingPipe_callback($matches) {
1217
+        $head		= $matches[1];
1218
+        $underline	= $matches[2];
1219
+        $content	= $matches[3];
1220
+
1221
+        $content	= preg_replace('/^ *[|]/m', '', $content);
1222
+
1223
+        return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
1224
+    }
1225
+
1226
+    /**
1227
+     * Make the align attribute in a table
1228
+     * @param  string $alignname
1229
+     * @return string
1230
+     */
1231
+    protected function _doTable_makeAlignAttr($alignname) {
1232
+        if (empty($this->table_align_class_tmpl)) {
1233
+            return " align=\"$alignname\"";
1234
+        }
1235
+
1236
+        $classname = str_replace('%%', $alignname, $this->table_align_class_tmpl);
1237
+        return " class=\"$classname\"";
1238
+    }
1239
+
1240
+    /**
1241
+     * Calback for processing tables
1242
+     * @param  array $matches
1243
+     * @return string
1244
+     */
1245
+    protected function _doTable_callback($matches) {
1246
+        $head		= $matches[1];
1247
+        $underline	= $matches[2];
1248
+        $content	= $matches[3];
1249
+
1250
+        // Remove any tailing pipes for each line.
1251
+        $head		= preg_replace('/[|] *$/m', '', $head);
1252
+        $underline	= preg_replace('/[|] *$/m', '', $underline);
1253
+        $content	= preg_replace('/[|] *$/m', '', $content);
1254
+
1255
+        // Reading alignement from header underline.
1256
+        $separators	= preg_split('/ *[|] */', $underline);
1257
+        foreach ($separators as $n => $s) {
1258
+            if (preg_match('/^ *-+: *$/', $s))
1259
+                $attr[$n] = $this->_doTable_makeAlignAttr('right');
1260
+            else if (preg_match('/^ *:-+: *$/', $s))
1261
+                $attr[$n] = $this->_doTable_makeAlignAttr('center');
1262
+            else if (preg_match('/^ *:-+ *$/', $s))
1263
+                $attr[$n] = $this->_doTable_makeAlignAttr('left');
1264
+            else
1265
+                $attr[$n] = '';
1266
+        }
1267
+
1268
+        // Parsing span elements, including code spans, character escapes,
1269
+        // and inline HTML tags, so that pipes inside those gets ignored.
1270
+        $head		= $this->parseSpan($head);
1271
+        $headers	= preg_split('/ *[|] */', $head);
1272
+        $col_count	= count($headers);
1273
+        $attr       = array_pad($attr, $col_count, '');
1274
+
1275
+        // Write column headers.
1276
+        $text = "<table>\n";
1277
+        $text .= "<thead>\n";
1278
+        $text .= "<tr>\n";
1279
+        foreach ($headers as $n => $header) {
1280
+            $text .= "  <th$attr[$n]>" . $this->runSpanGamut(trim($header)) . "</th>\n";
1281
+        }
1282
+        $text .= "</tr>\n";
1283
+        $text .= "</thead>\n";
1284
+
1285
+        // Split content by row.
1286
+        $rows = explode("\n", trim($content, "\n"));
1287
+
1288
+        $text .= "<tbody>\n";
1289
+        foreach ($rows as $row) {
1290
+            // Parsing span elements, including code spans, character escapes,
1291
+            // and inline HTML tags, so that pipes inside those gets ignored.
1292
+            $row = $this->parseSpan($row);
1293
+
1294
+            // Split row by cell.
1295
+            $row_cells = preg_split('/ *[|] */', $row, $col_count);
1296
+            $row_cells = array_pad($row_cells, $col_count, '');
1297
+
1298
+            $text .= "<tr>\n";
1299
+            foreach ($row_cells as $n => $cell) {
1300
+                $text .= "  <td$attr[$n]>" . $this->runSpanGamut(trim($cell)) . "</td>\n";
1301
+            }
1302
+            $text .= "</tr>\n";
1303
+        }
1304
+        $text .= "</tbody>\n";
1305
+        $text .= "</table>";
1306
+
1307
+        return $this->hashBlock($text) . "\n";
1308
+    }
1309
+
1310
+    /**
1311
+     * Form HTML definition lists.
1312
+     * @param  string $text
1313
+     * @return string
1314
+     */
1315
+    protected function doDefLists($text) {
1316
+        $less_than_tab = $this->tab_width - 1;
1317
+
1318
+        // Re-usable pattern to match any entire dl list:
1319
+        $whole_list_re = '(?>
1320 1320
 			(								# $1 = whole list
1321 1321
 			  (								# $2
1322 1322
 				[ ]{0,' . $less_than_tab . '}
@@ -1343,46 +1343,46 @@  discard block
 block discarded – undo
1343 1343
 			)
1344 1344
 		)'; // mx
1345 1345
 
1346
-		$text = preg_replace_callback('{
1346
+        $text = preg_replace_callback('{
1347 1347
 				(?>\A\n?|(?<=\n\n))
1348 1348
 				' . $whole_list_re . '
1349 1349
 			}mx',
1350
-			array($this, '_doDefLists_callback'), $text);
1351
-
1352
-		return $text;
1353
-	}
1354
-
1355
-	/**
1356
-	 * Callback for processing definition lists
1357
-	 * @param  array $matches
1358
-	 * @return string
1359
-	 */
1360
-	protected function _doDefLists_callback($matches) {
1361
-		// Re-usable patterns to match list item bullets and number markers:
1362
-		$list = $matches[1];
1363
-
1364
-		// Turn double returns into triple returns, so that we can make a
1365
-		// paragraph for the last item in a list, if necessary:
1366
-		$result = trim($this->processDefListItems($list));
1367
-		$result = "<dl>\n" . $result . "\n</dl>";
1368
-		return $this->hashBlock($result) . "\n\n";
1369
-	}
1370
-
1371
-	/**
1372
-	 * Process the contents of a single definition list, splitting it
1373
-	 * into individual term and definition list items.
1374
-	 * @param  string $list_str
1375
-	 * @return string
1376
-	 */
1377
-	protected function processDefListItems($list_str) {
1378
-
1379
-		$less_than_tab = $this->tab_width - 1;
1380
-
1381
-		// Trim trailing blank lines:
1382
-		$list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
1383
-
1384
-		// Process definition terms.
1385
-		$list_str = preg_replace_callback('{
1350
+            array($this, '_doDefLists_callback'), $text);
1351
+
1352
+        return $text;
1353
+    }
1354
+
1355
+    /**
1356
+     * Callback for processing definition lists
1357
+     * @param  array $matches
1358
+     * @return string
1359
+     */
1360
+    protected function _doDefLists_callback($matches) {
1361
+        // Re-usable patterns to match list item bullets and number markers:
1362
+        $list = $matches[1];
1363
+
1364
+        // Turn double returns into triple returns, so that we can make a
1365
+        // paragraph for the last item in a list, if necessary:
1366
+        $result = trim($this->processDefListItems($list));
1367
+        $result = "<dl>\n" . $result . "\n</dl>";
1368
+        return $this->hashBlock($result) . "\n\n";
1369
+    }
1370
+
1371
+    /**
1372
+     * Process the contents of a single definition list, splitting it
1373
+     * into individual term and definition list items.
1374
+     * @param  string $list_str
1375
+     * @return string
1376
+     */
1377
+    protected function processDefListItems($list_str) {
1378
+
1379
+        $less_than_tab = $this->tab_width - 1;
1380
+
1381
+        // Trim trailing blank lines:
1382
+        $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
1383
+
1384
+        // Process definition terms.
1385
+        $list_str = preg_replace_callback('{
1386 1386
 			(?>\A\n?|\n\n+)						# leading line
1387 1387
 			(									# definition terms = $1
1388 1388
 				[ ]{0,' . $less_than_tab . '}	# leading whitespace
@@ -1393,10 +1393,10 @@  discard block
 block discarded – undo
1393 1393
 			(?=\n?[ ]{0,3}:[ ])					# lookahead for following line feed
1394 1394
 												#   with a definition mark.
1395 1395
 			}xm',
1396
-			array($this, '_processDefListItems_callback_dt'), $list_str);
1396
+            array($this, '_processDefListItems_callback_dt'), $list_str);
1397 1397
 
1398
-		// Process actual definitions.
1399
-		$list_str = preg_replace_callback('{
1398
+        // Process actual definitions.
1399
+        $list_str = preg_replace_callback('{
1400 1400
 			\n(\n+)?							# leading line = $1
1401 1401
 			(									# marker space = $2
1402 1402
 				[ ]{0,' . $less_than_tab . '}	# whitespace before colon
@@ -1410,63 +1410,63 @@  discard block
 block discarded – undo
1410 1410
 				)
1411 1411
 			)
1412 1412
 			}xm',
1413
-			array($this, '_processDefListItems_callback_dd'), $list_str);
1414
-
1415
-		return $list_str;
1416
-	}
1417
-
1418
-	/**
1419
-	 * Callback for <dt> elements in definition lists
1420
-	 * @param  array $matches
1421
-	 * @return string
1422
-	 */
1423
-	protected function _processDefListItems_callback_dt($matches) {
1424
-		$terms = explode("\n", trim($matches[1]));
1425
-		$text = '';
1426
-		foreach ($terms as $term) {
1427
-			$term = $this->runSpanGamut(trim($term));
1428
-			$text .= "\n<dt>" . $term . "</dt>";
1429
-		}
1430
-		return $text . "\n";
1431
-	}
1432
-
1433
-	/**
1434
-	 * Callback for <dd> elements in definition lists
1435
-	 * @param  array $matches
1436
-	 * @return string
1437
-	 */
1438
-	protected function _processDefListItems_callback_dd($matches) {
1439
-		$leading_line	= $matches[1];
1440
-		$marker_space	= $matches[2];
1441
-		$def			= $matches[3];
1442
-
1443
-		if ($leading_line || preg_match('/\n{2,}/', $def)) {
1444
-			// Replace marker with the appropriate whitespace indentation
1445
-			$def = str_repeat(' ', strlen($marker_space)) . $def;
1446
-			$def = $this->runBlockGamut($this->outdent($def . "\n\n"));
1447
-			$def = "\n". $def ."\n";
1448
-		}
1449
-		else {
1450
-			$def = rtrim($def);
1451
-			$def = $this->runSpanGamut($this->outdent($def));
1452
-		}
1453
-
1454
-		return "\n<dd>" . $def . "</dd>\n";
1455
-	}
1456
-
1457
-	/**
1458
-	 * Adding the fenced code block syntax to regular Markdown:
1459
-	 *
1460
-	 * ~~~
1461
-	 * Code block
1462
-	 * ~~~
1463
-	 *
1464
-	 * @param  string $text
1465
-	 * @return string
1466
-	 */
1467
-	protected function doFencedCodeBlocks($text) {
1468
-
1469
-		$text = preg_replace_callback('{
1413
+            array($this, '_processDefListItems_callback_dd'), $list_str);
1414
+
1415
+        return $list_str;
1416
+    }
1417
+
1418
+    /**
1419
+     * Callback for <dt> elements in definition lists
1420
+     * @param  array $matches
1421
+     * @return string
1422
+     */
1423
+    protected function _processDefListItems_callback_dt($matches) {
1424
+        $terms = explode("\n", trim($matches[1]));
1425
+        $text = '';
1426
+        foreach ($terms as $term) {
1427
+            $term = $this->runSpanGamut(trim($term));
1428
+            $text .= "\n<dt>" . $term . "</dt>";
1429
+        }
1430
+        return $text . "\n";
1431
+    }
1432
+
1433
+    /**
1434
+     * Callback for <dd> elements in definition lists
1435
+     * @param  array $matches
1436
+     * @return string
1437
+     */
1438
+    protected function _processDefListItems_callback_dd($matches) {
1439
+        $leading_line	= $matches[1];
1440
+        $marker_space	= $matches[2];
1441
+        $def			= $matches[3];
1442
+
1443
+        if ($leading_line || preg_match('/\n{2,}/', $def)) {
1444
+            // Replace marker with the appropriate whitespace indentation
1445
+            $def = str_repeat(' ', strlen($marker_space)) . $def;
1446
+            $def = $this->runBlockGamut($this->outdent($def . "\n\n"));
1447
+            $def = "\n". $def ."\n";
1448
+        }
1449
+        else {
1450
+            $def = rtrim($def);
1451
+            $def = $this->runSpanGamut($this->outdent($def));
1452
+        }
1453
+
1454
+        return "\n<dd>" . $def . "</dd>\n";
1455
+    }
1456
+
1457
+    /**
1458
+     * Adding the fenced code block syntax to regular Markdown:
1459
+     *
1460
+     * ~~~
1461
+     * Code block
1462
+     * ~~~
1463
+     *
1464
+     * @param  string $text
1465
+     * @return string
1466
+     */
1467
+    protected function doFencedCodeBlocks($text) {
1468
+
1469
+        $text = preg_replace_callback('{
1470 1470
 				(?:\n|\A)
1471 1471
 				# 1: Opening marker
1472 1472
 				(
@@ -1493,123 +1493,123 @@  discard block
 block discarded – undo
1493 1493
 				# Closing marker.
1494 1494
 				\1 [ ]* (?= \n )
1495 1495
 			}xm',
1496
-			array($this, '_doFencedCodeBlocks_callback'), $text);
1497
-
1498
-		return $text;
1499
-	}
1500
-
1501
-	/**
1502
-	 * Callback to process fenced code blocks
1503
-	 * @param  array $matches
1504
-	 * @return string
1505
-	 */
1506
-	protected function _doFencedCodeBlocks_callback($matches) {
1507
-		$classname =& $matches[2];
1508
-		$attrs     =& $matches[3];
1509
-		$codeblock = $matches[4];
1510
-
1511
-		if ($this->code_block_content_func) {
1512
-			$codeblock = call_user_func($this->code_block_content_func, $codeblock, $classname);
1513
-		} else {
1514
-			$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
1515
-		}
1516
-
1517
-		$codeblock = preg_replace_callback('/^\n+/',
1518
-			array($this, '_doFencedCodeBlocks_newlines'), $codeblock);
1519
-
1520
-		$classes = array();
1521
-		if ($classname !== "") {
1522
-			if ($classname[0] === '.') {
1523
-				$classname = substr($classname, 1);
1524
-			}
1525
-			$classes[] = $this->code_class_prefix . $classname;
1526
-		}
1527
-		$attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs, null, $classes);
1528
-		$pre_attr_str  = $this->code_attr_on_pre ? $attr_str : '';
1529
-		$code_attr_str = $this->code_attr_on_pre ? '' : $attr_str;
1530
-		$codeblock  = "<pre$pre_attr_str><code$code_attr_str>$codeblock</code></pre>";
1531
-
1532
-		return "\n\n".$this->hashBlock($codeblock)."\n\n";
1533
-	}
1534
-
1535
-	/**
1536
-	 * Replace new lines in fenced code blocks
1537
-	 * @param  array $matches
1538
-	 * @return string
1539
-	 */
1540
-	protected function _doFencedCodeBlocks_newlines($matches) {
1541
-		return str_repeat("<br$this->empty_element_suffix",
1542
-			strlen($matches[0]));
1543
-	}
1544
-
1545
-	/**
1546
-	 * Redefining emphasis markers so that emphasis by underscore does not
1547
-	 * work in the middle of a word.
1548
-	 * @var array
1549
-	 */
1550
-	protected $em_relist = array(
1551
-		''  => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?![\.,:;]?\s)',
1552
-		'*' => '(?<![\s*])\*(?!\*)',
1553
-		'_' => '(?<![\s_])_(?![a-zA-Z0-9_])',
1554
-	);
1555
-	protected $strong_relist = array(
1556
-		''   => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?![\.,:;]?\s)',
1557
-		'**' => '(?<![\s*])\*\*(?!\*)',
1558
-		'__' => '(?<![\s_])__(?![a-zA-Z0-9_])',
1559
-	);
1560
-	protected $em_strong_relist = array(
1561
-		''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?![\.,:;]?\s)',
1562
-		'***' => '(?<![\s*])\*\*\*(?!\*)',
1563
-		'___' => '(?<![\s_])___(?![a-zA-Z0-9_])',
1564
-	);
1565
-
1566
-	/**
1567
-	 * Parse text into paragraphs
1568
-	 * @param  string $text String to process in paragraphs
1569
-	 * @param  boolean $wrap_in_p Whether paragraphs should be wrapped in <p> tags
1570
-	 * @return string       HTML output
1571
-	 */
1572
-	protected function formParagraphs($text, $wrap_in_p = true) {
1573
-		// Strip leading and trailing lines:
1574
-		$text = preg_replace('/\A\n+|\n+\z/', '', $text);
1575
-
1576
-		$grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
1577
-
1578
-		// Wrap <p> tags and unhashify HTML blocks
1579
-		foreach ($grafs as $key => $value) {
1580
-			$value = trim($this->runSpanGamut($value));
1581
-
1582
-			// Check if this should be enclosed in a paragraph.
1583
-			// Clean tag hashes & block tag hashes are left alone.
1584
-			$is_p = $wrap_in_p && !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
1585
-
1586
-			if ($is_p) {
1587
-				$value = "<p>$value</p>";
1588
-			}
1589
-			$grafs[$key] = $value;
1590
-		}
1591
-
1592
-		// Join grafs in one text, then unhash HTML tags.
1593
-		$text = implode("\n\n", $grafs);
1594
-
1595
-		// Finish by removing any tag hashes still present in $text.
1596
-		$text = $this->unhash($text);
1597
-
1598
-		return $text;
1599
-	}
1600
-
1601
-
1602
-	/**
1603
-	 * Footnotes - Strips link definitions from text, stores the URLs and
1604
-	 * titles in hash references.
1605
-	 * @param  string $text
1606
-	 * @return string
1607
-	 */
1608
-	protected function stripFootnotes($text) {
1609
-		$less_than_tab = $this->tab_width - 1;
1610
-
1611
-		// Link defs are in the form: [^id]: url "optional title"
1612
-		$text = preg_replace_callback('{
1496
+            array($this, '_doFencedCodeBlocks_callback'), $text);
1497
+
1498
+        return $text;
1499
+    }
1500
+
1501
+    /**
1502
+     * Callback to process fenced code blocks
1503
+     * @param  array $matches
1504
+     * @return string
1505
+     */
1506
+    protected function _doFencedCodeBlocks_callback($matches) {
1507
+        $classname =& $matches[2];
1508
+        $attrs     =& $matches[3];
1509
+        $codeblock = $matches[4];
1510
+
1511
+        if ($this->code_block_content_func) {
1512
+            $codeblock = call_user_func($this->code_block_content_func, $codeblock, $classname);
1513
+        } else {
1514
+            $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
1515
+        }
1516
+
1517
+        $codeblock = preg_replace_callback('/^\n+/',
1518
+            array($this, '_doFencedCodeBlocks_newlines'), $codeblock);
1519
+
1520
+        $classes = array();
1521
+        if ($classname !== "") {
1522
+            if ($classname[0] === '.') {
1523
+                $classname = substr($classname, 1);
1524
+            }
1525
+            $classes[] = $this->code_class_prefix . $classname;
1526
+        }
1527
+        $attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs, null, $classes);
1528
+        $pre_attr_str  = $this->code_attr_on_pre ? $attr_str : '';
1529
+        $code_attr_str = $this->code_attr_on_pre ? '' : $attr_str;
1530
+        $codeblock  = "<pre$pre_attr_str><code$code_attr_str>$codeblock</code></pre>";
1531
+
1532
+        return "\n\n".$this->hashBlock($codeblock)."\n\n";
1533
+    }
1534
+
1535
+    /**
1536
+     * Replace new lines in fenced code blocks
1537
+     * @param  array $matches
1538
+     * @return string
1539
+     */
1540
+    protected function _doFencedCodeBlocks_newlines($matches) {
1541
+        return str_repeat("<br$this->empty_element_suffix",
1542
+            strlen($matches[0]));
1543
+    }
1544
+
1545
+    /**
1546
+     * Redefining emphasis markers so that emphasis by underscore does not
1547
+     * work in the middle of a word.
1548
+     * @var array
1549
+     */
1550
+    protected $em_relist = array(
1551
+        ''  => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?![\.,:;]?\s)',
1552
+        '*' => '(?<![\s*])\*(?!\*)',
1553
+        '_' => '(?<![\s_])_(?![a-zA-Z0-9_])',
1554
+    );
1555
+    protected $strong_relist = array(
1556
+        ''   => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?![\.,:;]?\s)',
1557
+        '**' => '(?<![\s*])\*\*(?!\*)',
1558
+        '__' => '(?<![\s_])__(?![a-zA-Z0-9_])',
1559
+    );
1560
+    protected $em_strong_relist = array(
1561
+        ''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?![\.,:;]?\s)',
1562
+        '***' => '(?<![\s*])\*\*\*(?!\*)',
1563
+        '___' => '(?<![\s_])___(?![a-zA-Z0-9_])',
1564
+    );
1565
+
1566
+    /**
1567
+     * Parse text into paragraphs
1568
+     * @param  string $text String to process in paragraphs
1569
+     * @param  boolean $wrap_in_p Whether paragraphs should be wrapped in <p> tags
1570
+     * @return string       HTML output
1571
+     */
1572
+    protected function formParagraphs($text, $wrap_in_p = true) {
1573
+        // Strip leading and trailing lines:
1574
+        $text = preg_replace('/\A\n+|\n+\z/', '', $text);
1575
+
1576
+        $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
1577
+
1578
+        // Wrap <p> tags and unhashify HTML blocks
1579
+        foreach ($grafs as $key => $value) {
1580
+            $value = trim($this->runSpanGamut($value));
1581
+
1582
+            // Check if this should be enclosed in a paragraph.
1583
+            // Clean tag hashes & block tag hashes are left alone.
1584
+            $is_p = $wrap_in_p && !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
1585
+
1586
+            if ($is_p) {
1587
+                $value = "<p>$value</p>";
1588
+            }
1589
+            $grafs[$key] = $value;
1590
+        }
1591
+
1592
+        // Join grafs in one text, then unhash HTML tags.
1593
+        $text = implode("\n\n", $grafs);
1594
+
1595
+        // Finish by removing any tag hashes still present in $text.
1596
+        $text = $this->unhash($text);
1597
+
1598
+        return $text;
1599
+    }
1600
+
1601
+
1602
+    /**
1603
+     * Footnotes - Strips link definitions from text, stores the URLs and
1604
+     * titles in hash references.
1605
+     * @param  string $text
1606
+     * @return string
1607
+     */
1608
+    protected function stripFootnotes($text) {
1609
+        $less_than_tab = $this->tab_width - 1;
1610
+
1611
+        // Link defs are in the form: [^id]: url "optional title"
1612
+        $text = preg_replace_callback('{
1613 1613
 			^[ ]{0,' . $less_than_tab . '}\[\^(.+?)\][ ]?:	# note_id = $1
1614 1614
 			  [ ]*
1615 1615
 			  \n?					# maybe *one* newline
@@ -1624,270 +1624,270 @@  discard block
 block discarded – undo
1624 1624
 				)*
1625 1625
 			)
1626 1626
 			}xm',
1627
-			array($this, '_stripFootnotes_callback'),
1628
-			$text);
1629
-		return $text;
1630
-	}
1631
-
1632
-	/**
1633
-	 * Callback for stripping footnotes
1634
-	 * @param  array $matches
1635
-	 * @return string
1636
-	 */
1637
-	protected function _stripFootnotes_callback($matches) {
1638
-		$note_id = $this->fn_id_prefix . $matches[1];
1639
-		$this->footnotes[$note_id] = $this->outdent($matches[2]);
1640
-		return ''; // String that will replace the block
1641
-	}
1642
-
1643
-	/**
1644
-	 * Replace footnote references in $text [^id] with a special text-token
1645
-	 * which will be replaced by the actual footnote marker in appendFootnotes.
1646
-	 * @param  string $text
1647
-	 * @return string
1648
-	 */
1649
-	protected function doFootnotes($text) {
1650
-		if (!$this->in_anchor) {
1651
-			$text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
1652
-		}
1653
-		return $text;
1654
-	}
1655
-
1656
-	/**
1657
-	 * Append footnote list to text
1658
-	 * @param  string $text
1659
-	 * @return string
1660
-	 */
1661
-	protected function appendFootnotes($text) {
1662
-		$text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
1663
-			array($this, '_appendFootnotes_callback'), $text);
1664
-
1665
-		if ( ! empty( $this->footnotes_ordered ) ) {
1666
-			$this->_doFootnotes();
1667
-			if ( ! $this->omit_footnotes ) {
1668
-				$text .= "\n\n";
1669
-				$text .= "<div class=\"footnotes\" role=\"doc-endnotes\">\n";
1670
-				$text .= "<hr" . $this->empty_element_suffix . "\n";
1671
-				$text .= $this->footnotes_assembled;
1672
-				$text .= "</div>";
1673
-			}
1674
-		}
1675
-		return $text;
1676
-	}
1677
-
1678
-
1679
-	/**
1680
-	 * Generates the HTML for footnotes.  Called by appendFootnotes, even if
1681
-	 * footnotes are not being appended.
1682
-	 * @return void
1683
-	 */
1684
-	protected function _doFootnotes() {
1685
-		$attr = array();
1686
-		if ($this->fn_backlink_class !== "") {
1687
-			$class = $this->fn_backlink_class;
1688
-			$class = $this->encodeAttribute($class);
1689
-			$attr['class'] = " class=\"$class\"";
1690
-		}
1691
-		$attr['role'] = " role=\"doc-backlink\"";
1692
-		$num = 0;
1693
-
1694
-		$text = "<ol>\n\n";
1695
-		while (!empty($this->footnotes_ordered)) {
1696
-			$footnote = reset($this->footnotes_ordered);
1697
-			$note_id = key($this->footnotes_ordered);
1698
-			unset($this->footnotes_ordered[$note_id]);
1699
-			$ref_count = $this->footnotes_ref_count[$note_id];
1700
-			unset($this->footnotes_ref_count[$note_id]);
1701
-			unset($this->footnotes[$note_id]);
1702
-
1703
-			$footnote .= "\n"; // Need to append newline before parsing.
1704
-			$footnote = $this->runBlockGamut("$footnote\n");
1705
-			$footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
1706
-				array($this, '_appendFootnotes_callback'), $footnote);
1707
-
1708
-			$num++;
1709
-			$note_id = $this->encodeAttribute($note_id);
1710
-
1711
-			// Prepare backlink, multiple backlinks if multiple references
1712
-			// Do not create empty backlinks if the html is blank
1713
-			$backlink = "";
1714
-			if (!empty($this->fn_backlink_html)) {
1715
-				for ($ref_num = 1; $ref_num <= $ref_count; ++$ref_num) {
1716
-					if (!empty($this->fn_backlink_title)) {
1717
-						$attr['title'] = ' title="' . $this->encodeAttribute($this->fn_backlink_title) . '"';
1718
-					}
1719
-					if (!empty($this->fn_backlink_label)) {
1720
-						$attr['label'] = ' aria-label="' . $this->encodeAttribute($this->fn_backlink_label) . '"';
1721
-					}
1722
-					$parsed_attr = $this->parseFootnotePlaceholders(
1723
-						implode('', $attr),
1724
-						$num,
1725
-						$ref_num
1726
-					);
1727
-					$backlink_text = $this->parseFootnotePlaceholders(
1728
-						$this->fn_backlink_html,
1729
-						$num,
1730
-						$ref_num
1731
-					);
1732
-					$ref_count_mark = $ref_num > 1 ? $ref_num : '';
1733
-					$backlink .= " <a href=\"#fnref$ref_count_mark:$note_id\"$parsed_attr>$backlink_text</a>";
1734
-				}
1735
-				$backlink = trim($backlink);
1736
-			}
1737
-
1738
-			// Add backlink to last paragraph; create new paragraph if needed.
1739
-			if (!empty($backlink)) {
1740
-				if (preg_match('{</p>$}', $footnote)) {
1741
-					$footnote = substr($footnote, 0, -4) . "&#160;$backlink</p>";
1742
-				} else {
1743
-					$footnote .= "\n\n<p>$backlink</p>";
1744
-				}
1745
-			}
1746
-
1747
-			$text .= "<li id=\"fn:$note_id\" role=\"doc-endnote\">\n";
1748
-			$text .= $footnote . "\n";
1749
-			$text .= "</li>\n\n";
1750
-		}
1751
-		$text .= "</ol>\n";
1752
-
1753
-		$this->footnotes_assembled = $text;
1754
-	}
1755
-
1756
-	/**
1757
-	 * Callback for appending footnotes
1758
-	 * @param  array $matches
1759
-	 * @return string
1760
-	 */
1761
-	protected function _appendFootnotes_callback($matches) {
1762
-		$node_id = $this->fn_id_prefix . $matches[1];
1763
-
1764
-		// Create footnote marker only if it has a corresponding footnote *and*
1765
-		// the footnote hasn't been used by another marker.
1766
-		if (isset($this->footnotes[$node_id])) {
1767
-			$num =& $this->footnotes_numbers[$node_id];
1768
-			if (!isset($num)) {
1769
-				// Transfer footnote content to the ordered list and give it its
1770
-				// number
1771
-				$this->footnotes_ordered[$node_id] = $this->footnotes[$node_id];
1772
-				$this->footnotes_ref_count[$node_id] = 1;
1773
-				$num = $this->footnote_counter++;
1774
-				$ref_count_mark = '';
1775
-			} else {
1776
-				$ref_count_mark = $this->footnotes_ref_count[$node_id] += 1;
1777
-			}
1778
-
1779
-			$attr = "";
1780
-			if ($this->fn_link_class !== "") {
1781
-				$class = $this->fn_link_class;
1782
-				$class = $this->encodeAttribute($class);
1783
-				$attr .= " class=\"$class\"";
1784
-			}
1785
-			if ($this->fn_link_title !== "") {
1786
-				$title = $this->fn_link_title;
1787
-				$title = $this->encodeAttribute($title);
1788
-				$attr .= " title=\"$title\"";
1789
-			}
1790
-			$attr .= " role=\"doc-noteref\"";
1791
-
1792
-			$attr = str_replace("%%", $num, $attr);
1793
-			$node_id = $this->encodeAttribute($node_id);
1794
-
1795
-			return
1796
-				"<sup id=\"fnref$ref_count_mark:$node_id\">".
1797
-				"<a href=\"#fn:$node_id\"$attr>$num</a>".
1798
-				"</sup>";
1799
-		}
1800
-
1801
-		return "[^" . $matches[1] . "]";
1802
-	}
1803
-
1804
-	/**
1805
-	 * Build footnote label by evaluating any placeholders.
1806
-	 * - ^^  footnote number
1807
-	 * - %%  footnote reference number (Nth reference to footnote number)
1808
-	 * @param  string $label
1809
-	 * @param  int    $footnote_number
1810
-	 * @param  int    $reference_number
1811
-	 * @return string
1812
-	 */
1813
-	protected function parseFootnotePlaceholders($label, $footnote_number, $reference_number) {
1814
-		return str_replace(
1815
-			array('^^', '%%'),
1816
-			array($footnote_number, $reference_number),
1817
-			$label
1818
-		);
1819
-	}
1820
-
1821
-
1822
-	/**
1823
-	 * Abbreviations - strips abbreviations from text, stores titles in hash
1824
-	 * references.
1825
-	 * @param  string $text
1826
-	 * @return string
1827
-	 */
1828
-	protected function stripAbbreviations($text) {
1829
-		$less_than_tab = $this->tab_width - 1;
1830
-
1831
-		// Link defs are in the form: [id]*: url "optional title"
1832
-		$text = preg_replace_callback('{
1627
+            array($this, '_stripFootnotes_callback'),
1628
+            $text);
1629
+        return $text;
1630
+    }
1631
+
1632
+    /**
1633
+     * Callback for stripping footnotes
1634
+     * @param  array $matches
1635
+     * @return string
1636
+     */
1637
+    protected function _stripFootnotes_callback($matches) {
1638
+        $note_id = $this->fn_id_prefix . $matches[1];
1639
+        $this->footnotes[$note_id] = $this->outdent($matches[2]);
1640
+        return ''; // String that will replace the block
1641
+    }
1642
+
1643
+    /**
1644
+     * Replace footnote references in $text [^id] with a special text-token
1645
+     * which will be replaced by the actual footnote marker in appendFootnotes.
1646
+     * @param  string $text
1647
+     * @return string
1648
+     */
1649
+    protected function doFootnotes($text) {
1650
+        if (!$this->in_anchor) {
1651
+            $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
1652
+        }
1653
+        return $text;
1654
+    }
1655
+
1656
+    /**
1657
+     * Append footnote list to text
1658
+     * @param  string $text
1659
+     * @return string
1660
+     */
1661
+    protected function appendFootnotes($text) {
1662
+        $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
1663
+            array($this, '_appendFootnotes_callback'), $text);
1664
+
1665
+        if ( ! empty( $this->footnotes_ordered ) ) {
1666
+            $this->_doFootnotes();
1667
+            if ( ! $this->omit_footnotes ) {
1668
+                $text .= "\n\n";
1669
+                $text .= "<div class=\"footnotes\" role=\"doc-endnotes\">\n";
1670
+                $text .= "<hr" . $this->empty_element_suffix . "\n";
1671
+                $text .= $this->footnotes_assembled;
1672
+                $text .= "</div>";
1673
+            }
1674
+        }
1675
+        return $text;
1676
+    }
1677
+
1678
+
1679
+    /**
1680
+     * Generates the HTML for footnotes.  Called by appendFootnotes, even if
1681
+     * footnotes are not being appended.
1682
+     * @return void
1683
+     */
1684
+    protected function _doFootnotes() {
1685
+        $attr = array();
1686
+        if ($this->fn_backlink_class !== "") {
1687
+            $class = $this->fn_backlink_class;
1688
+            $class = $this->encodeAttribute($class);
1689
+            $attr['class'] = " class=\"$class\"";
1690
+        }
1691
+        $attr['role'] = " role=\"doc-backlink\"";
1692
+        $num = 0;
1693
+
1694
+        $text = "<ol>\n\n";
1695
+        while (!empty($this->footnotes_ordered)) {
1696
+            $footnote = reset($this->footnotes_ordered);
1697
+            $note_id = key($this->footnotes_ordered);
1698
+            unset($this->footnotes_ordered[$note_id]);
1699
+            $ref_count = $this->footnotes_ref_count[$note_id];
1700
+            unset($this->footnotes_ref_count[$note_id]);
1701
+            unset($this->footnotes[$note_id]);
1702
+
1703
+            $footnote .= "\n"; // Need to append newline before parsing.
1704
+            $footnote = $this->runBlockGamut("$footnote\n");
1705
+            $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
1706
+                array($this, '_appendFootnotes_callback'), $footnote);
1707
+
1708
+            $num++;
1709
+            $note_id = $this->encodeAttribute($note_id);
1710
+
1711
+            // Prepare backlink, multiple backlinks if multiple references
1712
+            // Do not create empty backlinks if the html is blank
1713
+            $backlink = "";
1714
+            if (!empty($this->fn_backlink_html)) {
1715
+                for ($ref_num = 1; $ref_num <= $ref_count; ++$ref_num) {
1716
+                    if (!empty($this->fn_backlink_title)) {
1717
+                        $attr['title'] = ' title="' . $this->encodeAttribute($this->fn_backlink_title) . '"';
1718
+                    }
1719
+                    if (!empty($this->fn_backlink_label)) {
1720
+                        $attr['label'] = ' aria-label="' . $this->encodeAttribute($this->fn_backlink_label) . '"';
1721
+                    }
1722
+                    $parsed_attr = $this->parseFootnotePlaceholders(
1723
+                        implode('', $attr),
1724
+                        $num,
1725
+                        $ref_num
1726
+                    );
1727
+                    $backlink_text = $this->parseFootnotePlaceholders(
1728
+                        $this->fn_backlink_html,
1729
+                        $num,
1730
+                        $ref_num
1731
+                    );
1732
+                    $ref_count_mark = $ref_num > 1 ? $ref_num : '';
1733
+                    $backlink .= " <a href=\"#fnref$ref_count_mark:$note_id\"$parsed_attr>$backlink_text</a>";
1734
+                }
1735
+                $backlink = trim($backlink);
1736
+            }
1737
+
1738
+            // Add backlink to last paragraph; create new paragraph if needed.
1739
+            if (!empty($backlink)) {
1740
+                if (preg_match('{</p>$}', $footnote)) {
1741
+                    $footnote = substr($footnote, 0, -4) . "&#160;$backlink</p>";
1742
+                } else {
1743
+                    $footnote .= "\n\n<p>$backlink</p>";
1744
+                }
1745
+            }
1746
+
1747
+            $text .= "<li id=\"fn:$note_id\" role=\"doc-endnote\">\n";
1748
+            $text .= $footnote . "\n";
1749
+            $text .= "</li>\n\n";
1750
+        }
1751
+        $text .= "</ol>\n";
1752
+
1753
+        $this->footnotes_assembled = $text;
1754
+    }
1755
+
1756
+    /**
1757
+     * Callback for appending footnotes
1758
+     * @param  array $matches
1759
+     * @return string
1760
+     */
1761
+    protected function _appendFootnotes_callback($matches) {
1762
+        $node_id = $this->fn_id_prefix . $matches[1];
1763
+
1764
+        // Create footnote marker only if it has a corresponding footnote *and*
1765
+        // the footnote hasn't been used by another marker.
1766
+        if (isset($this->footnotes[$node_id])) {
1767
+            $num =& $this->footnotes_numbers[$node_id];
1768
+            if (!isset($num)) {
1769
+                // Transfer footnote content to the ordered list and give it its
1770
+                // number
1771
+                $this->footnotes_ordered[$node_id] = $this->footnotes[$node_id];
1772
+                $this->footnotes_ref_count[$node_id] = 1;
1773
+                $num = $this->footnote_counter++;
1774
+                $ref_count_mark = '';
1775
+            } else {
1776
+                $ref_count_mark = $this->footnotes_ref_count[$node_id] += 1;
1777
+            }
1778
+
1779
+            $attr = "";
1780
+            if ($this->fn_link_class !== "") {
1781
+                $class = $this->fn_link_class;
1782
+                $class = $this->encodeAttribute($class);
1783
+                $attr .= " class=\"$class\"";
1784
+            }
1785
+            if ($this->fn_link_title !== "") {
1786
+                $title = $this->fn_link_title;
1787
+                $title = $this->encodeAttribute($title);
1788
+                $attr .= " title=\"$title\"";
1789
+            }
1790
+            $attr .= " role=\"doc-noteref\"";
1791
+
1792
+            $attr = str_replace("%%", $num, $attr);
1793
+            $node_id = $this->encodeAttribute($node_id);
1794
+
1795
+            return
1796
+                "<sup id=\"fnref$ref_count_mark:$node_id\">".
1797
+                "<a href=\"#fn:$node_id\"$attr>$num</a>".
1798
+                "</sup>";
1799
+        }
1800
+
1801
+        return "[^" . $matches[1] . "]";
1802
+    }
1803
+
1804
+    /**
1805
+     * Build footnote label by evaluating any placeholders.
1806
+     * - ^^  footnote number
1807
+     * - %%  footnote reference number (Nth reference to footnote number)
1808
+     * @param  string $label
1809
+     * @param  int    $footnote_number
1810
+     * @param  int    $reference_number
1811
+     * @return string
1812
+     */
1813
+    protected function parseFootnotePlaceholders($label, $footnote_number, $reference_number) {
1814
+        return str_replace(
1815
+            array('^^', '%%'),
1816
+            array($footnote_number, $reference_number),
1817
+            $label
1818
+        );
1819
+    }
1820
+
1821
+
1822
+    /**
1823
+     * Abbreviations - strips abbreviations from text, stores titles in hash
1824
+     * references.
1825
+     * @param  string $text
1826
+     * @return string
1827
+     */
1828
+    protected function stripAbbreviations($text) {
1829
+        $less_than_tab = $this->tab_width - 1;
1830
+
1831
+        // Link defs are in the form: [id]*: url "optional title"
1832
+        $text = preg_replace_callback('{
1833 1833
 			^[ ]{0,' . $less_than_tab . '}\*\[(.+?)\][ ]?:	# abbr_id = $1
1834 1834
 			(.*)					# text = $2 (no blank lines allowed)
1835 1835
 			}xm',
1836
-			array($this, '_stripAbbreviations_callback'),
1837
-			$text);
1838
-		return $text;
1839
-	}
1840
-
1841
-	/**
1842
-	 * Callback for stripping abbreviations
1843
-	 * @param  array $matches
1844
-	 * @return string
1845
-	 */
1846
-	protected function _stripAbbreviations_callback($matches) {
1847
-		$abbr_word = $matches[1];
1848
-		$abbr_desc = $matches[2];
1849
-		if ($this->abbr_word_re) {
1850
-			$this->abbr_word_re .= '|';
1851
-		}
1852
-		$this->abbr_word_re .= preg_quote($abbr_word);
1853
-		$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
1854
-		return ''; // String that will replace the block
1855
-	}
1856
-
1857
-	/**
1858
-	 * Find defined abbreviations in text and wrap them in <abbr> elements.
1859
-	 * @param  string $text
1860
-	 * @return string
1861
-	 */
1862
-	protected function doAbbreviations($text) {
1863
-		if ($this->abbr_word_re) {
1864
-			// cannot use the /x modifier because abbr_word_re may
1865
-			// contain significant spaces:
1866
-			$text = preg_replace_callback('{' .
1867
-				'(?<![\w\x1A])' .
1868
-				'(?:' . $this->abbr_word_re . ')' .
1869
-				'(?![\w\x1A])' .
1870
-				'}',
1871
-				array($this, '_doAbbreviations_callback'), $text);
1872
-		}
1873
-		return $text;
1874
-	}
1875
-
1876
-	/**
1877
-	 * Callback for processing abbreviations
1878
-	 * @param  array $matches
1879
-	 * @return string
1880
-	 */
1881
-	protected function _doAbbreviations_callback($matches) {
1882
-		$abbr = $matches[0];
1883
-		if (isset($this->abbr_desciptions[$abbr])) {
1884
-			$desc = $this->abbr_desciptions[$abbr];
1885
-			if (empty($desc)) {
1886
-				return $this->hashPart("<abbr>$abbr</abbr>");
1887
-			}
1888
-			$desc = $this->encodeAttribute($desc);
1889
-			return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>");
1890
-		}
1891
-		return $matches[0];
1892
-	}
1836
+            array($this, '_stripAbbreviations_callback'),
1837
+            $text);
1838
+        return $text;
1839
+    }
1840
+
1841
+    /**
1842
+     * Callback for stripping abbreviations
1843
+     * @param  array $matches
1844
+     * @return string
1845
+     */
1846
+    protected function _stripAbbreviations_callback($matches) {
1847
+        $abbr_word = $matches[1];
1848
+        $abbr_desc = $matches[2];
1849
+        if ($this->abbr_word_re) {
1850
+            $this->abbr_word_re .= '|';
1851
+        }
1852
+        $this->abbr_word_re .= preg_quote($abbr_word);
1853
+        $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
1854
+        return ''; // String that will replace the block
1855
+    }
1856
+
1857
+    /**
1858
+     * Find defined abbreviations in text and wrap them in <abbr> elements.
1859
+     * @param  string $text
1860
+     * @return string
1861
+     */
1862
+    protected function doAbbreviations($text) {
1863
+        if ($this->abbr_word_re) {
1864
+            // cannot use the /x modifier because abbr_word_re may
1865
+            // contain significant spaces:
1866
+            $text = preg_replace_callback('{' .
1867
+                '(?<![\w\x1A])' .
1868
+                '(?:' . $this->abbr_word_re . ')' .
1869
+                '(?![\w\x1A])' .
1870
+                '}',
1871
+                array($this, '_doAbbreviations_callback'), $text);
1872
+        }
1873
+        return $text;
1874
+    }
1875
+
1876
+    /**
1877
+     * Callback for processing abbreviations
1878
+     * @param  array $matches
1879
+     * @return string
1880
+     */
1881
+    protected function _doAbbreviations_callback($matches) {
1882
+        $abbr = $matches[0];
1883
+        if (isset($this->abbr_desciptions[$abbr])) {
1884
+            $desc = $this->abbr_desciptions[$abbr];
1885
+            if (empty($desc)) {
1886
+                return $this->hashPart("<abbr>$abbr</abbr>");
1887
+            }
1888
+            $desc = $this->encodeAttribute($desc);
1889
+            return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>");
1890
+        }
1891
+        return $matches[0];
1892
+    }
1893 1893
 }
Please login to merge, or discard this patch.
Spacing   +63 added lines, -63 removed lines patch added patch discarded remove patch
@@ -205,7 +205,7 @@  discard block
 block discarded – undo
205 205
 		$this->abbr_desciptions = array();
206 206
 		$this->abbr_word_re = '';
207 207
 
208
-		if ( ! $this->omit_footnotes )
208
+		if (!$this->omit_footnotes)
209 209
 			$this->footnotes_assembled = null;
210 210
 
211 211
 		parent::teardown();
@@ -273,13 +273,13 @@  discard block
 block discarded – undo
273 273
 		// Compose attributes as string
274 274
 		$attr_str = "";
275 275
 		if (!empty($id)) {
276
-			$attr_str .= ' id="'.$this->encodeAttribute($id) .'"';
276
+			$attr_str .= ' id="' . $this->encodeAttribute($id) . '"';
277 277
 		}
278 278
 		if (!empty($classes)) {
279
-			$attr_str .= ' class="'. implode(" ", $classes) . '"';
279
+			$attr_str .= ' class="' . implode(" ", $classes) . '"';
280 280
 		}
281 281
 		if (!$this->no_markup && !empty($attributes)) {
282
-			$attr_str .= ' '.implode(" ", $attributes);
282
+			$attr_str .= ' ' . implode(" ", $attributes);
283 283
 		}
284 284
 		return $attr_str;
285 285
 	}
@@ -295,7 +295,7 @@  discard block
 block discarded – undo
295 295
 
296 296
 		// Link defs are in the form: ^[id]: url "optional title"
297 297
 		$text = preg_replace_callback('{
298
-							^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?:	# id = $1
298
+							^[ ]{0,'.$less_than_tab . '}\[(.+)\][ ]?:	# id = $1
299 299
 							  [ ]*
300 300
 							  \n?				# maybe *one* newline
301 301
 							  [ ]*
@@ -314,7 +314,7 @@  discard block
 block discarded – undo
314 314
 								[")]
315 315
 								[ ]*
316 316
 							)?	# title is optional
317
-					(?:[ ]* '.$this->id_class_attr_catch_re.' )?  # $5 = extra id & class attr
317
+					(?:[ ]* '.$this->id_class_attr_catch_re . ' )?  # $5 = extra id & class attr
318 318
 							(?:\n+|\Z)
319 319
 			}xm',
320 320
 			array($this, '_stripLinkDefinitions_callback'),
@@ -331,8 +331,8 @@  discard block
 block discarded – undo
331 331
 		$link_id = strtolower($matches[1]);
332 332
 		$url = $matches[2] == '' ? $matches[3] : $matches[2];
333 333
 		$this->urls[$link_id] = $url;
334
-		$this->titles[$link_id] =& $matches[4];
335
-		$this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]);
334
+		$this->titles[$link_id] = & $matches[4];
335
+		$this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy = & $matches[5]);
336 336
 		return ''; // String that will replace the block
337 337
 	}
338 338
 
@@ -395,7 +395,7 @@  discard block
 block discarded – undo
395 395
 		}
396 396
 
397 397
 		// Call the HTML-in-Markdown hasher.
398
-		list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
398
+		list($text,) = $this->_hashHTMLBlocks_inMarkdown($text);
399 399
 
400 400
 		return $text;
401 401
 	}
@@ -472,7 +472,7 @@  discard block
 block discarded – undo
472 472
 					<\?.*?\?> | <%.*?%>	# Processing instruction
473 473
 				|
474 474
 					<!\[CDATA\[.*?\]\]>	# CData Block
475
-				' . ( !$span ? ' # If not in span.
475
+				' . (!$span ? ' # If not in span.
476 476
 				|
477 477
 					# Indented code block
478 478
 					(?: ^[ ]*\n | ^ | \n[ ]*\n )
@@ -490,7 +490,7 @@  discard block
 block discarded – undo
490 490
 					(?: ' . $this->id_class_attr_nocatch_re . ' )? # extra attributes
491 491
 					[ ]*
492 492
 					(?= \n )
493
-				' : '' ) . ' # End (if not is span).
493
+				' : '') . ' # End (if not is span).
494 494
 				|
495 495
 					# Code span marker
496 496
 					# Note, this regex needs to go after backtick fenced
@@ -501,8 +501,8 @@  discard block
 block discarded – undo
501 501
 			}xs';
502 502
 
503 503
 
504
-		$depth = 0;		// Current depth inside the tag tree.
505
-		$parsed = "";	// Parsed text that will be returned.
504
+		$depth = 0; // Current depth inside the tag tree.
505
+		$parsed = ""; // Parsed text that will be returned.
506 506
 
507 507
 		// Loop through every tag until we find the closing tag of the parent
508 508
 		// or loop until reaching the end of text if no parent tag specified.
@@ -579,9 +579,9 @@  discard block
 block discarded – undo
579 579
 			//            Opening Context Block tag (like ins and del)
580 580
 			//               used as a block tag (tag is alone on it's line).
581 581
 			else if (preg_match('{^<(?:' . $this->block_tags_re . ')\b}', $tag) ||
582
-				(	preg_match('{^<(?:' . $this->context_block_tags_re . ')\b}', $tag) &&
582
+				(preg_match('{^<(?:' . $this->context_block_tags_re . ')\b}', $tag) &&
583 583
 					preg_match($newline_before_re, $parsed) &&
584
-					preg_match($newline_after_re, $text)	)
584
+					preg_match($newline_after_re, $text))
585 585
 				)
586 586
 			{
587 587
 				// Need to parse tag and following text using the HTML parser.
@@ -611,7 +611,7 @@  discard block
 block discarded – undo
611 611
 				// Increase/decrease nested tag count.
612 612
 				if ($tag[1] === '/') {
613 613
 					$depth--;
614
-				} else if ($tag[strlen($tag)-2] !== '/') {
614
+				} else if ($tag[strlen($tag) - 2] !== '/') {
615 615
 					$depth++;
616 616
 				}
617 617
 
@@ -688,11 +688,11 @@  discard block
 block discarded – undo
688 688
 				)
689 689
 			}xs';
690 690
 
691
-		$original_text = $text;		// Save original text in case of faliure.
691
+		$original_text = $text; // Save original text in case of faliure.
692 692
 
693
-		$depth		= 0;	// Current depth inside the tag tree.
694
-		$block_text	= "";	// Temporary text holder for current text.
695
-		$parsed		= "";	// Parsed text that will be returned.
693
+		$depth = 0; // Current depth inside the tag tree.
694
+		$block_text = ""; // Temporary text holder for current text.
695
+		$parsed = ""; // Parsed text that will be returned.
696 696
 		$base_tag_name_re = '';
697 697
 
698 698
 		// Get the name of the starting tag.
@@ -734,7 +734,7 @@  discard block
 block discarded – undo
734 734
 				if (preg_match('{^</?' . $base_tag_name_re . '\b}', $tag)) {
735 735
 					if ($tag[1] === '/') {
736 736
 						$depth--;
737
-					} else if ($tag[strlen($tag)-2] !== '/') {
737
+					} else if ($tag[strlen($tag) - 2] !== '/') {
738 738
 						$depth++;
739 739
 					}
740 740
 				}
@@ -784,7 +784,7 @@  discard block
 block discarded – undo
784 784
 					if (!$span_mode) {
785 785
 						$parsed .= "\n\n$block_text\n\n";
786 786
 					} else {
787
-						$parsed .= (string) $block_text;
787
+						$parsed .= (string)$block_text;
788 788
 					}
789 789
 
790 790
 					// Start over with a new block.
@@ -888,9 +888,9 @@  discard block
 block discarded – undo
888 888
 	 * @return string
889 889
 	 */
890 890
 	protected function _doAnchors_reference_callback($matches) {
891
-		$whole_match =  $matches[1];
892
-		$link_text   =  $matches[2];
893
-		$link_id     =& $matches[3];
891
+		$whole_match = $matches[1];
892
+		$link_text   = $matches[2];
893
+		$link_id     = & $matches[3];
894 894
 
895 895
 		if ($link_id == "") {
896 896
 			// for shortcut links like [this][] or [this].
@@ -906,10 +906,10 @@  discard block
 block discarded – undo
906 906
 			$url = $this->encodeURLAttribute($url);
907 907
 
908 908
 			$result = "<a href=\"$url\"";
909
-			if ( isset( $this->titles[$link_id] ) ) {
909
+			if (isset($this->titles[$link_id])) {
910 910
 				$title = $this->titles[$link_id];
911 911
 				$title = $this->encodeAttribute($title);
912
-				$result .=  " title=\"$title\"";
912
+				$result .= " title=\"$title\"";
913 913
 			}
914 914
 			if (isset($this->ref_attr[$link_id]))
915 915
 				$result .= $this->ref_attr[$link_id];
@@ -930,10 +930,10 @@  discard block
 block discarded – undo
930 930
 	 * @return string
931 931
 	 */
932 932
 	protected function _doAnchors_inline_callback($matches) {
933
-		$link_text		=  $this->runSpanGamut($matches[2]);
934
-		$url			=  $matches[3] === '' ? $matches[4] : $matches[3];
935
-		$title			=& $matches[7];
936
-		$attr  = $this->doExtraAttributes("a", $dummy =& $matches[8]);
933
+		$link_text = $this->runSpanGamut($matches[2]);
934
+		$url			= $matches[3] === '' ? $matches[4] : $matches[3];
935
+		$title = & $matches[7];
936
+		$attr  = $this->doExtraAttributes("a", $dummy = & $matches[8]);
937 937
 
938 938
 		// if the URL was of the form <s p a c e s> it got caught by the HTML
939 939
 		// tag parser and hashed. Need to reverse the process before using the URL.
@@ -946,7 +946,7 @@  discard block
 block discarded – undo
946 946
 		$result = "<a href=\"$url\"";
947 947
 		if (isset($title)) {
948 948
 			$title = $this->encodeAttribute($title);
949
-			$result .=  " title=\"$title\"";
949
+			$result .= " title=\"$title\"";
950 950
 		}
951 951
 		$result .= $attr;
952 952
 
@@ -1032,7 +1032,7 @@  discard block
 block discarded – undo
1032 1032
 			if (isset($this->titles[$link_id])) {
1033 1033
 				$title = $this->titles[$link_id];
1034 1034
 				$title = $this->encodeAttribute($title);
1035
-				$result .=  " title=\"$title\"";
1035
+				$result .= " title=\"$title\"";
1036 1036
 			}
1037 1037
 			if (isset($this->ref_attr[$link_id])) {
1038 1038
 				$result .= $this->ref_attr[$link_id];
@@ -1054,17 +1054,17 @@  discard block
 block discarded – undo
1054 1054
 	 * @return string
1055 1055
 	 */
1056 1056
 	protected function _doImages_inline_callback($matches) {
1057
-		$alt_text		= $matches[2];
1057
+		$alt_text = $matches[2];
1058 1058
 		$url			= $matches[3] === '' ? $matches[4] : $matches[3];
1059
-		$title			=& $matches[7];
1060
-		$attr  = $this->doExtraAttributes("img", $dummy =& $matches[8]);
1059
+		$title = & $matches[7];
1060
+		$attr  = $this->doExtraAttributes("img", $dummy = & $matches[8]);
1061 1061
 
1062 1062
 		$alt_text = $this->encodeAttribute($alt_text);
1063 1063
 		$url = $this->encodeURLAttribute($url);
1064 1064
 		$result = "<img src=\"$url\" alt=\"$alt_text\"";
1065 1065
 		if (isset($title)) {
1066 1066
 			$title = $this->encodeAttribute($title);
1067
-			$result .=  " title=\"$title\""; // $title already quoted
1067
+			$result .= " title=\"$title\""; // $title already quoted
1068 1068
 		}
1069 1069
 		$result .= $attr;
1070 1070
 		$result .= $this->empty_element_suffix;
@@ -1102,7 +1102,7 @@  discard block
 block discarded – undo
1102 1102
 		//
1103 1103
 		$text = preg_replace_callback('{
1104 1104
 				^(\#{1,6})	# $1 = string of #\'s
1105
-				[ ]'.($this->hashtag_protection ? '+' : '*').'
1105
+				[ ]'.($this->hashtag_protection ? '+' : '*') . '
1106 1106
 				(.+?)		# $2 = Header text
1107 1107
 				[ ]*
1108 1108
 				\#*			# optional closing #\'s (not counted)
@@ -1129,7 +1129,7 @@  discard block
 block discarded – undo
1129 1129
 
1130 1130
 		$defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[1]) : null;
1131 1131
 
1132
-		$attr  = $this->doExtraAttributes("h$level", $dummy =& $matches[2], $defaultId);
1132
+		$attr  = $this->doExtraAttributes("h$level", $dummy = & $matches[2], $defaultId);
1133 1133
 		$block = "<h$level$attr>" . $this->runSpanGamut($matches[1]) . "</h$level>";
1134 1134
 		return "\n" . $this->hashBlock($block) . "\n\n";
1135 1135
 	}
@@ -1143,7 +1143,7 @@  discard block
 block discarded – undo
1143 1143
 		$level = strlen($matches[1]);
1144 1144
 
1145 1145
 		$defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[2]) : null;
1146
-		$attr  = $this->doExtraAttributes("h$level", $dummy =& $matches[3], $defaultId);
1146
+		$attr  = $this->doExtraAttributes("h$level", $dummy = & $matches[3], $defaultId);
1147 1147
 		$block = "<h$level$attr>" . $this->runSpanGamut($matches[2]) . "</h$level>";
1148 1148
 		return "\n" . $this->hashBlock($block) . "\n\n";
1149 1149
 	}
@@ -1214,8 +1214,8 @@  discard block
 block discarded – undo
1214 1214
 	 * @return string
1215 1215
 	 */
1216 1216
 	protected function _doTable_leadingPipe_callback($matches) {
1217
-		$head		= $matches[1];
1218
-		$underline	= $matches[2];
1217
+		$head = $matches[1];
1218
+		$underline = $matches[2];
1219 1219
 		$content	= $matches[3];
1220 1220
 
1221 1221
 		$content	= preg_replace('/^ *[|]/m', '', $content);
@@ -1243,14 +1243,14 @@  discard block
 block discarded – undo
1243 1243
 	 * @return string
1244 1244
 	 */
1245 1245
 	protected function _doTable_callback($matches) {
1246
-		$head		= $matches[1];
1247
-		$underline	= $matches[2];
1248
-		$content	= $matches[3];
1246
+		$head = $matches[1];
1247
+		$underline = $matches[2];
1248
+		$content = $matches[3];
1249 1249
 
1250 1250
 		// Remove any tailing pipes for each line.
1251
-		$head		= preg_replace('/[|] *$/m', '', $head);
1252
-		$underline	= preg_replace('/[|] *$/m', '', $underline);
1253
-		$content	= preg_replace('/[|] *$/m', '', $content);
1251
+		$head = preg_replace('/[|] *$/m', '', $head);
1252
+		$underline = preg_replace('/[|] *$/m', '', $underline);
1253
+		$content = preg_replace('/[|] *$/m', '', $content);
1254 1254
 
1255 1255
 		// Reading alignement from header underline.
1256 1256
 		$separators	= preg_split('/ *[|] */', $underline);
@@ -1267,10 +1267,10 @@  discard block
 block discarded – undo
1267 1267
 
1268 1268
 		// Parsing span elements, including code spans, character escapes,
1269 1269
 		// and inline HTML tags, so that pipes inside those gets ignored.
1270
-		$head		= $this->parseSpan($head);
1271
-		$headers	= preg_split('/ *[|] */', $head);
1272
-		$col_count	= count($headers);
1273
-		$attr       = array_pad($attr, $col_count, '');
1270
+		$head = $this->parseSpan($head);
1271
+		$headers = preg_split('/ *[|] */', $head);
1272
+		$col_count = count($headers);
1273
+		$attr = array_pad($attr, $col_count, '');
1274 1274
 
1275 1275
 		// Write column headers.
1276 1276
 		$text = "<table>\n";
@@ -1438,13 +1438,13 @@  discard block
 block discarded – undo
1438 1438
 	protected function _processDefListItems_callback_dd($matches) {
1439 1439
 		$leading_line	= $matches[1];
1440 1440
 		$marker_space	= $matches[2];
1441
-		$def			= $matches[3];
1441
+		$def = $matches[3];
1442 1442
 
1443 1443
 		if ($leading_line || preg_match('/\n{2,}/', $def)) {
1444 1444
 			// Replace marker with the appropriate whitespace indentation
1445 1445
 			$def = str_repeat(' ', strlen($marker_space)) . $def;
1446 1446
 			$def = $this->runBlockGamut($this->outdent($def . "\n\n"));
1447
-			$def = "\n". $def ."\n";
1447
+			$def = "\n" . $def . "\n";
1448 1448
 		}
1449 1449
 		else {
1450 1450
 			$def = rtrim($def);
@@ -1504,8 +1504,8 @@  discard block
 block discarded – undo
1504 1504
 	 * @return string
1505 1505
 	 */
1506 1506
 	protected function _doFencedCodeBlocks_callback($matches) {
1507
-		$classname =& $matches[2];
1508
-		$attrs     =& $matches[3];
1507
+		$classname = & $matches[2];
1508
+		$attrs     = & $matches[3];
1509 1509
 		$codeblock = $matches[4];
1510 1510
 
1511 1511
 		if ($this->code_block_content_func) {
@@ -1527,9 +1527,9 @@  discard block
 block discarded – undo
1527 1527
 		$attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs, null, $classes);
1528 1528
 		$pre_attr_str  = $this->code_attr_on_pre ? $attr_str : '';
1529 1529
 		$code_attr_str = $this->code_attr_on_pre ? '' : $attr_str;
1530
-		$codeblock  = "<pre$pre_attr_str><code$code_attr_str>$codeblock</code></pre>";
1530
+		$codeblock = "<pre$pre_attr_str><code$code_attr_str>$codeblock</code></pre>";
1531 1531
 
1532
-		return "\n\n".$this->hashBlock($codeblock)."\n\n";
1532
+		return "\n\n" . $this->hashBlock($codeblock) . "\n\n";
1533 1533
 	}
1534 1534
 
1535 1535
 	/**
@@ -1662,9 +1662,9 @@  discard block
 block discarded – undo
1662 1662
 		$text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
1663 1663
 			array($this, '_appendFootnotes_callback'), $text);
1664 1664
 
1665
-		if ( ! empty( $this->footnotes_ordered ) ) {
1665
+		if (!empty($this->footnotes_ordered)) {
1666 1666
 			$this->_doFootnotes();
1667
-			if ( ! $this->omit_footnotes ) {
1667
+			if (!$this->omit_footnotes) {
1668 1668
 				$text .= "\n\n";
1669 1669
 				$text .= "<div class=\"footnotes\" role=\"doc-endnotes\">\n";
1670 1670
 				$text .= "<hr" . $this->empty_element_suffix . "\n";
@@ -1764,7 +1764,7 @@  discard block
 block discarded – undo
1764 1764
 		// Create footnote marker only if it has a corresponding footnote *and*
1765 1765
 		// the footnote hasn't been used by another marker.
1766 1766
 		if (isset($this->footnotes[$node_id])) {
1767
-			$num =& $this->footnotes_numbers[$node_id];
1767
+			$num = & $this->footnotes_numbers[$node_id];
1768 1768
 			if (!isset($num)) {
1769 1769
 				// Transfer footnote content to the ordered list and give it its
1770 1770
 				// number
@@ -1793,8 +1793,8 @@  discard block
 block discarded – undo
1793 1793
 			$node_id = $this->encodeAttribute($node_id);
1794 1794
 
1795 1795
 			return
1796
-				"<sup id=\"fnref$ref_count_mark:$node_id\">".
1797
-				"<a href=\"#fn:$node_id\"$attr>$num</a>".
1796
+				"<sup id=\"fnref$ref_count_mark:$node_id\">" .
1797
+				"<a href=\"#fn:$node_id\"$attr>$num</a>" .
1798 1798
 				"</sup>";
1799 1799
 		}
1800 1800
 
Please login to merge, or discard this patch.
Braces   +42 added lines, -36 removed lines patch added patch discarded remove patch
@@ -187,8 +187,9 @@  discard block
 block discarded – undo
187 187
 		$this->footnotes_assembled = null;
188 188
 
189 189
 		foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
190
-			if ($this->abbr_word_re)
191
-				$this->abbr_word_re .= '|';
190
+			if ($this->abbr_word_re) {
191
+							$this->abbr_word_re .= '|';
192
+			}
192 193
 			$this->abbr_word_re .= preg_quote($abbr_word);
193 194
 			$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
194 195
 		}
@@ -205,8 +206,9 @@  discard block
 block discarded – undo
205 206
 		$this->abbr_desciptions = array();
206 207
 		$this->abbr_word_re = '';
207 208
 
208
-		if ( ! $this->omit_footnotes )
209
-			$this->footnotes_assembled = null;
209
+		if ( ! $this->omit_footnotes ) {
210
+					$this->footnotes_assembled = null;
211
+		}
210 212
 
211 213
 		parent::teardown();
212 214
 	}
@@ -259,7 +261,9 @@  discard block
 block discarded – undo
259 261
 			if ($element[0] === '.') {
260 262
 				$classes[] = substr($element, 1);
261 263
 			} else if ($element[0] === '#') {
262
-				if ($id === false) $id = substr($element, 1);
264
+				if ($id === false) {
265
+				    $id = substr($element, 1);
266
+				}
263 267
 			} else if (strpos($element, '=') > 0) {
264 268
 				$parts = explode('=', $element, 2);
265 269
 				$attributes[] = $parts[0] . '="' . $parts[1] . '"';
@@ -435,7 +439,9 @@  discard block
 block discarded – undo
435 439
 										$enclosing_tag_re = '', $span = false)
436 440
 	{
437 441
 
438
-		if ($text === '') return array('', '');
442
+		if ($text === '') {
443
+		    return array('', '');
444
+		}
439 445
 
440 446
 		// Regex to check for the presense of newlines around a block tag.
441 447
 		$newline_before_re = '/(?:^\n?|\n\n)*$/';
@@ -546,8 +552,7 @@  discard block
 block discarded – undo
546 552
 					// End marker found: pass text unchanged until marker.
547 553
 					$parsed .= $tag . $matches[0];
548 554
 					$text = substr($text, strlen($matches[0]));
549
-				}
550
-				else {
555
+				} else {
551 556
 					// No end marker: just skip it.
552 557
 					$parsed .= $tag;
553 558
 				}
@@ -569,8 +574,7 @@  discard block
 block discarded – undo
569 574
 					// End marker found: pass text unchanged until marker.
570 575
 					$parsed .= $tag . $matches[0];
571 576
 					$text = substr($text, strlen($matches[0]));
572
-				}
573
-				else {
577
+				} else {
574 578
 					// Unmatched marker: just skip it.
575 579
 					$parsed .= $tag;
576 580
 				}
@@ -623,8 +627,7 @@  discard block
 block discarded – undo
623 627
 				}
624 628
 
625 629
 				$parsed .= $tag;
626
-			}
627
-			else {
630
+			} else {
628 631
 				$parsed .= $tag;
629 632
 			}
630 633
 		} while ($depth >= 0);
@@ -647,7 +650,9 @@  discard block
 block discarded – undo
647 650
 	 * @return array
648 651
 	 */
649 652
 	protected function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
650
-		if ($text === '') return array('', '');
653
+		if ($text === '') {
654
+		    return array('', '');
655
+		}
651 656
 
652 657
 		// Regex to match `markdown` attribute inside of a tag.
653 658
 		$markdown_attr_re = '
@@ -697,8 +702,9 @@  discard block
 block discarded – undo
697 702
 
698 703
 		// Get the name of the starting tag.
699 704
 		// (This pattern makes $base_tag_name_re safe without quoting.)
700
-		if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
701
-			$base_tag_name_re = $matches[1];
705
+		if (preg_match('/^<([\w:$]*)\b/', $text, $matches)) {
706
+					$base_tag_name_re = $matches[1];
707
+		}
702 708
 
703 709
 		// Loop through every tag until we find the corresponding closing tag.
704 710
 		do {
@@ -727,8 +733,7 @@  discard block
 block discarded – undo
727 733
 			{
728 734
 				// Just add the tag to the block as if it was text.
729 735
 				$block_text .= $tag;
730
-			}
731
-			else {
736
+			} else {
732 737
 				// Increase/decrease nested tag count. Only do so if
733 738
 				// the tag's name match base tag's.
734 739
 				if (preg_match('{^</?' . $base_tag_name_re . '\b}', $tag)) {
@@ -789,8 +794,9 @@  discard block
 block discarded – undo
789 794
 
790 795
 					// Start over with a new block.
791 796
 					$block_text = "";
797
+				} else {
798
+				    $block_text .= $tag;
792 799
 				}
793
-				else $block_text .= $tag;
794 800
 			}
795 801
 
796 802
 		} while ($depth > 0);
@@ -911,14 +917,14 @@  discard block
 block discarded – undo
911 917
 				$title = $this->encodeAttribute($title);
912 918
 				$result .=  " title=\"$title\"";
913 919
 			}
914
-			if (isset($this->ref_attr[$link_id]))
915
-				$result .= $this->ref_attr[$link_id];
920
+			if (isset($this->ref_attr[$link_id])) {
921
+							$result .= $this->ref_attr[$link_id];
922
+			}
916 923
 
917 924
 			$link_text = $this->runSpanGamut($link_text);
918 925
 			$result .= ">$link_text</a>";
919 926
 			$result = $this->hashPart($result);
920
-		}
921
-		else {
927
+		} else {
922 928
 			$result = $whole_match;
923 929
 		}
924 930
 		return $result;
@@ -938,8 +944,9 @@  discard block
 block discarded – undo
938 944
 		// if the URL was of the form <s p a c e s> it got caught by the HTML
939 945
 		// tag parser and hashed. Need to reverse the process before using the URL.
940 946
 		$unhashed = $this->unhash($url);
941
-		if ($unhashed !== $url)
942
-			$url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
947
+		if ($unhashed !== $url) {
948
+					$url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
949
+		}
943 950
 
944 951
 		$url = $this->encodeURLAttribute($url);
945 952
 
@@ -1039,8 +1046,7 @@  discard block
 block discarded – undo
1039 1046
 			}
1040 1047
 			$result .= $this->empty_element_suffix;
1041 1048
 			$result = $this->hashPart($result);
1042
-		}
1043
-		else {
1049
+		} else {
1044 1050
 			// If there's no such link ID, leave intact:
1045 1051
 			$result = $whole_match;
1046 1052
 		}
@@ -1255,14 +1261,15 @@  discard block
 block discarded – undo
1255 1261
 		// Reading alignement from header underline.
1256 1262
 		$separators	= preg_split('/ *[|] */', $underline);
1257 1263
 		foreach ($separators as $n => $s) {
1258
-			if (preg_match('/^ *-+: *$/', $s))
1259
-				$attr[$n] = $this->_doTable_makeAlignAttr('right');
1260
-			else if (preg_match('/^ *:-+: *$/', $s))
1261
-				$attr[$n] = $this->_doTable_makeAlignAttr('center');
1262
-			else if (preg_match('/^ *:-+ *$/', $s))
1263
-				$attr[$n] = $this->_doTable_makeAlignAttr('left');
1264
-			else
1265
-				$attr[$n] = '';
1264
+			if (preg_match('/^ *-+: *$/', $s)) {
1265
+							$attr[$n] = $this->_doTable_makeAlignAttr('right');
1266
+			} else if (preg_match('/^ *:-+: *$/', $s)) {
1267
+							$attr[$n] = $this->_doTable_makeAlignAttr('center');
1268
+			} else if (preg_match('/^ *:-+ *$/', $s)) {
1269
+							$attr[$n] = $this->_doTable_makeAlignAttr('left');
1270
+			} else {
1271
+							$attr[$n] = '';
1272
+			}
1266 1273
 		}
1267 1274
 
1268 1275
 		// Parsing span elements, including code spans, character escapes,
@@ -1445,8 +1452,7 @@  discard block
 block discarded – undo
1445 1452
 			$def = str_repeat(' ', strlen($marker_space)) . $def;
1446 1453
 			$def = $this->runBlockGamut($this->outdent($def . "\n\n"));
1447 1454
 			$def = "\n". $def ."\n";
1448
-		}
1449
-		else {
1455
+		} else {
1450 1456
 			$def = rtrim($def);
1451 1457
 			$def = $this->runSpanGamut($this->outdent($def));
1452 1458
 		}
Please login to merge, or discard this patch.
a/vendor/michelf/php-markdown/Michelf/MarkdownInterface.php 1 patch
Indentation   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -14,25 +14,25 @@
 block discarded – undo
14 14
  * Markdown Parser Interface
15 15
  */
16 16
 interface MarkdownInterface {
17
-	/**
18
-	 * Initialize the parser and return the result of its transform method.
19
-	 * This will work fine for derived classes too.
20
-	 *
21
-	 * @api
22
-	 *
23
-	 * @param  string $text
24
-	 * @return string
25
-	 */
26
-	public static function defaultTransform($text);
17
+    /**
18
+     * Initialize the parser and return the result of its transform method.
19
+     * This will work fine for derived classes too.
20
+     *
21
+     * @api
22
+     *
23
+     * @param  string $text
24
+     * @return string
25
+     */
26
+    public static function defaultTransform($text);
27 27
 
28
-	/**
29
-	 * Main function. Performs some preprocessing on the input text
30
-	 * and pass it through the document gamut.
31
-	 *
32
-	 * @api
33
-	 *
34
-	 * @param  string $text
35
-	 * @return string
36
-	 */
37
-	public function transform($text);
28
+    /**
29
+     * Main function. Performs some preprocessing on the input text
30
+     * and pass it through the document gamut.
31
+     *
32
+     * @api
33
+     *
34
+     * @param  string $text
35
+     * @return string
36
+     */
37
+    public function transform($text);
38 38
 }
Please login to merge, or discard this patch.