Completed
Push — master ( 754537...f00877 )
by Petrus
04:14
created
vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php 1 patch
Indentation   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -86,7 +86,7 @@
 block discarded – undo
86 86
         $content = array();
87 87
 
88 88
         $tbody_mode = false; // if true, then we need to wrap any stray
89
-                             // <tr>s with a <tbody>.
89
+                                // <tr>s with a <tbody>.
90 90
 
91 91
         $ws_accum =& $initial_ws;
92 92
 
Please login to merge, or discard this patch.
vendor/mos/ctextfilter/test/src/TextFilter/CTextFilterTest.php 1 patch
Indentation   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -12,23 +12,23 @@  discard block
 block discarded – undo
12 12
      * Supported filters.
13 13
      */
14 14
     private $standardFilters = [
15
-         'yamlfrontmatter',
16
-         'bbcode',
17
-         'clickable',
18
-         'markdown',
19
-         'nl2br',
20
-         'shortcode',
21
-         'purify',
22
-         'titlefromh1',
23
-     ];
24
-
25
-
26
-
27
-     /**
28
-      * Test.
29
-      *
30
-      * @return void
31
-      */
15
+            'yamlfrontmatter',
16
+            'bbcode',
17
+            'clickable',
18
+            'markdown',
19
+            'nl2br',
20
+            'shortcode',
21
+            'purify',
22
+            'titlefromh1',
23
+        ];
24
+
25
+
26
+
27
+        /**
28
+         * Test.
29
+         *
30
+         * @return void
31
+         */
32 32
     public function testTitleFromFirstH1()
33 33
     {
34 34
         $filter = new CTextFilter();
@@ -59,13 +59,13 @@  discard block
 block discarded – undo
59 59
 
60 60
 
61 61
 
62
-     /**
63
-      * Test.
64
-      *
65
-      * @expectedException /Mos/TextFilter/Exception
66
-      *
67
-      * @return void
68
-      */
62
+        /**
63
+         * Test.
64
+         *
65
+         * @expectedException /Mos/TextFilter/Exception
66
+         *
67
+         * @return void
68
+         */
69 69
     public function testJsonFrontMatterException()
70 70
     {
71 71
         $filter = new CTextFilter();
@@ -80,11 +80,11 @@  discard block
 block discarded – undo
80 80
 
81 81
 
82 82
 
83
-     /**
84
-      * Test.
85
-      *
86
-      * @return void
87
-      */
83
+        /**
84
+         * Test.
85
+         *
86
+         * @return void
87
+         */
88 88
     public function testJsonFrontMatter()
89 89
     {
90 90
         $filter = new CTextFilter();
Please login to merge, or discard this patch.
vendor/mos/ctextfilter/src/TextFilter/CTextFilter.php 1 patch
Indentation   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -21,13 +21,13 @@
 block discarded – undo
21 21
         "nl2br",
22 22
         "purify",
23 23
         "titlefromh1",
24
-     ];
24
+        ];
25 25
 
26 26
 
27 27
 
28
-     /**
29
-      * Current document parsed.
30
-      */
28
+        /**
29
+         * Current document parsed.
30
+         */
31 31
     private $current;
32 32
 
33 33
 
Please login to merge, or discard this patch.
vendor/michelf/php-markdown/Michelf/Markdown.php 1 patch
Indentation   +1159 added lines, -1159 removed lines patch added patch discarded remove patch
@@ -19,193 +19,193 @@  discard block
 block discarded – undo
19 19
 
20 20
 class Markdown implements MarkdownInterface {
21 21
 
22
-	### Version ###
22
+    ### Version ###
23 23
 
24
-	const  MARKDOWNLIB_VERSION  =  "1.5.0";
24
+    const  MARKDOWNLIB_VERSION  =  "1.5.0";
25 25
 
26
-	### Simple Function Interface ###
26
+    ### Simple Function Interface ###
27 27
 
28
-	public static function defaultTransform($text) {
29
-	#
30
-	# Initialize the parser and return the result of its transform method.
31
-	# This will work fine for derived classes too.
32
-	#
33
-		# Take parser class on which this function was called.
34
-		$parser_class = \get_called_class();
28
+    public static function defaultTransform($text) {
29
+    #
30
+    # Initialize the parser and return the result of its transform method.
31
+    # This will work fine for derived classes too.
32
+    #
33
+        # Take parser class on which this function was called.
34
+        $parser_class = \get_called_class();
35 35
 
36
-		# try to take parser from the static parser list
37
-		static $parser_list;
38
-		$parser =& $parser_list[$parser_class];
36
+        # try to take parser from the static parser list
37
+        static $parser_list;
38
+        $parser =& $parser_list[$parser_class];
39 39
 
40
-		# create the parser it not already set
41
-		if (!$parser)
42
-			$parser = new $parser_class;
40
+        # create the parser it not already set
41
+        if (!$parser)
42
+            $parser = new $parser_class;
43 43
 
44
-		# Transform text using parser.
45
-		return $parser->transform($text);
46
-	}
44
+        # Transform text using parser.
45
+        return $parser->transform($text);
46
+    }
47 47
 
48
-	### Configuration Variables ###
48
+    ### Configuration Variables ###
49 49
 
50
-	# Change to ">" for HTML output.
51
-	public $empty_element_suffix = " />";
52
-	public $tab_width = 4;
50
+    # Change to ">" for HTML output.
51
+    public $empty_element_suffix = " />";
52
+    public $tab_width = 4;
53 53
 	
54
-	# Change to `true` to disallow markup or entities.
55
-	public $no_markup = false;
56
-	public $no_entities = false;
54
+    # Change to `true` to disallow markup or entities.
55
+    public $no_markup = false;
56
+    public $no_entities = false;
57 57
 	
58
-	# Predefined urls and titles for reference links and images.
59
-	public $predef_urls = array();
60
-	public $predef_titles = array();
61
-
62
-	# Optional filter function for URLs
63
-	public $url_filter_func = null;
64
-
65
-	# Optional header id="" generation callback function.
66
-	public $header_id_func = null;
67
-
68
-	# Class attribute to toggle "enhanced ordered list" behaviour
69
-	# setting this to true will allow ordered lists to start from the index
70
-	# number that is defined first.  For example:
71
-	# 2. List item two
72
-	# 3. List item three
73
-	# 
74
-	# becomes
75
-	# <ol start="2">
76
-	# <li>List item two</li>
77
-	# <li>List item three</li>
78
-	# </ol>
79
-	public $enhanced_ordered_list = false;
80
-
81
-	### Parser Implementation ###
82
-
83
-	# Regex to match balanced [brackets].
84
-	# Needed to insert a maximum bracked depth while converting to PHP.
85
-	protected $nested_brackets_depth = 6;
86
-	protected $nested_brackets_re;
58
+    # Predefined urls and titles for reference links and images.
59
+    public $predef_urls = array();
60
+    public $predef_titles = array();
61
+
62
+    # Optional filter function for URLs
63
+    public $url_filter_func = null;
64
+
65
+    # Optional header id="" generation callback function.
66
+    public $header_id_func = null;
67
+
68
+    # Class attribute to toggle "enhanced ordered list" behaviour
69
+    # setting this to true will allow ordered lists to start from the index
70
+    # number that is defined first.  For example:
71
+    # 2. List item two
72
+    # 3. List item three
73
+    # 
74
+    # becomes
75
+    # <ol start="2">
76
+    # <li>List item two</li>
77
+    # <li>List item three</li>
78
+    # </ol>
79
+    public $enhanced_ordered_list = false;
80
+
81
+    ### Parser Implementation ###
82
+
83
+    # Regex to match balanced [brackets].
84
+    # Needed to insert a maximum bracked depth while converting to PHP.
85
+    protected $nested_brackets_depth = 6;
86
+    protected $nested_brackets_re;
87 87
 	
88
-	protected $nested_url_parenthesis_depth = 4;
89
-	protected $nested_url_parenthesis_re;
88
+    protected $nested_url_parenthesis_depth = 4;
89
+    protected $nested_url_parenthesis_re;
90 90
 
91
-	# Table of hash values for escaped characters:
92
-	protected $escape_chars = '\`*_{}[]()>#+-.!';
93
-	protected $escape_chars_re;
91
+    # Table of hash values for escaped characters:
92
+    protected $escape_chars = '\`*_{}[]()>#+-.!';
93
+    protected $escape_chars_re;
94 94
 
95 95
 
96
-	public function __construct() {
97
-	#
98
-	# Constructor function. Initialize appropriate member variables.
99
-	#
100
-		$this->_initDetab();
101
-		$this->prepareItalicsAndBold();
96
+    public function __construct() {
97
+    #
98
+    # Constructor function. Initialize appropriate member variables.
99
+    #
100
+        $this->_initDetab();
101
+        $this->prepareItalicsAndBold();
102 102
 	
103
-		$this->nested_brackets_re = 
104
-			str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
105
-			str_repeat('\])*', $this->nested_brackets_depth);
103
+        $this->nested_brackets_re = 
104
+            str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
105
+            str_repeat('\])*', $this->nested_brackets_depth);
106 106
 	
107
-		$this->nested_url_parenthesis_re = 
108
-			str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
109
-			str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
107
+        $this->nested_url_parenthesis_re = 
108
+            str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
109
+            str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
110 110
 		
111
-		$this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
111
+        $this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
112 112
 		
113
-		# Sort document, block, and span gamut in ascendent priority order.
114
-		asort($this->document_gamut);
115
-		asort($this->block_gamut);
116
-		asort($this->span_gamut);
117
-	}
113
+        # Sort document, block, and span gamut in ascendent priority order.
114
+        asort($this->document_gamut);
115
+        asort($this->block_gamut);
116
+        asort($this->span_gamut);
117
+    }
118 118
 
119 119
 
120
-	# Internal hashes used during transformation.
121
-	protected $urls = array();
122
-	protected $titles = array();
123
-	protected $html_hashes = array();
120
+    # Internal hashes used during transformation.
121
+    protected $urls = array();
122
+    protected $titles = array();
123
+    protected $html_hashes = array();
124 124
 	
125
-	# Status flag to avoid invalid nesting.
126
-	protected $in_anchor = false;
125
+    # Status flag to avoid invalid nesting.
126
+    protected $in_anchor = false;
127 127
 	
128 128
 	
129
-	protected function setup() {
130
-	#
131
-	# Called before the transformation process starts to setup parser 
132
-	# states.
133
-	#
134
-		# Clear global hashes.
135
-		$this->urls = $this->predef_urls;
136
-		$this->titles = $this->predef_titles;
137
-		$this->html_hashes = array();
129
+    protected function setup() {
130
+    #
131
+    # Called before the transformation process starts to setup parser 
132
+    # states.
133
+    #
134
+        # Clear global hashes.
135
+        $this->urls = $this->predef_urls;
136
+        $this->titles = $this->predef_titles;
137
+        $this->html_hashes = array();
138 138
 		
139
-		$this->in_anchor = false;
140
-	}
139
+        $this->in_anchor = false;
140
+    }
141 141
 	
142
-	protected function teardown() {
143
-	#
144
-	# Called after the transformation process to clear any variable 
145
-	# which may be taking up memory unnecessarly.
146
-	#
147
-		$this->urls = array();
148
-		$this->titles = array();
149
-		$this->html_hashes = array();
150
-	}
151
-
152
-
153
-	public function transform($text) {
154
-	#
155
-	# Main function. Performs some preprocessing on the input text
156
-	# and pass it through the document gamut.
157
-	#
158
-		$this->setup();
142
+    protected function teardown() {
143
+    #
144
+    # Called after the transformation process to clear any variable 
145
+    # which may be taking up memory unnecessarly.
146
+    #
147
+        $this->urls = array();
148
+        $this->titles = array();
149
+        $this->html_hashes = array();
150
+    }
151
+
152
+
153
+    public function transform($text) {
154
+    #
155
+    # Main function. Performs some preprocessing on the input text
156
+    # and pass it through the document gamut.
157
+    #
158
+        $this->setup();
159 159
 	
160
-		# Remove UTF-8 BOM and marker character in input, if present.
161
-		$text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
160
+        # Remove UTF-8 BOM and marker character in input, if present.
161
+        $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
162 162
 
163
-		# Standardize line endings:
164
-		#   DOS to Unix and Mac to Unix
165
-		$text = preg_replace('{\r\n?}', "\n", $text);
163
+        # Standardize line endings:
164
+        #   DOS to Unix and Mac to Unix
165
+        $text = preg_replace('{\r\n?}', "\n", $text);
166 166
 
167
-		# Make sure $text ends with a couple of newlines:
168
-		$text .= "\n\n";
167
+        # Make sure $text ends with a couple of newlines:
168
+        $text .= "\n\n";
169 169
 
170
-		# Convert all tabs to spaces.
171
-		$text = $this->detab($text);
170
+        # Convert all tabs to spaces.
171
+        $text = $this->detab($text);
172 172
 
173
-		# Turn block-level HTML blocks into hash entries
174
-		$text = $this->hashHTMLBlocks($text);
173
+        # Turn block-level HTML blocks into hash entries
174
+        $text = $this->hashHTMLBlocks($text);
175 175
 
176
-		# Strip any lines consisting only of spaces and tabs.
177
-		# This makes subsequent regexen easier to write, because we can
178
-		# match consecutive blank lines with /\n+/ instead of something
179
-		# contorted like /[ ]*\n+/ .
180
-		$text = preg_replace('/^[ ]+$/m', '', $text);
176
+        # Strip any lines consisting only of spaces and tabs.
177
+        # This makes subsequent regexen easier to write, because we can
178
+        # match consecutive blank lines with /\n+/ instead of something
179
+        # contorted like /[ ]*\n+/ .
180
+        $text = preg_replace('/^[ ]+$/m', '', $text);
181 181
 
182
-		# Run document gamut methods.
183
-		foreach ($this->document_gamut as $method => $priority) {
184
-			$text = $this->$method($text);
185
-		}
182
+        # Run document gamut methods.
183
+        foreach ($this->document_gamut as $method => $priority) {
184
+            $text = $this->$method($text);
185
+        }
186 186
 		
187
-		$this->teardown();
187
+        $this->teardown();
188 188
 
189
-		return $text . "\n";
190
-	}
189
+        return $text . "\n";
190
+    }
191 191
 	
192
-	protected $document_gamut = array(
193
-		# Strip link definitions, store in hashes.
194
-		"stripLinkDefinitions" => 20,
192
+    protected $document_gamut = array(
193
+        # Strip link definitions, store in hashes.
194
+        "stripLinkDefinitions" => 20,
195 195
 		
196
-		"runBasicBlockGamut"   => 30,
197
-		);
196
+        "runBasicBlockGamut"   => 30,
197
+        );
198 198
 
199 199
 
200
-	protected function stripLinkDefinitions($text) {
201
-	#
202
-	# Strips link definitions from text, stores the URLs and titles in
203
-	# hash references.
204
-	#
205
-		$less_than_tab = $this->tab_width - 1;
200
+    protected function stripLinkDefinitions($text) {
201
+    #
202
+    # Strips link definitions from text, stores the URLs and titles in
203
+    # hash references.
204
+    #
205
+        $less_than_tab = $this->tab_width - 1;
206 206
 
207
-		# Link defs are in the form: ^[id]: url "optional title"
208
-		$text = preg_replace_callback('{
207
+        # Link defs are in the form: ^[id]: url "optional title"
208
+        $text = preg_replace_callback('{
209 209
 							^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?:	# id = $1
210 210
 							  [ ]*
211 211
 							  \n?				# maybe *one* newline
@@ -227,46 +227,46 @@  discard block
 block discarded – undo
227 227
 							)?	# title is optional
228 228
 							(?:\n+|\Z)
229 229
 			}xm',
230
-			array($this, '_stripLinkDefinitions_callback'),
231
-			$text);
232
-		return $text;
233
-	}
234
-	protected function _stripLinkDefinitions_callback($matches) {
235
-		$link_id = strtolower($matches[1]);
236
-		$url = $matches[2] == '' ? $matches[3] : $matches[2];
237
-		$this->urls[$link_id] = $url;
238
-		$this->titles[$link_id] =& $matches[4];
239
-		return ''; # String that will replace the block
240
-	}
241
-
242
-
243
-	protected function hashHTMLBlocks($text) {
244
-		if ($this->no_markup)  return $text;
245
-
246
-		$less_than_tab = $this->tab_width - 1;
247
-
248
-		# Hashify HTML blocks:
249
-		# We only want to do this for block-level HTML tags, such as headers,
250
-		# lists, and tables. That's because we still want to wrap <p>s around
251
-		# "paragraphs" that are wrapped in non-block-level tags, such as anchors,
252
-		# phrase emphasis, and spans. The list of tags we're looking for is
253
-		# hard-coded:
254
-		#
255
-		# *  List "a" is made of tags which can be both inline or block-level.
256
-		#    These will be treated block-level when the start tag is alone on 
257
-		#    its line, otherwise they're not matched here and will be taken as 
258
-		#    inline later.
259
-		# *  List "b" is made of tags which are always block-level;
260
-		#
261
-		$block_tags_a_re = 'ins|del';
262
-		$block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
263
-						   'script|noscript|style|form|fieldset|iframe|math|svg|'.
264
-						   'article|section|nav|aside|hgroup|header|footer|'.
265
-						   'figure';
266
-
267
-		# Regular expression for the content of a block tag.
268
-		$nested_tags_level = 4;
269
-		$attr = '
230
+            array($this, '_stripLinkDefinitions_callback'),
231
+            $text);
232
+        return $text;
233
+    }
234
+    protected function _stripLinkDefinitions_callback($matches) {
235
+        $link_id = strtolower($matches[1]);
236
+        $url = $matches[2] == '' ? $matches[3] : $matches[2];
237
+        $this->urls[$link_id] = $url;
238
+        $this->titles[$link_id] =& $matches[4];
239
+        return ''; # String that will replace the block
240
+    }
241
+
242
+
243
+    protected function hashHTMLBlocks($text) {
244
+        if ($this->no_markup)  return $text;
245
+
246
+        $less_than_tab = $this->tab_width - 1;
247
+
248
+        # Hashify HTML blocks:
249
+        # We only want to do this for block-level HTML tags, such as headers,
250
+        # lists, and tables. That's because we still want to wrap <p>s around
251
+        # "paragraphs" that are wrapped in non-block-level tags, such as anchors,
252
+        # phrase emphasis, and spans. The list of tags we're looking for is
253
+        # hard-coded:
254
+        #
255
+        # *  List "a" is made of tags which can be both inline or block-level.
256
+        #    These will be treated block-level when the start tag is alone on 
257
+        #    its line, otherwise they're not matched here and will be taken as 
258
+        #    inline later.
259
+        # *  List "b" is made of tags which are always block-level;
260
+        #
261
+        $block_tags_a_re = 'ins|del';
262
+        $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
263
+                            'script|noscript|style|form|fieldset|iframe|math|svg|'.
264
+                            'article|section|nav|aside|hgroup|header|footer|'.
265
+                            'figure';
266
+
267
+        # Regular expression for the content of a block tag.
268
+        $nested_tags_level = 4;
269
+        $attr = '
270 270
 			(?>				# optional tag attributes
271 271
 			  \s			# starts with whitespace
272 272
 			  (?>
@@ -280,8 +280,8 @@  discard block
 block discarded – undo
280 280
 			  )*
281 281
 			)?	
282 282
 			';
283
-		$content =
284
-			str_repeat('
283
+        $content =
284
+            str_repeat('
285 285
 				(?>
286 286
 				  [^<]+			# content without tag
287 287
 				|
@@ -291,29 +291,29 @@  discard block
 block discarded – undo
291 291
 					  />
292 292
 					|
293 293
 					  >', $nested_tags_level).	# end of opening tag
294
-					  '.*?'.					# last level nested tag content
295
-			str_repeat('
294
+                        '.*?'.					# last level nested tag content
295
+            str_repeat('
296 296
 					  </\2\s*>	# closing nested tag
297 297
 					)
298 298
 				  |				
299 299
 					<(?!/\2\s*>	# other tags with a different name
300 300
 				  )
301 301
 				)*',
302
-				$nested_tags_level);
303
-		$content2 = str_replace('\2', '\3', $content);
304
-
305
-		# First, look for nested blocks, e.g.:
306
-		# 	<div>
307
-		# 		<div>
308
-		# 		tags for inner block must be indented.
309
-		# 		</div>
310
-		# 	</div>
311
-		#
312
-		# The outermost tags must start at the left margin for this to match, and
313
-		# the inner nested divs must be indented.
314
-		# We need to do this before the next, more liberal match, because the next
315
-		# match will start at the first `<div>` and stop at the first `</div>`.
316
-		$text = preg_replace_callback('{(?>
302
+                $nested_tags_level);
303
+        $content2 = str_replace('\2', '\3', $content);
304
+
305
+        # First, look for nested blocks, e.g.:
306
+        # 	<div>
307
+        # 		<div>
308
+        # 		tags for inner block must be indented.
309
+        # 		</div>
310
+        # 	</div>
311
+        #
312
+        # The outermost tags must start at the left margin for this to match, and
313
+        # the inner nested divs must be indented.
314
+        # We need to do this before the next, more liberal match, because the next
315
+        # match will start at the first `<div>` and stop at the first `</div>`.
316
+        $text = preg_replace_callback('{(?>
317 317
 			(?>
318 318
 				(?<=\n)			# Starting on its own line
319 319
 				|				# or
@@ -374,97 +374,97 @@  discard block
 block discarded – undo
374 374
 					
375 375
 			)
376 376
 			)}Sxmi',
377
-			array($this, '_hashHTMLBlocks_callback'),
378
-			$text);
379
-
380
-		return $text;
381
-	}
382
-	protected function _hashHTMLBlocks_callback($matches) {
383
-		$text = $matches[1];
384
-		$key  = $this->hashBlock($text);
385
-		return "\n\n$key\n\n";
386
-	}
377
+            array($this, '_hashHTMLBlocks_callback'),
378
+            $text);
379
+
380
+        return $text;
381
+    }
382
+    protected function _hashHTMLBlocks_callback($matches) {
383
+        $text = $matches[1];
384
+        $key  = $this->hashBlock($text);
385
+        return "\n\n$key\n\n";
386
+    }
387 387
 	
388 388
 	
389
-	protected function hashPart($text, $boundary = 'X') {
390
-	#
391
-	# Called whenever a tag must be hashed when a function insert an atomic 
392
-	# element in the text stream. Passing $text to through this function gives
393
-	# a unique text-token which will be reverted back when calling unhash.
394
-	#
395
-	# The $boundary argument specify what character should be used to surround
396
-	# the token. By convension, "B" is used for block elements that needs not
397
-	# to be wrapped into paragraph tags at the end, ":" is used for elements
398
-	# that are word separators and "X" is used in the general case.
399
-	#
400
-		# Swap back any tag hash found in $text so we do not have to `unhash`
401
-		# multiple times at the end.
402
-		$text = $this->unhash($text);
389
+    protected function hashPart($text, $boundary = 'X') {
390
+    #
391
+    # Called whenever a tag must be hashed when a function insert an atomic 
392
+    # element in the text stream. Passing $text to through this function gives
393
+    # a unique text-token which will be reverted back when calling unhash.
394
+    #
395
+    # The $boundary argument specify what character should be used to surround
396
+    # the token. By convension, "B" is used for block elements that needs not
397
+    # to be wrapped into paragraph tags at the end, ":" is used for elements
398
+    # that are word separators and "X" is used in the general case.
399
+    #
400
+        # Swap back any tag hash found in $text so we do not have to `unhash`
401
+        # multiple times at the end.
402
+        $text = $this->unhash($text);
403 403
 		
404
-		# Then hash the block.
405
-		static $i = 0;
406
-		$key = "$boundary\x1A" . ++$i . $boundary;
407
-		$this->html_hashes[$key] = $text;
408
-		return $key; # String that will replace the tag.
409
-	}
410
-
411
-
412
-	protected function hashBlock($text) {
413
-	#
414
-	# Shortcut function for hashPart with block-level boundaries.
415
-	#
416
-		return $this->hashPart($text, 'B');
417
-	}
418
-
419
-
420
-	protected $block_gamut = array(
421
-	#
422
-	# These are all the transformations that form block-level
423
-	# tags like paragraphs, headers, and list items.
424
-	#
425
-		"doHeaders"         => 10,
426
-		"doHorizontalRules" => 20,
404
+        # Then hash the block.
405
+        static $i = 0;
406
+        $key = "$boundary\x1A" . ++$i . $boundary;
407
+        $this->html_hashes[$key] = $text;
408
+        return $key; # String that will replace the tag.
409
+    }
410
+
411
+
412
+    protected function hashBlock($text) {
413
+    #
414
+    # Shortcut function for hashPart with block-level boundaries.
415
+    #
416
+        return $this->hashPart($text, 'B');
417
+    }
418
+
419
+
420
+    protected $block_gamut = array(
421
+    #
422
+    # These are all the transformations that form block-level
423
+    # tags like paragraphs, headers, and list items.
424
+    #
425
+        "doHeaders"         => 10,
426
+        "doHorizontalRules" => 20,
427 427
 		
428
-		"doLists"           => 40,
429
-		"doCodeBlocks"      => 50,
430
-		"doBlockQuotes"     => 60,
431
-		);
432
-
433
-	protected function runBlockGamut($text) {
434
-	#
435
-	# Run block gamut tranformations.
436
-	#
437
-		# We need to escape raw HTML in Markdown source before doing anything 
438
-		# else. This need to be done for each block, and not only at the 
439
-		# begining in the Markdown function since hashed blocks can be part of
440
-		# list items and could have been indented. Indented blocks would have 
441
-		# been seen as a code block in a previous pass of hashHTMLBlocks.
442
-		$text = $this->hashHTMLBlocks($text);
428
+        "doLists"           => 40,
429
+        "doCodeBlocks"      => 50,
430
+        "doBlockQuotes"     => 60,
431
+        );
432
+
433
+    protected function runBlockGamut($text) {
434
+    #
435
+    # Run block gamut tranformations.
436
+    #
437
+        # We need to escape raw HTML in Markdown source before doing anything 
438
+        # else. This need to be done for each block, and not only at the 
439
+        # begining in the Markdown function since hashed blocks can be part of
440
+        # list items and could have been indented. Indented blocks would have 
441
+        # been seen as a code block in a previous pass of hashHTMLBlocks.
442
+        $text = $this->hashHTMLBlocks($text);
443 443
 		
444
-		return $this->runBasicBlockGamut($text);
445
-	}
444
+        return $this->runBasicBlockGamut($text);
445
+    }
446 446
 	
447
-	protected function runBasicBlockGamut($text) {
448
-	#
449
-	# Run block gamut tranformations, without hashing HTML blocks. This is 
450
-	# useful when HTML blocks are known to be already hashed, like in the first
451
-	# whole-document pass.
452
-	#
453
-		foreach ($this->block_gamut as $method => $priority) {
454
-			$text = $this->$method($text);
455
-		}
447
+    protected function runBasicBlockGamut($text) {
448
+    #
449
+    # Run block gamut tranformations, without hashing HTML blocks. This is 
450
+    # useful when HTML blocks are known to be already hashed, like in the first
451
+    # whole-document pass.
452
+    #
453
+        foreach ($this->block_gamut as $method => $priority) {
454
+            $text = $this->$method($text);
455
+        }
456 456
 		
457
-		# Finally form paragraph and restore hashed blocks.
458
-		$text = $this->formParagraphs($text);
457
+        # Finally form paragraph and restore hashed blocks.
458
+        $text = $this->formParagraphs($text);
459 459
 
460
-		return $text;
461
-	}
460
+        return $text;
461
+    }
462 462
 	
463 463
 	
464
-	protected function doHorizontalRules($text) {
465
-		# Do Horizontal Rules:
466
-		return preg_replace(
467
-			'{
464
+    protected function doHorizontalRules($text) {
465
+        # Do Horizontal Rules:
466
+        return preg_replace(
467
+            '{
468 468
 				^[ ]{0,3}	# Leading space
469 469
 				([-*_])		# $1: First marker
470 470
 				(?>			# Repeated marker group
@@ -474,68 +474,68 @@  discard block
 block discarded – undo
474 474
 				[ ]*		# Tailing spaces
475 475
 				$			# End of line.
476 476
 			}mx',
477
-			"\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n", 
478
-			$text);
479
-	}
480
-
481
-
482
-	protected $span_gamut = array(
483
-	#
484
-	# These are all the transformations that occur *within* block-level
485
-	# tags like paragraphs, headers, and list items.
486
-	#
487
-		# Process character escapes, code spans, and inline HTML
488
-		# in one shot.
489
-		"parseSpan"           => -30,
490
-
491
-		# Process anchor and image tags. Images must come first,
492
-		# because ![foo][f] looks like an anchor.
493
-		"doImages"            =>  10,
494
-		"doAnchors"           =>  20,
477
+            "\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n", 
478
+            $text);
479
+    }
480
+
481
+
482
+    protected $span_gamut = array(
483
+    #
484
+    # These are all the transformations that occur *within* block-level
485
+    # tags like paragraphs, headers, and list items.
486
+    #
487
+        # Process character escapes, code spans, and inline HTML
488
+        # in one shot.
489
+        "parseSpan"           => -30,
490
+
491
+        # Process anchor and image tags. Images must come first,
492
+        # because ![foo][f] looks like an anchor.
493
+        "doImages"            =>  10,
494
+        "doAnchors"           =>  20,
495 495
 		
496
-		# Make links out of things like `<http://example.com/>`
497
-		# Must come after doAnchors, because you can use < and >
498
-		# delimiters in inline links like [this](<url>).
499
-		"doAutoLinks"         =>  30,
500
-		"encodeAmpsAndAngles" =>  40,
501
-
502
-		"doItalicsAndBold"    =>  50,
503
-		"doHardBreaks"        =>  60,
504
-		);
505
-
506
-	protected function runSpanGamut($text) {
507
-	#
508
-	# Run span gamut tranformations.
509
-	#
510
-		foreach ($this->span_gamut as $method => $priority) {
511
-			$text = $this->$method($text);
512
-		}
513
-
514
-		return $text;
515
-	}
496
+        # Make links out of things like `<http://example.com/>`
497
+        # Must come after doAnchors, because you can use < and >
498
+        # delimiters in inline links like [this](<url>).
499
+        "doAutoLinks"         =>  30,
500
+        "encodeAmpsAndAngles" =>  40,
501
+
502
+        "doItalicsAndBold"    =>  50,
503
+        "doHardBreaks"        =>  60,
504
+        );
505
+
506
+    protected function runSpanGamut($text) {
507
+    #
508
+    # Run span gamut tranformations.
509
+    #
510
+        foreach ($this->span_gamut as $method => $priority) {
511
+            $text = $this->$method($text);
512
+        }
513
+
514
+        return $text;
515
+    }
516 516
 	
517 517
 	
518
-	protected function doHardBreaks($text) {
519
-		# Do hard breaks:
520
-		return preg_replace_callback('/ {2,}\n/', 
521
-			array($this, '_doHardBreaks_callback'), $text);
522
-	}
523
-	protected function _doHardBreaks_callback($matches) {
524
-		return $this->hashPart("<br$this->empty_element_suffix\n");
525
-	}
526
-
527
-
528
-	protected function doAnchors($text) {
529
-	#
530
-	# Turn Markdown link shortcuts into XHTML <a> tags.
531
-	#
532
-		if ($this->in_anchor) return $text;
533
-		$this->in_anchor = true;
518
+    protected function doHardBreaks($text) {
519
+        # Do hard breaks:
520
+        return preg_replace_callback('/ {2,}\n/', 
521
+            array($this, '_doHardBreaks_callback'), $text);
522
+    }
523
+    protected function _doHardBreaks_callback($matches) {
524
+        return $this->hashPart("<br$this->empty_element_suffix\n");
525
+    }
526
+
527
+
528
+    protected function doAnchors($text) {
529
+    #
530
+    # Turn Markdown link shortcuts into XHTML <a> tags.
531
+    #
532
+        if ($this->in_anchor) return $text;
533
+        $this->in_anchor = true;
534 534
 		
535
-		#
536
-		# First, handle reference-style links: [link text] [id]
537
-		#
538
-		$text = preg_replace_callback('{
535
+        #
536
+        # First, handle reference-style links: [link text] [id]
537
+        #
538
+        $text = preg_replace_callback('{
539 539
 			(					# wrap whole match in $1
540 540
 			  \[
541 541
 				('.$this->nested_brackets_re.')	# link text = $2
@@ -549,12 +549,12 @@  discard block
 block discarded – undo
549 549
 			  \]
550 550
 			)
551 551
 			}xs',
552
-			array($this, '_doAnchors_reference_callback'), $text);
552
+            array($this, '_doAnchors_reference_callback'), $text);
553 553
 
554
-		#
555
-		# Next, inline-style links: [link text](url "optional title")
556
-		#
557
-		$text = preg_replace_callback('{
554
+        #
555
+        # Next, inline-style links: [link text](url "optional title")
556
+        #
557
+        $text = preg_replace_callback('{
558 558
 			(				# wrap whole match in $1
559 559
 			  \[
560 560
 				('.$this->nested_brackets_re.')	# link text = $2
@@ -576,94 +576,94 @@  discard block
 block discarded – undo
576 576
 			  \)
577 577
 			)
578 578
 			}xs',
579
-			array($this, '_doAnchors_inline_callback'), $text);
580
-
581
-		#
582
-		# Last, handle reference-style shortcuts: [link text]
583
-		# These must come last in case you've also got [link text][1]
584
-		# or [link text](/foo)
585
-		#
586
-		$text = preg_replace_callback('{
579
+            array($this, '_doAnchors_inline_callback'), $text);
580
+
581
+        #
582
+        # Last, handle reference-style shortcuts: [link text]
583
+        # These must come last in case you've also got [link text][1]
584
+        # or [link text](/foo)
585
+        #
586
+        $text = preg_replace_callback('{
587 587
 			(					# wrap whole match in $1
588 588
 			  \[
589 589
 				([^\[\]]+)		# link text = $2; can\'t contain [ or ]
590 590
 			  \]
591 591
 			)
592 592
 			}xs',
593
-			array($this, '_doAnchors_reference_callback'), $text);
594
-
595
-		$this->in_anchor = false;
596
-		return $text;
597
-	}
598
-	protected function _doAnchors_reference_callback($matches) {
599
-		$whole_match =  $matches[1];
600
-		$link_text   =  $matches[2];
601
-		$link_id     =& $matches[3];
602
-
603
-		if ($link_id == "") {
604
-			# for shortcut links like [this][] or [this].
605
-			$link_id = $link_text;
606
-		}
593
+            array($this, '_doAnchors_reference_callback'), $text);
594
+
595
+        $this->in_anchor = false;
596
+        return $text;
597
+    }
598
+    protected function _doAnchors_reference_callback($matches) {
599
+        $whole_match =  $matches[1];
600
+        $link_text   =  $matches[2];
601
+        $link_id     =& $matches[3];
602
+
603
+        if ($link_id == "") {
604
+            # for shortcut links like [this][] or [this].
605
+            $link_id = $link_text;
606
+        }
607 607
 		
608
-		# lower-case and turn embedded newlines into spaces
609
-		$link_id = strtolower($link_id);
610
-		$link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
608
+        # lower-case and turn embedded newlines into spaces
609
+        $link_id = strtolower($link_id);
610
+        $link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
611 611
 
612
-		if (isset($this->urls[$link_id])) {
613
-			$url = $this->urls[$link_id];
614
-			$url = $this->encodeURLAttribute($url);
612
+        if (isset($this->urls[$link_id])) {
613
+            $url = $this->urls[$link_id];
614
+            $url = $this->encodeURLAttribute($url);
615 615
 			
616
-			$result = "<a href=\"$url\"";
617
-			if ( isset( $this->titles[$link_id] ) ) {
618
-				$title = $this->titles[$link_id];
619
-				$title = $this->encodeAttribute($title);
620
-				$result .=  " title=\"$title\"";
621
-			}
616
+            $result = "<a href=\"$url\"";
617
+            if ( isset( $this->titles[$link_id] ) ) {
618
+                $title = $this->titles[$link_id];
619
+                $title = $this->encodeAttribute($title);
620
+                $result .=  " title=\"$title\"";
621
+            }
622 622
 		
623
-			$link_text = $this->runSpanGamut($link_text);
624
-			$result .= ">$link_text</a>";
625
-			$result = $this->hashPart($result);
626
-		}
627
-		else {
628
-			$result = $whole_match;
629
-		}
630
-		return $result;
631
-	}
632
-	protected function _doAnchors_inline_callback($matches) {
633
-		$whole_match	=  $matches[1];
634
-		$link_text		=  $this->runSpanGamut($matches[2]);
635
-		$url			=  $matches[3] == '' ? $matches[4] : $matches[3];
636
-		$title			=& $matches[7];
637
-
638
-		// if the URL was of the form <s p a c e s> it got caught by the HTML
639
-		// tag parser and hashed. Need to reverse the process before using the URL.
640
-		$unhashed = $this->unhash($url);
641
-		if ($unhashed != $url)
642
-			$url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
643
-
644
-		$url = $this->encodeURLAttribute($url);
645
-
646
-		$result = "<a href=\"$url\"";
647
-		if (isset($title)) {
648
-			$title = $this->encodeAttribute($title);
649
-			$result .=  " title=\"$title\"";
650
-		}
623
+            $link_text = $this->runSpanGamut($link_text);
624
+            $result .= ">$link_text</a>";
625
+            $result = $this->hashPart($result);
626
+        }
627
+        else {
628
+            $result = $whole_match;
629
+        }
630
+        return $result;
631
+    }
632
+    protected function _doAnchors_inline_callback($matches) {
633
+        $whole_match	=  $matches[1];
634
+        $link_text		=  $this->runSpanGamut($matches[2]);
635
+        $url			=  $matches[3] == '' ? $matches[4] : $matches[3];
636
+        $title			=& $matches[7];
637
+
638
+        // if the URL was of the form <s p a c e s> it got caught by the HTML
639
+        // tag parser and hashed. Need to reverse the process before using the URL.
640
+        $unhashed = $this->unhash($url);
641
+        if ($unhashed != $url)
642
+            $url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
643
+
644
+        $url = $this->encodeURLAttribute($url);
645
+
646
+        $result = "<a href=\"$url\"";
647
+        if (isset($title)) {
648
+            $title = $this->encodeAttribute($title);
649
+            $result .=  " title=\"$title\"";
650
+        }
651 651
 		
652
-		$link_text = $this->runSpanGamut($link_text);
653
-		$result .= ">$link_text</a>";
652
+        $link_text = $this->runSpanGamut($link_text);
653
+        $result .= ">$link_text</a>";
654 654
 
655
-		return $this->hashPart($result);
656
-	}
655
+        return $this->hashPart($result);
656
+    }
657 657
 
658 658
 
659
-	protected function doImages($text) {
660
-	#
661
-	# Turn Markdown image shortcuts into <img> tags.
662
-	#
663
-		#
664
-		# First, handle reference-style labeled images: ![alt text][id]
665
-		#
666
-		$text = preg_replace_callback('{
659
+    protected function doImages($text) {
660
+    #
661
+    # Turn Markdown image shortcuts into <img> tags.
662
+    #
663
+        #
664
+        # First, handle reference-style labeled images: ![alt text][id]
665
+        #
666
+        $text = preg_replace_callback('{
667 667
 			(				# wrap whole match in $1
668 668
 			  !\[
669 669
 				('.$this->nested_brackets_re.')		# alt text = $2
@@ -678,13 +678,13 @@  discard block
 block discarded – undo
678 678
 
679 679
 			)
680 680
 			}xs', 
681
-			array($this, '_doImages_reference_callback'), $text);
681
+            array($this, '_doImages_reference_callback'), $text);
682 682
 
683
-		#
684
-		# Next, handle inline images:  ![alt text](url "optional title")
685
-		# Don't forget: encode * and _
686
-		#
687
-		$text = preg_replace_callback('{
683
+        #
684
+        # Next, handle inline images:  ![alt text](url "optional title")
685
+        # Don't forget: encode * and _
686
+        #
687
+        $text = preg_replace_callback('{
688 688
 			(				# wrap whole match in $1
689 689
 			  !\[
690 690
 				('.$this->nested_brackets_re.')		# alt text = $2
@@ -707,76 +707,76 @@  discard block
 block discarded – undo
707 707
 			  \)
708 708
 			)
709 709
 			}xs',
710
-			array($this, '_doImages_inline_callback'), $text);
711
-
712
-		return $text;
713
-	}
714
-	protected function _doImages_reference_callback($matches) {
715
-		$whole_match = $matches[1];
716
-		$alt_text    = $matches[2];
717
-		$link_id     = strtolower($matches[3]);
718
-
719
-		if ($link_id == "") {
720
-			$link_id = strtolower($alt_text); # for shortcut links like ![this][].
721
-		}
722
-
723
-		$alt_text = $this->encodeAttribute($alt_text);
724
-		if (isset($this->urls[$link_id])) {
725
-			$url = $this->encodeURLAttribute($this->urls[$link_id]);
726
-			$result = "<img src=\"$url\" alt=\"$alt_text\"";
727
-			if (isset($this->titles[$link_id])) {
728
-				$title = $this->titles[$link_id];
729
-				$title = $this->encodeAttribute($title);
730
-				$result .=  " title=\"$title\"";
731
-			}
732
-			$result .= $this->empty_element_suffix;
733
-			$result = $this->hashPart($result);
734
-		}
735
-		else {
736
-			# If there's no such link ID, leave intact:
737
-			$result = $whole_match;
738
-		}
739
-
740
-		return $result;
741
-	}
742
-	protected function _doImages_inline_callback($matches) {
743
-		$whole_match	= $matches[1];
744
-		$alt_text		= $matches[2];
745
-		$url			= $matches[3] == '' ? $matches[4] : $matches[3];
746
-		$title			=& $matches[7];
747
-
748
-		$alt_text = $this->encodeAttribute($alt_text);
749
-		$url = $this->encodeURLAttribute($url);
750
-		$result = "<img src=\"$url\" alt=\"$alt_text\"";
751
-		if (isset($title)) {
752
-			$title = $this->encodeAttribute($title);
753
-			$result .=  " title=\"$title\""; # $title already quoted
754
-		}
755
-		$result .= $this->empty_element_suffix;
756
-
757
-		return $this->hashPart($result);
758
-	}
759
-
760
-
761
-	protected function doHeaders($text) {
762
-		# Setext-style headers:
763
-		#	  Header 1
764
-		#	  ========
765
-		#  
766
-		#	  Header 2
767
-		#	  --------
768
-		#
769
-		$text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx',
770
-			array($this, '_doHeaders_callback_setext'), $text);
771
-
772
-		# atx-style headers:
773
-		#	# Header 1
774
-		#	## Header 2
775
-		#	## Header 2 with closing hashes ##
776
-		#	...
777
-		#	###### Header 6
778
-		#
779
-		$text = preg_replace_callback('{
710
+            array($this, '_doImages_inline_callback'), $text);
711
+
712
+        return $text;
713
+    }
714
+    protected function _doImages_reference_callback($matches) {
715
+        $whole_match = $matches[1];
716
+        $alt_text    = $matches[2];
717
+        $link_id     = strtolower($matches[3]);
718
+
719
+        if ($link_id == "") {
720
+            $link_id = strtolower($alt_text); # for shortcut links like ![this][].
721
+        }
722
+
723
+        $alt_text = $this->encodeAttribute($alt_text);
724
+        if (isset($this->urls[$link_id])) {
725
+            $url = $this->encodeURLAttribute($this->urls[$link_id]);
726
+            $result = "<img src=\"$url\" alt=\"$alt_text\"";
727
+            if (isset($this->titles[$link_id])) {
728
+                $title = $this->titles[$link_id];
729
+                $title = $this->encodeAttribute($title);
730
+                $result .=  " title=\"$title\"";
731
+            }
732
+            $result .= $this->empty_element_suffix;
733
+            $result = $this->hashPart($result);
734
+        }
735
+        else {
736
+            # If there's no such link ID, leave intact:
737
+            $result = $whole_match;
738
+        }
739
+
740
+        return $result;
741
+    }
742
+    protected function _doImages_inline_callback($matches) {
743
+        $whole_match	= $matches[1];
744
+        $alt_text		= $matches[2];
745
+        $url			= $matches[3] == '' ? $matches[4] : $matches[3];
746
+        $title			=& $matches[7];
747
+
748
+        $alt_text = $this->encodeAttribute($alt_text);
749
+        $url = $this->encodeURLAttribute($url);
750
+        $result = "<img src=\"$url\" alt=\"$alt_text\"";
751
+        if (isset($title)) {
752
+            $title = $this->encodeAttribute($title);
753
+            $result .=  " title=\"$title\""; # $title already quoted
754
+        }
755
+        $result .= $this->empty_element_suffix;
756
+
757
+        return $this->hashPart($result);
758
+    }
759
+
760
+
761
+    protected function doHeaders($text) {
762
+        # Setext-style headers:
763
+        #	  Header 1
764
+        #	  ========
765
+        #  
766
+        #	  Header 2
767
+        #	  --------
768
+        #
769
+        $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx',
770
+            array($this, '_doHeaders_callback_setext'), $text);
771
+
772
+        # atx-style headers:
773
+        #	# Header 1
774
+        #	## Header 2
775
+        #	## Header 2 with closing hashes ##
776
+        #	...
777
+        #	###### Header 6
778
+        #
779
+        $text = preg_replace_callback('{
780 780
 				^(\#{1,6})	# $1 = string of #\'s
781 781
 				[ ]*
782 782
 				(.+?)		# $2 = Header text
@@ -784,69 +784,69 @@  discard block
 block discarded – undo
784 784
 				\#*			# optional closing #\'s (not counted)
785 785
 				\n+
786 786
 			}xm',
787
-			array($this, '_doHeaders_callback_atx'), $text);
787
+            array($this, '_doHeaders_callback_atx'), $text);
788 788
 
789
-		return $text;
790
-	}
789
+        return $text;
790
+    }
791 791
 
792
-	protected function _doHeaders_callback_setext($matches) {
793
-		# Terrible hack to check we haven't found an empty list item.
794
-		if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1]))
795
-			return $matches[0];
792
+    protected function _doHeaders_callback_setext($matches) {
793
+        # Terrible hack to check we haven't found an empty list item.
794
+        if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1]))
795
+            return $matches[0];
796 796
 		
797
-		$level = $matches[2]{0} == '=' ? 1 : 2;
798
-
799
-		# id attribute generation
800
-		$idAtt = $this->_generateIdFromHeaderValue($matches[1]);
801
-
802
-		$block = "<h$level$idAtt>".$this->runSpanGamut($matches[1])."</h$level>";
803
-		return "\n" . $this->hashBlock($block) . "\n\n";
804
-	}
805
-	protected function _doHeaders_callback_atx($matches) {
806
-
807
-		# id attribute generation
808
-		$idAtt = $this->_generateIdFromHeaderValue($matches[2]);
809
-
810
-		$level = strlen($matches[1]);
811
-		$block = "<h$level$idAtt>".$this->runSpanGamut($matches[2])."</h$level>";
812
-		return "\n" . $this->hashBlock($block) . "\n\n";
813
-	}
814
-
815
-	protected function _generateIdFromHeaderValue($headerValue) {
816
-
817
-		# if a header_id_func property is set, we can use it to automatically
818
-		# generate an id attribute.
819
-		#
820
-		# This method returns a string in the form id="foo", or an empty string
821
-		# otherwise.
822
-		if (!is_callable($this->header_id_func)) {
823
-			return "";
824
-		}
825
-		$idValue = call_user_func($this->header_id_func, $headerValue);
826
-		if (!$idValue) return "";
827
-
828
-		return ' id="' . $this->encodeAttribute($idValue) . '"';
829
-
830
-	}
831
-
832
-	protected function doLists($text) {
833
-	#
834
-	# Form HTML ordered (numbered) and unordered (bulleted) lists.
835
-	#
836
-		$less_than_tab = $this->tab_width - 1;
837
-
838
-		# Re-usable patterns to match list item bullets and number markers:
839
-		$marker_ul_re  = '[*+-]';
840
-		$marker_ol_re  = '\d+[\.]';
841
-
842
-		$markers_relist = array(
843
-			$marker_ul_re => $marker_ol_re,
844
-			$marker_ol_re => $marker_ul_re,
845
-			);
846
-
847
-		foreach ($markers_relist as $marker_re => $other_marker_re) {
848
-			# Re-usable pattern to match any entirel ul or ol list:
849
-			$whole_list_re = '
797
+        $level = $matches[2]{0} == '=' ? 1 : 2;
798
+
799
+        # id attribute generation
800
+        $idAtt = $this->_generateIdFromHeaderValue($matches[1]);
801
+
802
+        $block = "<h$level$idAtt>".$this->runSpanGamut($matches[1])."</h$level>";
803
+        return "\n" . $this->hashBlock($block) . "\n\n";
804
+    }
805
+    protected function _doHeaders_callback_atx($matches) {
806
+
807
+        # id attribute generation
808
+        $idAtt = $this->_generateIdFromHeaderValue($matches[2]);
809
+
810
+        $level = strlen($matches[1]);
811
+        $block = "<h$level$idAtt>".$this->runSpanGamut($matches[2])."</h$level>";
812
+        return "\n" . $this->hashBlock($block) . "\n\n";
813
+    }
814
+
815
+    protected function _generateIdFromHeaderValue($headerValue) {
816
+
817
+        # if a header_id_func property is set, we can use it to automatically
818
+        # generate an id attribute.
819
+        #
820
+        # This method returns a string in the form id="foo", or an empty string
821
+        # otherwise.
822
+        if (!is_callable($this->header_id_func)) {
823
+            return "";
824
+        }
825
+        $idValue = call_user_func($this->header_id_func, $headerValue);
826
+        if (!$idValue) return "";
827
+
828
+        return ' id="' . $this->encodeAttribute($idValue) . '"';
829
+
830
+    }
831
+
832
+    protected function doLists($text) {
833
+    #
834
+    # Form HTML ordered (numbered) and unordered (bulleted) lists.
835
+    #
836
+        $less_than_tab = $this->tab_width - 1;
837
+
838
+        # Re-usable patterns to match list item bullets and number markers:
839
+        $marker_ul_re  = '[*+-]';
840
+        $marker_ol_re  = '\d+[\.]';
841
+
842
+        $markers_relist = array(
843
+            $marker_ul_re => $marker_ol_re,
844
+            $marker_ol_re => $marker_ul_re,
845
+            );
846
+
847
+        foreach ($markers_relist as $marker_re => $other_marker_re) {
848
+            # Re-usable pattern to match any entirel ul or ol list:
849
+            $whole_list_re = '
850 850
 				(								# $1 = whole list
851 851
 				  (								# $2
852 852
 					([ ]{0,'.$less_than_tab.'})	# $3 = number of spaces
@@ -873,96 +873,96 @@  discard block
 block discarded – undo
873 873
 				)
874 874
 			'; // mx
875 875
 			
876
-			# We use a different prefix before nested lists than top-level lists.
877
-			# See extended comment in _ProcessListItems().
876
+            # We use a different prefix before nested lists than top-level lists.
877
+            # See extended comment in _ProcessListItems().
878 878
 		
879
-			if ($this->list_level) {
880
-				$text = preg_replace_callback('{
879
+            if ($this->list_level) {
880
+                $text = preg_replace_callback('{
881 881
 						^
882 882
 						'.$whole_list_re.'
883 883
 					}mx',
884
-					array($this, '_doLists_callback'), $text);
885
-			}
886
-			else {
887
-				$text = preg_replace_callback('{
884
+                    array($this, '_doLists_callback'), $text);
885
+            }
886
+            else {
887
+                $text = preg_replace_callback('{
888 888
 						(?:(?<=\n)\n|\A\n?) # Must eat the newline
889 889
 						'.$whole_list_re.'
890 890
 					}mx',
891
-					array($this, '_doLists_callback'), $text);
892
-			}
893
-		}
894
-
895
-		return $text;
896
-	}
897
-	protected function _doLists_callback($matches) {
898
-		# Re-usable patterns to match list item bullets and number markers:
899
-		$marker_ul_re  = '[*+-]';
900
-		$marker_ol_re  = '\d+[\.]';
901
-		$marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
902
-		$marker_ol_start_re = '[0-9]+';
903
-
904
-		$list = $matches[1];
905
-		$list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol";
906
-
907
-		$marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
908
-
909
-		$list .= "\n";
910
-		$result = $this->processListItems($list, $marker_any_re);
911
-
912
-		$ol_start = 1;
913
-		if ($this->enhanced_ordered_list) {
914
-			# Get the start number for ordered list.
915
-			if ($list_type == 'ol') {
916
-				$ol_start_array = array();
917
-				$ol_start_check = preg_match("/$marker_ol_start_re/", $matches[4], $ol_start_array);
918
-				if ($ol_start_check){
919
-					$ol_start = $ol_start_array[0];
920
-				}
921
-			}
922
-		}
923
-
924
-		if ($ol_start > 1 && $list_type == 'ol'){
925
-			$result = $this->hashBlock("<$list_type start=\"$ol_start\">\n" . $result . "</$list_type>");
926
-		} else {
927
-			$result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
928
-		}
929
-		return "\n". $result ."\n\n";
930
-	}
931
-
932
-	protected $list_level = 0;
933
-
934
-	protected function processListItems($list_str, $marker_any_re) {
935
-	#
936
-	#	Process the contents of a single ordered or unordered list, splitting it
937
-	#	into individual list items.
938
-	#
939
-		# The $this->list_level global keeps track of when we're inside a list.
940
-		# Each time we enter a list, we increment it; when we leave a list,
941
-		# we decrement. If it's zero, we're not in a list anymore.
942
-		#
943
-		# We do this because when we're not inside a list, we want to treat
944
-		# something like this:
945
-		#
946
-		#		I recommend upgrading to version
947
-		#		8. Oops, now this line is treated
948
-		#		as a sub-list.
949
-		#
950
-		# As a single paragraph, despite the fact that the second line starts
951
-		# with a digit-period-space sequence.
952
-		#
953
-		# Whereas when we're inside a list (or sub-list), that line will be
954
-		# treated as the start of a sub-list. What a kludge, huh? This is
955
-		# an aspect of Markdown's syntax that's hard to parse perfectly
956
-		# without resorting to mind-reading. Perhaps the solution is to
957
-		# change the syntax rules such that sub-lists must start with a
958
-		# starting cardinal number; e.g. "1." or "a.".
891
+                    array($this, '_doLists_callback'), $text);
892
+            }
893
+        }
894
+
895
+        return $text;
896
+    }
897
+    protected function _doLists_callback($matches) {
898
+        # Re-usable patterns to match list item bullets and number markers:
899
+        $marker_ul_re  = '[*+-]';
900
+        $marker_ol_re  = '\d+[\.]';
901
+        $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
902
+        $marker_ol_start_re = '[0-9]+';
903
+
904
+        $list = $matches[1];
905
+        $list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol";
906
+
907
+        $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
908
+
909
+        $list .= "\n";
910
+        $result = $this->processListItems($list, $marker_any_re);
911
+
912
+        $ol_start = 1;
913
+        if ($this->enhanced_ordered_list) {
914
+            # Get the start number for ordered list.
915
+            if ($list_type == 'ol') {
916
+                $ol_start_array = array();
917
+                $ol_start_check = preg_match("/$marker_ol_start_re/", $matches[4], $ol_start_array);
918
+                if ($ol_start_check){
919
+                    $ol_start = $ol_start_array[0];
920
+                }
921
+            }
922
+        }
923
+
924
+        if ($ol_start > 1 && $list_type == 'ol'){
925
+            $result = $this->hashBlock("<$list_type start=\"$ol_start\">\n" . $result . "</$list_type>");
926
+        } else {
927
+            $result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
928
+        }
929
+        return "\n". $result ."\n\n";
930
+    }
931
+
932
+    protected $list_level = 0;
933
+
934
+    protected function processListItems($list_str, $marker_any_re) {
935
+    #
936
+    #	Process the contents of a single ordered or unordered list, splitting it
937
+    #	into individual list items.
938
+    #
939
+        # The $this->list_level global keeps track of when we're inside a list.
940
+        # Each time we enter a list, we increment it; when we leave a list,
941
+        # we decrement. If it's zero, we're not in a list anymore.
942
+        #
943
+        # We do this because when we're not inside a list, we want to treat
944
+        # something like this:
945
+        #
946
+        #		I recommend upgrading to version
947
+        #		8. Oops, now this line is treated
948
+        #		as a sub-list.
949
+        #
950
+        # As a single paragraph, despite the fact that the second line starts
951
+        # with a digit-period-space sequence.
952
+        #
953
+        # Whereas when we're inside a list (or sub-list), that line will be
954
+        # treated as the start of a sub-list. What a kludge, huh? This is
955
+        # an aspect of Markdown's syntax that's hard to parse perfectly
956
+        # without resorting to mind-reading. Perhaps the solution is to
957
+        # change the syntax rules such that sub-lists must start with a
958
+        # starting cardinal number; e.g. "1." or "a.".
959 959
 		
960
-		$this->list_level++;
960
+        $this->list_level++;
961 961
 
962
-		# trim trailing blank lines:
963
-		$list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
962
+        # trim trailing blank lines:
963
+        $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
964 964
 
965
-		$list_str = preg_replace_callback('{
965
+        $list_str = preg_replace_callback('{
966 966
 			(\n)?							# leading line = $1
967 967
 			(^[ ]*)							# leading whitespace = $2
968 968
 			('.$marker_any_re.'				# list marker and space = $3
@@ -972,41 +972,41 @@  discard block
 block discarded – undo
972 972
 			(?:(\n+(?=\n))|\n)				# tailing blank line = $5
973 973
 			(?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n))))
974 974
 			}xm',
975
-			array($this, '_processListItems_callback'), $list_str);
976
-
977
-		$this->list_level--;
978
-		return $list_str;
979
-	}
980
-	protected function _processListItems_callback($matches) {
981
-		$item = $matches[4];
982
-		$leading_line =& $matches[1];
983
-		$leading_space =& $matches[2];
984
-		$marker_space = $matches[3];
985
-		$tailing_blank_line =& $matches[5];
986
-
987
-		if ($leading_line || $tailing_blank_line || 
988
-			preg_match('/\n{2,}/', $item))
989
-		{
990
-			# Replace marker with the appropriate whitespace indentation
991
-			$item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
992
-			$item = $this->runBlockGamut($this->outdent($item)."\n");
993
-		}
994
-		else {
995
-			# Recursion for sub-lists:
996
-			$item = $this->doLists($this->outdent($item));
997
-			$item = preg_replace('/\n+$/', '', $item);
998
-			$item = $this->runSpanGamut($item);
999
-		}
1000
-
1001
-		return "<li>" . $item . "</li>\n";
1002
-	}
1003
-
1004
-
1005
-	protected function doCodeBlocks($text) {
1006
-	#
1007
-	#	Process Markdown `<pre><code>` blocks.
1008
-	#
1009
-		$text = preg_replace_callback('{
975
+            array($this, '_processListItems_callback'), $list_str);
976
+
977
+        $this->list_level--;
978
+        return $list_str;
979
+    }
980
+    protected function _processListItems_callback($matches) {
981
+        $item = $matches[4];
982
+        $leading_line =& $matches[1];
983
+        $leading_space =& $matches[2];
984
+        $marker_space = $matches[3];
985
+        $tailing_blank_line =& $matches[5];
986
+
987
+        if ($leading_line || $tailing_blank_line || 
988
+            preg_match('/\n{2,}/', $item))
989
+        {
990
+            # Replace marker with the appropriate whitespace indentation
991
+            $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
992
+            $item = $this->runBlockGamut($this->outdent($item)."\n");
993
+        }
994
+        else {
995
+            # Recursion for sub-lists:
996
+            $item = $this->doLists($this->outdent($item));
997
+            $item = preg_replace('/\n+$/', '', $item);
998
+            $item = $this->runSpanGamut($item);
999
+        }
1000
+
1001
+        return "<li>" . $item . "</li>\n";
1002
+    }
1003
+
1004
+
1005
+    protected function doCodeBlocks($text) {
1006
+    #
1007
+    #	Process Markdown `<pre><code>` blocks.
1008
+    #
1009
+        $text = preg_replace_callback('{
1010 1010
 				(?:\n\n|\A\n?)
1011 1011
 				(	            # $1 = the code block -- one or more lines, starting with a space/tab
1012 1012
 				  (?>
@@ -1016,197 +1016,197 @@  discard block
 block discarded – undo
1016 1016
 				)
1017 1017
 				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
1018 1018
 			}xm',
1019
-			array($this, '_doCodeBlocks_callback'), $text);
1020
-
1021
-		return $text;
1022
-	}
1023
-	protected function _doCodeBlocks_callback($matches) {
1024
-		$codeblock = $matches[1];
1025
-
1026
-		$codeblock = $this->outdent($codeblock);
1027
-		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
1028
-
1029
-		# trim leading newlines and trailing newlines
1030
-		$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
1031
-
1032
-		$codeblock = "<pre><code>$codeblock\n</code></pre>";
1033
-		return "\n\n".$this->hashBlock($codeblock)."\n\n";
1034
-	}
1035
-
1036
-
1037
-	protected function makeCodeSpan($code) {
1038
-	#
1039
-	# Create a code span markup for $code. Called from handleSpanToken.
1040
-	#
1041
-		$code = htmlspecialchars(trim($code), ENT_NOQUOTES);
1042
-		return $this->hashPart("<code>$code</code>");
1043
-	}
1044
-
1045
-
1046
-	protected $em_relist = array(
1047
-		''  => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?![\.,:;]?\s)',
1048
-		'*' => '(?<![\s*])\*(?!\*)',
1049
-		'_' => '(?<![\s_])_(?!_)',
1050
-		);
1051
-	protected $strong_relist = array(
1052
-		''   => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?![\.,:;]?\s)',
1053
-		'**' => '(?<![\s*])\*\*(?!\*)',
1054
-		'__' => '(?<![\s_])__(?!_)',
1055
-		);
1056
-	protected $em_strong_relist = array(
1057
-		''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?![\.,:;]?\s)',
1058
-		'***' => '(?<![\s*])\*\*\*(?!\*)',
1059
-		'___' => '(?<![\s_])___(?!_)',
1060
-		);
1061
-	protected $em_strong_prepared_relist;
1019
+            array($this, '_doCodeBlocks_callback'), $text);
1020
+
1021
+        return $text;
1022
+    }
1023
+    protected function _doCodeBlocks_callback($matches) {
1024
+        $codeblock = $matches[1];
1025
+
1026
+        $codeblock = $this->outdent($codeblock);
1027
+        $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
1028
+
1029
+        # trim leading newlines and trailing newlines
1030
+        $codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
1031
+
1032
+        $codeblock = "<pre><code>$codeblock\n</code></pre>";
1033
+        return "\n\n".$this->hashBlock($codeblock)."\n\n";
1034
+    }
1035
+
1036
+
1037
+    protected function makeCodeSpan($code) {
1038
+    #
1039
+    # Create a code span markup for $code. Called from handleSpanToken.
1040
+    #
1041
+        $code = htmlspecialchars(trim($code), ENT_NOQUOTES);
1042
+        return $this->hashPart("<code>$code</code>");
1043
+    }
1044
+
1045
+
1046
+    protected $em_relist = array(
1047
+        ''  => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?![\.,:;]?\s)',
1048
+        '*' => '(?<![\s*])\*(?!\*)',
1049
+        '_' => '(?<![\s_])_(?!_)',
1050
+        );
1051
+    protected $strong_relist = array(
1052
+        ''   => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?![\.,:;]?\s)',
1053
+        '**' => '(?<![\s*])\*\*(?!\*)',
1054
+        '__' => '(?<![\s_])__(?!_)',
1055
+        );
1056
+    protected $em_strong_relist = array(
1057
+        ''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?![\.,:;]?\s)',
1058
+        '***' => '(?<![\s*])\*\*\*(?!\*)',
1059
+        '___' => '(?<![\s_])___(?!_)',
1060
+        );
1061
+    protected $em_strong_prepared_relist;
1062 1062
 	
1063
-	protected function prepareItalicsAndBold() {
1064
-	#
1065
-	# Prepare regular expressions for searching emphasis tokens in any
1066
-	# context.
1067
-	#
1068
-		foreach ($this->em_relist as $em => $em_re) {
1069
-			foreach ($this->strong_relist as $strong => $strong_re) {
1070
-				# Construct list of allowed token expressions.
1071
-				$token_relist = array();
1072
-				if (isset($this->em_strong_relist["$em$strong"])) {
1073
-					$token_relist[] = $this->em_strong_relist["$em$strong"];
1074
-				}
1075
-				$token_relist[] = $em_re;
1076
-				$token_relist[] = $strong_re;
1063
+    protected function prepareItalicsAndBold() {
1064
+    #
1065
+    # Prepare regular expressions for searching emphasis tokens in any
1066
+    # context.
1067
+    #
1068
+        foreach ($this->em_relist as $em => $em_re) {
1069
+            foreach ($this->strong_relist as $strong => $strong_re) {
1070
+                # Construct list of allowed token expressions.
1071
+                $token_relist = array();
1072
+                if (isset($this->em_strong_relist["$em$strong"])) {
1073
+                    $token_relist[] = $this->em_strong_relist["$em$strong"];
1074
+                }
1075
+                $token_relist[] = $em_re;
1076
+                $token_relist[] = $strong_re;
1077 1077
 				
1078
-				# Construct master expression from list.
1079
-				$token_re = '{('. implode('|', $token_relist) .')}';
1080
-				$this->em_strong_prepared_relist["$em$strong"] = $token_re;
1081
-			}
1082
-		}
1083
-	}
1078
+                # Construct master expression from list.
1079
+                $token_re = '{('. implode('|', $token_relist) .')}';
1080
+                $this->em_strong_prepared_relist["$em$strong"] = $token_re;
1081
+            }
1082
+        }
1083
+    }
1084 1084
 	
1085
-	protected function doItalicsAndBold($text) {
1086
-		$token_stack = array('');
1087
-		$text_stack = array('');
1088
-		$em = '';
1089
-		$strong = '';
1090
-		$tree_char_em = false;
1085
+    protected function doItalicsAndBold($text) {
1086
+        $token_stack = array('');
1087
+        $text_stack = array('');
1088
+        $em = '';
1089
+        $strong = '';
1090
+        $tree_char_em = false;
1091 1091
 		
1092
-		while (1) {
1093
-			#
1094
-			# Get prepared regular expression for seraching emphasis tokens
1095
-			# in current context.
1096
-			#
1097
-			$token_re = $this->em_strong_prepared_relist["$em$strong"];
1092
+        while (1) {
1093
+            #
1094
+            # Get prepared regular expression for seraching emphasis tokens
1095
+            # in current context.
1096
+            #
1097
+            $token_re = $this->em_strong_prepared_relist["$em$strong"];
1098 1098
 			
1099
-			#
1100
-			# Each loop iteration search for the next emphasis token. 
1101
-			# Each token is then passed to handleSpanToken.
1102
-			#
1103
-			$parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
1104
-			$text_stack[0] .= $parts[0];
1105
-			$token =& $parts[1];
1106
-			$text =& $parts[2];
1099
+            #
1100
+            # Each loop iteration search for the next emphasis token. 
1101
+            # Each token is then passed to handleSpanToken.
1102
+            #
1103
+            $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
1104
+            $text_stack[0] .= $parts[0];
1105
+            $token =& $parts[1];
1106
+            $text =& $parts[2];
1107 1107
 			
1108
-			if (empty($token)) {
1109
-				# Reached end of text span: empty stack without emitting.
1110
-				# any more emphasis.
1111
-				while ($token_stack[0]) {
1112
-					$text_stack[1] .= array_shift($token_stack);
1113
-					$text_stack[0] .= array_shift($text_stack);
1114
-				}
1115
-				break;
1116
-			}
1108
+            if (empty($token)) {
1109
+                # Reached end of text span: empty stack without emitting.
1110
+                # any more emphasis.
1111
+                while ($token_stack[0]) {
1112
+                    $text_stack[1] .= array_shift($token_stack);
1113
+                    $text_stack[0] .= array_shift($text_stack);
1114
+                }
1115
+                break;
1116
+            }
1117 1117
 			
1118
-			$token_len = strlen($token);
1119
-			if ($tree_char_em) {
1120
-				# Reached closing marker while inside a three-char emphasis.
1121
-				if ($token_len == 3) {
1122
-					# Three-char closing marker, close em and strong.
1123
-					array_shift($token_stack);
1124
-					$span = array_shift($text_stack);
1125
-					$span = $this->runSpanGamut($span);
1126
-					$span = "<strong><em>$span</em></strong>";
1127
-					$text_stack[0] .= $this->hashPart($span);
1128
-					$em = '';
1129
-					$strong = '';
1130
-				} else {
1131
-					# Other closing marker: close one em or strong and
1132
-					# change current token state to match the other
1133
-					$token_stack[0] = str_repeat($token{0}, 3-$token_len);
1134
-					$tag = $token_len == 2 ? "strong" : "em";
1135
-					$span = $text_stack[0];
1136
-					$span = $this->runSpanGamut($span);
1137
-					$span = "<$tag>$span</$tag>";
1138
-					$text_stack[0] = $this->hashPart($span);
1139
-					$$tag = ''; # $$tag stands for $em or $strong
1140
-				}
1141
-				$tree_char_em = false;
1142
-			} else if ($token_len == 3) {
1143
-				if ($em) {
1144
-					# Reached closing marker for both em and strong.
1145
-					# Closing strong marker:
1146
-					for ($i = 0; $i < 2; ++$i) {
1147
-						$shifted_token = array_shift($token_stack);
1148
-						$tag = strlen($shifted_token) == 2 ? "strong" : "em";
1149
-						$span = array_shift($text_stack);
1150
-						$span = $this->runSpanGamut($span);
1151
-						$span = "<$tag>$span</$tag>";
1152
-						$text_stack[0] .= $this->hashPart($span);
1153
-						$$tag = ''; # $$tag stands for $em or $strong
1154
-					}
1155
-				} else {
1156
-					# Reached opening three-char emphasis marker. Push on token 
1157
-					# stack; will be handled by the special condition above.
1158
-					$em = $token{0};
1159
-					$strong = "$em$em";
1160
-					array_unshift($token_stack, $token);
1161
-					array_unshift($text_stack, '');
1162
-					$tree_char_em = true;
1163
-				}
1164
-			} else if ($token_len == 2) {
1165
-				if ($strong) {
1166
-					# Unwind any dangling emphasis marker:
1167
-					if (strlen($token_stack[0]) == 1) {
1168
-						$text_stack[1] .= array_shift($token_stack);
1169
-						$text_stack[0] .= array_shift($text_stack);
1170
-					}
1171
-					# Closing strong marker:
1172
-					array_shift($token_stack);
1173
-					$span = array_shift($text_stack);
1174
-					$span = $this->runSpanGamut($span);
1175
-					$span = "<strong>$span</strong>";
1176
-					$text_stack[0] .= $this->hashPart($span);
1177
-					$strong = '';
1178
-				} else {
1179
-					array_unshift($token_stack, $token);
1180
-					array_unshift($text_stack, '');
1181
-					$strong = $token;
1182
-				}
1183
-			} else {
1184
-				# Here $token_len == 1
1185
-				if ($em) {
1186
-					if (strlen($token_stack[0]) == 1) {
1187
-						# Closing emphasis marker:
1188
-						array_shift($token_stack);
1189
-						$span = array_shift($text_stack);
1190
-						$span = $this->runSpanGamut($span);
1191
-						$span = "<em>$span</em>";
1192
-						$text_stack[0] .= $this->hashPart($span);
1193
-						$em = '';
1194
-					} else {
1195
-						$text_stack[0] .= $token;
1196
-					}
1197
-				} else {
1198
-					array_unshift($token_stack, $token);
1199
-					array_unshift($text_stack, '');
1200
-					$em = $token;
1201
-				}
1202
-			}
1203
-		}
1204
-		return $text_stack[0];
1205
-	}
1206
-
1207
-
1208
-	protected function doBlockQuotes($text) {
1209
-		$text = preg_replace_callback('/
1118
+            $token_len = strlen($token);
1119
+            if ($tree_char_em) {
1120
+                # Reached closing marker while inside a three-char emphasis.
1121
+                if ($token_len == 3) {
1122
+                    # Three-char closing marker, close em and strong.
1123
+                    array_shift($token_stack);
1124
+                    $span = array_shift($text_stack);
1125
+                    $span = $this->runSpanGamut($span);
1126
+                    $span = "<strong><em>$span</em></strong>";
1127
+                    $text_stack[0] .= $this->hashPart($span);
1128
+                    $em = '';
1129
+                    $strong = '';
1130
+                } else {
1131
+                    # Other closing marker: close one em or strong and
1132
+                    # change current token state to match the other
1133
+                    $token_stack[0] = str_repeat($token{0}, 3-$token_len);
1134
+                    $tag = $token_len == 2 ? "strong" : "em";
1135
+                    $span = $text_stack[0];
1136
+                    $span = $this->runSpanGamut($span);
1137
+                    $span = "<$tag>$span</$tag>";
1138
+                    $text_stack[0] = $this->hashPart($span);
1139
+                    $$tag = ''; # $$tag stands for $em or $strong
1140
+                }
1141
+                $tree_char_em = false;
1142
+            } else if ($token_len == 3) {
1143
+                if ($em) {
1144
+                    # Reached closing marker for both em and strong.
1145
+                    # Closing strong marker:
1146
+                    for ($i = 0; $i < 2; ++$i) {
1147
+                        $shifted_token = array_shift($token_stack);
1148
+                        $tag = strlen($shifted_token) == 2 ? "strong" : "em";
1149
+                        $span = array_shift($text_stack);
1150
+                        $span = $this->runSpanGamut($span);
1151
+                        $span = "<$tag>$span</$tag>";
1152
+                        $text_stack[0] .= $this->hashPart($span);
1153
+                        $$tag = ''; # $$tag stands for $em or $strong
1154
+                    }
1155
+                } else {
1156
+                    # Reached opening three-char emphasis marker. Push on token 
1157
+                    # stack; will be handled by the special condition above.
1158
+                    $em = $token{0};
1159
+                    $strong = "$em$em";
1160
+                    array_unshift($token_stack, $token);
1161
+                    array_unshift($text_stack, '');
1162
+                    $tree_char_em = true;
1163
+                }
1164
+            } else if ($token_len == 2) {
1165
+                if ($strong) {
1166
+                    # Unwind any dangling emphasis marker:
1167
+                    if (strlen($token_stack[0]) == 1) {
1168
+                        $text_stack[1] .= array_shift($token_stack);
1169
+                        $text_stack[0] .= array_shift($text_stack);
1170
+                    }
1171
+                    # Closing strong marker:
1172
+                    array_shift($token_stack);
1173
+                    $span = array_shift($text_stack);
1174
+                    $span = $this->runSpanGamut($span);
1175
+                    $span = "<strong>$span</strong>";
1176
+                    $text_stack[0] .= $this->hashPart($span);
1177
+                    $strong = '';
1178
+                } else {
1179
+                    array_unshift($token_stack, $token);
1180
+                    array_unshift($text_stack, '');
1181
+                    $strong = $token;
1182
+                }
1183
+            } else {
1184
+                # Here $token_len == 1
1185
+                if ($em) {
1186
+                    if (strlen($token_stack[0]) == 1) {
1187
+                        # Closing emphasis marker:
1188
+                        array_shift($token_stack);
1189
+                        $span = array_shift($text_stack);
1190
+                        $span = $this->runSpanGamut($span);
1191
+                        $span = "<em>$span</em>";
1192
+                        $text_stack[0] .= $this->hashPart($span);
1193
+                        $em = '';
1194
+                    } else {
1195
+                        $text_stack[0] .= $token;
1196
+                    }
1197
+                } else {
1198
+                    array_unshift($token_stack, $token);
1199
+                    array_unshift($text_stack, '');
1200
+                    $em = $token;
1201
+                }
1202
+            }
1203
+        }
1204
+        return $text_stack[0];
1205
+    }
1206
+
1207
+
1208
+    protected function doBlockQuotes($text) {
1209
+        $text = preg_replace_callback('/
1210 1210
 			  (								# Wrap whole match in $1
1211 1211
 				(?>
1212 1212
 				  ^[ ]*>[ ]?			# ">" at the start of a line
@@ -1216,58 +1216,58 @@  discard block
 block discarded – undo
1216 1216
 				)+
1217 1217
 			  )
1218 1218
 			/xm',
1219
-			array($this, '_doBlockQuotes_callback'), $text);
1220
-
1221
-		return $text;
1222
-	}
1223
-	protected function _doBlockQuotes_callback($matches) {
1224
-		$bq = $matches[1];
1225
-		# trim one level of quoting - trim whitespace-only lines
1226
-		$bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
1227
-		$bq = $this->runBlockGamut($bq);		# recurse
1228
-
1229
-		$bq = preg_replace('/^/m', "  ", $bq);
1230
-		# These leading spaces cause problem with <pre> content, 
1231
-		# so we need to fix that:
1232
-		$bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx', 
1233
-			array($this, '_doBlockQuotes_callback2'), $bq);
1234
-
1235
-		return "\n". $this->hashBlock("<blockquote>\n$bq\n</blockquote>")."\n\n";
1236
-	}
1237
-	protected function _doBlockQuotes_callback2($matches) {
1238
-		$pre = $matches[1];
1239
-		$pre = preg_replace('/^  /m', '', $pre);
1240
-		return $pre;
1241
-	}
1242
-
1243
-
1244
-	protected function formParagraphs($text) {
1245
-	#
1246
-	#	Params:
1247
-	#		$text - string to process with html <p> tags
1248
-	#
1249
-		# Strip leading and trailing lines:
1250
-		$text = preg_replace('/\A\n+|\n+\z/', '', $text);
1251
-
1252
-		$grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
1253
-
1254
-		#
1255
-		# Wrap <p> tags and unhashify HTML blocks
1256
-		#
1257
-		foreach ($grafs as $key => $value) {
1258
-			if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
1259
-				# Is a paragraph.
1260
-				$value = $this->runSpanGamut($value);
1261
-				$value = preg_replace('/^([ ]*)/', "<p>", $value);
1262
-				$value .= "</p>";
1263
-				$grafs[$key] = $this->unhash($value);
1264
-			}
1265
-			else {
1266
-				# Is a block.
1267
-				# Modify elements of @grafs in-place...
1268
-				$graf = $value;
1269
-				$block = $this->html_hashes[$graf];
1270
-				$graf = $block;
1219
+            array($this, '_doBlockQuotes_callback'), $text);
1220
+
1221
+        return $text;
1222
+    }
1223
+    protected function _doBlockQuotes_callback($matches) {
1224
+        $bq = $matches[1];
1225
+        # trim one level of quoting - trim whitespace-only lines
1226
+        $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
1227
+        $bq = $this->runBlockGamut($bq);		# recurse
1228
+
1229
+        $bq = preg_replace('/^/m', "  ", $bq);
1230
+        # These leading spaces cause problem with <pre> content, 
1231
+        # so we need to fix that:
1232
+        $bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx', 
1233
+            array($this, '_doBlockQuotes_callback2'), $bq);
1234
+
1235
+        return "\n". $this->hashBlock("<blockquote>\n$bq\n</blockquote>")."\n\n";
1236
+    }
1237
+    protected function _doBlockQuotes_callback2($matches) {
1238
+        $pre = $matches[1];
1239
+        $pre = preg_replace('/^  /m', '', $pre);
1240
+        return $pre;
1241
+    }
1242
+
1243
+
1244
+    protected function formParagraphs($text) {
1245
+    #
1246
+    #	Params:
1247
+    #		$text - string to process with html <p> tags
1248
+    #
1249
+        # Strip leading and trailing lines:
1250
+        $text = preg_replace('/\A\n+|\n+\z/', '', $text);
1251
+
1252
+        $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
1253
+
1254
+        #
1255
+        # Wrap <p> tags and unhashify HTML blocks
1256
+        #
1257
+        foreach ($grafs as $key => $value) {
1258
+            if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
1259
+                # Is a paragraph.
1260
+                $value = $this->runSpanGamut($value);
1261
+                $value = preg_replace('/^([ ]*)/', "<p>", $value);
1262
+                $value .= "</p>";
1263
+                $grafs[$key] = $this->unhash($value);
1264
+            }
1265
+            else {
1266
+                # Is a block.
1267
+                # Modify elements of @grafs in-place...
1268
+                $graf = $value;
1269
+                $block = $this->html_hashes[$graf];
1270
+                $graf = $block;
1271 1271
 //				if (preg_match('{
1272 1272
 //					\A
1273 1273
 //					(							# $1 = <div> tag
@@ -1303,79 +1303,79 @@  discard block
 block discarded – undo
1303 1303
 //
1304 1304
 //					$graf = $div_open . "\n" . $div_content . "\n" . $div_close;
1305 1305
 //				}
1306
-				$grafs[$key] = $graf;
1307
-			}
1308
-		}
1309
-
1310
-		return implode("\n\n", $grafs);
1311
-	}
1312
-
1313
-
1314
-	protected function encodeAttribute($text) {
1315
-	#
1316
-	# Encode text for a double-quoted HTML attribute. This function
1317
-	# is *not* suitable for attributes enclosed in single quotes.
1318
-	#
1319
-		$text = $this->encodeAmpsAndAngles($text);
1320
-		$text = str_replace('"', '&quot;', $text);
1321
-		return $text;
1322
-	}
1323
-
1324
-
1325
-	protected function encodeURLAttribute($url, &$text = null) {
1326
-	#
1327
-	# Encode text for a double-quoted HTML attribute containing a URL,
1328
-	# applying the URL filter if set. Also generates the textual
1329
-	# representation for the URL (removing mailto: or tel:) storing it in $text.
1330
-	# This function is *not* suitable for attributes enclosed in single quotes.
1331
-	#
1332
-		if ($this->url_filter_func)
1333
-			$url = call_user_func($this->url_filter_func, $url);
1334
-
1335
-		if (preg_match('{^mailto:}i', $url))
1336
-			$url = $this->encodeEntityObfuscatedAttribute($url, $text, 7);
1337
-		else if (preg_match('{^tel:}i', $url))
1338
-		{
1339
-			$url = $this->encodeAttribute($url);
1340
-			$text = substr($url, 4);
1341
-		}
1342
-		else
1343
-		{
1344
-			$url = $this->encodeAttribute($url);
1345
-			$text = $url;
1346
-		}
1347
-
1348
-		return $url;
1349
-	}
1306
+                $grafs[$key] = $graf;
1307
+            }
1308
+        }
1309
+
1310
+        return implode("\n\n", $grafs);
1311
+    }
1312
+
1313
+
1314
+    protected function encodeAttribute($text) {
1315
+    #
1316
+    # Encode text for a double-quoted HTML attribute. This function
1317
+    # is *not* suitable for attributes enclosed in single quotes.
1318
+    #
1319
+        $text = $this->encodeAmpsAndAngles($text);
1320
+        $text = str_replace('"', '&quot;', $text);
1321
+        return $text;
1322
+    }
1323
+
1324
+
1325
+    protected function encodeURLAttribute($url, &$text = null) {
1326
+    #
1327
+    # Encode text for a double-quoted HTML attribute containing a URL,
1328
+    # applying the URL filter if set. Also generates the textual
1329
+    # representation for the URL (removing mailto: or tel:) storing it in $text.
1330
+    # This function is *not* suitable for attributes enclosed in single quotes.
1331
+    #
1332
+        if ($this->url_filter_func)
1333
+            $url = call_user_func($this->url_filter_func, $url);
1334
+
1335
+        if (preg_match('{^mailto:}i', $url))
1336
+            $url = $this->encodeEntityObfuscatedAttribute($url, $text, 7);
1337
+        else if (preg_match('{^tel:}i', $url))
1338
+        {
1339
+            $url = $this->encodeAttribute($url);
1340
+            $text = substr($url, 4);
1341
+        }
1342
+        else
1343
+        {
1344
+            $url = $this->encodeAttribute($url);
1345
+            $text = $url;
1346
+        }
1347
+
1348
+        return $url;
1349
+    }
1350 1350
 	
1351 1351
 	
1352
-	protected function encodeAmpsAndAngles($text) {
1353
-	#
1354
-	# Smart processing for ampersands and angle brackets that need to 
1355
-	# be encoded. Valid character entities are left alone unless the
1356
-	# no-entities mode is set.
1357
-	#
1358
-		if ($this->no_entities) {
1359
-			$text = str_replace('&', '&amp;', $text);
1360
-		} else {
1361
-			# Ampersand-encoding based entirely on Nat Irons's Amputator
1362
-			# MT plugin: <http://bumppo.net/projects/amputator/>
1363
-			$text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', 
1364
-								'&amp;', $text);
1365
-		}
1366
-		# Encode remaining <'s
1367
-		$text = str_replace('<', '&lt;', $text);
1368
-
1369
-		return $text;
1370
-	}
1371
-
1372
-
1373
-	protected function doAutoLinks($text) {
1374
-		$text = preg_replace_callback('{<((https?|ftp|dict|tel):[^\'">\s]+)>}i',
1375
-			array($this, '_doAutoLinks_url_callback'), $text);
1376
-
1377
-		# Email addresses: <[email protected]>
1378
-		$text = preg_replace_callback('{
1352
+    protected function encodeAmpsAndAngles($text) {
1353
+    #
1354
+    # Smart processing for ampersands and angle brackets that need to 
1355
+    # be encoded. Valid character entities are left alone unless the
1356
+    # no-entities mode is set.
1357
+    #
1358
+        if ($this->no_entities) {
1359
+            $text = str_replace('&', '&amp;', $text);
1360
+        } else {
1361
+            # Ampersand-encoding based entirely on Nat Irons's Amputator
1362
+            # MT plugin: <http://bumppo.net/projects/amputator/>
1363
+            $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', 
1364
+                                '&amp;', $text);
1365
+        }
1366
+        # Encode remaining <'s
1367
+        $text = str_replace('<', '&lt;', $text);
1368
+
1369
+        return $text;
1370
+    }
1371
+
1372
+
1373
+    protected function doAutoLinks($text) {
1374
+        $text = preg_replace_callback('{<((https?|ftp|dict|tel):[^\'">\s]+)>}i',
1375
+            array($this, '_doAutoLinks_url_callback'), $text);
1376
+
1377
+        # Email addresses: <[email protected]>
1378
+        $text = preg_replace_callback('{
1379 1379
 			<
1380 1380
 			(?:mailto:)?
1381 1381
 			(
@@ -1393,76 +1393,76 @@  discard block
 block discarded – undo
1393 1393
 			)
1394 1394
 			>
1395 1395
 			}xi',
1396
-			array($this, '_doAutoLinks_email_callback'), $text);
1397
-
1398
-		return $text;
1399
-	}
1400
-	protected function _doAutoLinks_url_callback($matches) {
1401
-		$url = $this->encodeURLAttribute($matches[1], $text);
1402
-		$link = "<a href=\"$url\">$text</a>";
1403
-		return $this->hashPart($link);
1404
-	}
1405
-	protected function _doAutoLinks_email_callback($matches) {
1406
-		$addr = $matches[1];
1407
-		$url = $this->encodeURLAttribute("mailto:$addr", $text);
1408
-		$link = "<a href=\"$url\">$text</a>";
1409
-		return $this->hashPart($link);
1410
-	}
1411
-
1412
-
1413
-	protected function encodeEntityObfuscatedAttribute($text, &$tail = null, $head_length = 0) {
1414
-	#
1415
-	#	Input: some text to obfuscate, e.g. "mailto:[email protected]"
1416
-	#
1417
-	#	Output: the same text but with most characters encoded as either a
1418
-	#		decimal or hex entity, in the hopes of foiling most address
1419
-	#		harvesting spam bots. E.g.:
1420
-	#
1421
-	#        &#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x66;o&#111;
1422
-	#        &#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#111;
1423
-	#        &#x6d;
1424
-	#
1425
-	#	Note: the additional output $tail is assigned the same value as the
1426
-	#	ouput, minus the number of characters specified by $head_length.
1427
-	#
1428
-	#	Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
1429
-	#   With some optimizations by Milian Wolff. Forced encoding of HTML
1430
-	#	attribute special characters by Allan Odgaard.
1431
-	#
1432
-		if ($text == "") return $tail = "";
1433
-
1434
-		$chars = preg_split('/(?<!^)(?!$)/', $text);
1435
-		$seed = (int)abs(crc32($text) / strlen($text)); # Deterministic seed.
1436
-
1437
-		foreach ($chars as $key => $char) {
1438
-			$ord = ord($char);
1439
-			# Ignore non-ascii chars.
1440
-			if ($ord < 128) {
1441
-				$r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
1442
-				# roughly 10% raw, 45% hex, 45% dec
1443
-				# '@' *must* be encoded. I insist.
1444
-				# '"' and '>' have to be encoded inside the attribute
1445
-				if ($r > 90 && strpos('@"&>', $char) === false) /* do nothing */;
1446
-				else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';';
1447
-				else              $chars[$key] = '&#'.$ord.';';
1448
-			}
1449
-		}
1450
-
1451
-		$text = implode('', $chars);
1452
-		$tail = $head_length ? implode('', array_slice($chars, $head_length)) : $text;
1453
-
1454
-		return $text;
1455
-	}
1456
-
1457
-
1458
-	protected function parseSpan($str) {
1459
-	#
1460
-	# Take the string $str and parse it into tokens, hashing embeded HTML,
1461
-	# escaped characters and handling code spans.
1462
-	#
1463
-		$output = '';
1396
+            array($this, '_doAutoLinks_email_callback'), $text);
1397
+
1398
+        return $text;
1399
+    }
1400
+    protected function _doAutoLinks_url_callback($matches) {
1401
+        $url = $this->encodeURLAttribute($matches[1], $text);
1402
+        $link = "<a href=\"$url\">$text</a>";
1403
+        return $this->hashPart($link);
1404
+    }
1405
+    protected function _doAutoLinks_email_callback($matches) {
1406
+        $addr = $matches[1];
1407
+        $url = $this->encodeURLAttribute("mailto:$addr", $text);
1408
+        $link = "<a href=\"$url\">$text</a>";
1409
+        return $this->hashPart($link);
1410
+    }
1411
+
1412
+
1413
+    protected function encodeEntityObfuscatedAttribute($text, &$tail = null, $head_length = 0) {
1414
+    #
1415
+    #	Input: some text to obfuscate, e.g. "mailto:[email protected]"
1416
+    #
1417
+    #	Output: the same text but with most characters encoded as either a
1418
+    #		decimal or hex entity, in the hopes of foiling most address
1419
+    #		harvesting spam bots. E.g.:
1420
+    #
1421
+    #        &#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x66;o&#111;
1422
+    #        &#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#111;
1423
+    #        &#x6d;
1424
+    #
1425
+    #	Note: the additional output $tail is assigned the same value as the
1426
+    #	ouput, minus the number of characters specified by $head_length.
1427
+    #
1428
+    #	Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
1429
+    #   With some optimizations by Milian Wolff. Forced encoding of HTML
1430
+    #	attribute special characters by Allan Odgaard.
1431
+    #
1432
+        if ($text == "") return $tail = "";
1433
+
1434
+        $chars = preg_split('/(?<!^)(?!$)/', $text);
1435
+        $seed = (int)abs(crc32($text) / strlen($text)); # Deterministic seed.
1436
+
1437
+        foreach ($chars as $key => $char) {
1438
+            $ord = ord($char);
1439
+            # Ignore non-ascii chars.
1440
+            if ($ord < 128) {
1441
+                $r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
1442
+                # roughly 10% raw, 45% hex, 45% dec
1443
+                # '@' *must* be encoded. I insist.
1444
+                # '"' and '>' have to be encoded inside the attribute
1445
+                if ($r > 90 && strpos('@"&>', $char) === false) /* do nothing */;
1446
+                else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';';
1447
+                else              $chars[$key] = '&#'.$ord.';';
1448
+            }
1449
+        }
1450
+
1451
+        $text = implode('', $chars);
1452
+        $tail = $head_length ? implode('', array_slice($chars, $head_length)) : $text;
1453
+
1454
+        return $text;
1455
+    }
1456
+
1457
+
1458
+    protected function parseSpan($str) {
1459
+    #
1460
+    # Take the string $str and parse it into tokens, hashing embeded HTML,
1461
+    # escaped characters and handling code spans.
1462
+    #
1463
+        $output = '';
1464 1464
 		
1465
-		$span_re = '{
1465
+        $span_re = '{
1466 1466
 				(
1467 1467
 					\\\\'.$this->escape_chars_re.'
1468 1468
 				|
@@ -1488,122 +1488,122 @@  discard block
 block discarded – undo
1488 1488
 				)
1489 1489
 				}xs';
1490 1490
 
1491
-		while (1) {
1492
-			#
1493
-			# Each loop iteration seach for either the next tag, the next 
1494
-			# openning code span marker, or the next escaped character. 
1495
-			# Each token is then passed to handleSpanToken.
1496
-			#
1497
-			$parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
1491
+        while (1) {
1492
+            #
1493
+            # Each loop iteration seach for either the next tag, the next 
1494
+            # openning code span marker, or the next escaped character. 
1495
+            # Each token is then passed to handleSpanToken.
1496
+            #
1497
+            $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
1498 1498
 			
1499
-			# Create token from text preceding tag.
1500
-			if ($parts[0] != "") {
1501
-				$output .= $parts[0];
1502
-			}
1499
+            # Create token from text preceding tag.
1500
+            if ($parts[0] != "") {
1501
+                $output .= $parts[0];
1502
+            }
1503 1503
 			
1504
-			# Check if we reach the end.
1505
-			if (isset($parts[1])) {
1506
-				$output .= $this->handleSpanToken($parts[1], $parts[2]);
1507
-				$str = $parts[2];
1508
-			}
1509
-			else {
1510
-				break;
1511
-			}
1512
-		}
1504
+            # Check if we reach the end.
1505
+            if (isset($parts[1])) {
1506
+                $output .= $this->handleSpanToken($parts[1], $parts[2]);
1507
+                $str = $parts[2];
1508
+            }
1509
+            else {
1510
+                break;
1511
+            }
1512
+        }
1513 1513
 		
1514
-		return $output;
1515
-	}
1514
+        return $output;
1515
+    }
1516 1516
 	
1517 1517
 	
1518
-	protected function handleSpanToken($token, &$str) {
1519
-	#
1520
-	# Handle $token provided by parseSpan by determining its nature and 
1521
-	# returning the corresponding value that should replace it.
1522
-	#
1523
-		switch ($token{0}) {
1524
-			case "\\":
1525
-				return $this->hashPart("&#". ord($token{1}). ";");
1526
-			case "`":
1527
-				# Search for end marker in remaining text.
1528
-				if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', 
1529
-					$str, $matches))
1530
-				{
1531
-					$str = $matches[2];
1532
-					$codespan = $this->makeCodeSpan($matches[1]);
1533
-					return $this->hashPart($codespan);
1534
-				}
1535
-				return $token; // return as text since no ending marker found.
1536
-			default:
1537
-				return $this->hashPart($token);
1538
-		}
1539
-	}
1540
-
1541
-
1542
-	protected function outdent($text) {
1543
-	#
1544
-	# Remove one level of line-leading tabs or spaces
1545
-	#
1546
-		return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text);
1547
-	}
1548
-
1549
-
1550
-	# String length function for detab. `_initDetab` will create a function to 
1551
-	# hanlde UTF-8 if the default function does not exist.
1552
-	protected $utf8_strlen = 'mb_strlen';
1518
+    protected function handleSpanToken($token, &$str) {
1519
+    #
1520
+    # Handle $token provided by parseSpan by determining its nature and 
1521
+    # returning the corresponding value that should replace it.
1522
+    #
1523
+        switch ($token{0}) {
1524
+            case "\\":
1525
+                return $this->hashPart("&#". ord($token{1}). ";");
1526
+            case "`":
1527
+                # Search for end marker in remaining text.
1528
+                if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', 
1529
+                    $str, $matches))
1530
+                {
1531
+                    $str = $matches[2];
1532
+                    $codespan = $this->makeCodeSpan($matches[1]);
1533
+                    return $this->hashPart($codespan);
1534
+                }
1535
+                return $token; // return as text since no ending marker found.
1536
+            default:
1537
+                return $this->hashPart($token);
1538
+        }
1539
+    }
1540
+
1541
+
1542
+    protected function outdent($text) {
1543
+    #
1544
+    # Remove one level of line-leading tabs or spaces
1545
+    #
1546
+        return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text);
1547
+    }
1548
+
1549
+
1550
+    # String length function for detab. `_initDetab` will create a function to 
1551
+    # hanlde UTF-8 if the default function does not exist.
1552
+    protected $utf8_strlen = 'mb_strlen';
1553 1553
 	
1554
-	protected function detab($text) {
1555
-	#
1556
-	# Replace tabs with the appropriate amount of space.
1557
-	#
1558
-		# For each line we separate the line in blocks delemited by
1559
-		# tab characters. Then we reconstruct every line by adding the 
1560
-		# appropriate number of space between each blocks.
1554
+    protected function detab($text) {
1555
+    #
1556
+    # Replace tabs with the appropriate amount of space.
1557
+    #
1558
+        # For each line we separate the line in blocks delemited by
1559
+        # tab characters. Then we reconstruct every line by adding the 
1560
+        # appropriate number of space between each blocks.
1561 1561
 		
1562
-		$text = preg_replace_callback('/^.*\t.*$/m',
1563
-			array($this, '_detab_callback'), $text);
1564
-
1565
-		return $text;
1566
-	}
1567
-	protected function _detab_callback($matches) {
1568
-		$line = $matches[0];
1569
-		$strlen = $this->utf8_strlen; # strlen function for UTF-8.
1562
+        $text = preg_replace_callback('/^.*\t.*$/m',
1563
+            array($this, '_detab_callback'), $text);
1564
+
1565
+        return $text;
1566
+    }
1567
+    protected function _detab_callback($matches) {
1568
+        $line = $matches[0];
1569
+        $strlen = $this->utf8_strlen; # strlen function for UTF-8.
1570 1570
 		
1571
-		# Split in blocks.
1572
-		$blocks = explode("\t", $line);
1573
-		# Add each blocks to the line.
1574
-		$line = $blocks[0];
1575
-		unset($blocks[0]); # Do not add first block twice.
1576
-		foreach ($blocks as $block) {
1577
-			# Calculate amount of space, insert spaces, insert block.
1578
-			$amount = $this->tab_width - 
1579
-				$strlen($line, 'UTF-8') % $this->tab_width;
1580
-			$line .= str_repeat(" ", $amount) . $block;
1581
-		}
1582
-		return $line;
1583
-	}
1584
-	protected function _initDetab() {
1585
-	#
1586
-	# Check for the availability of the function in the `utf8_strlen` property
1587
-	# (initially `mb_strlen`). If the function is not available, create a 
1588
-	# function that will loosely count the number of UTF-8 characters with a
1589
-	# regular expression.
1590
-	#
1591
-		if (function_exists($this->utf8_strlen)) return;
1592
-		$this->utf8_strlen = create_function('$text', 'return preg_match_all(
1571
+        # Split in blocks.
1572
+        $blocks = explode("\t", $line);
1573
+        # Add each blocks to the line.
1574
+        $line = $blocks[0];
1575
+        unset($blocks[0]); # Do not add first block twice.
1576
+        foreach ($blocks as $block) {
1577
+            # Calculate amount of space, insert spaces, insert block.
1578
+            $amount = $this->tab_width - 
1579
+                $strlen($line, 'UTF-8') % $this->tab_width;
1580
+            $line .= str_repeat(" ", $amount) . $block;
1581
+        }
1582
+        return $line;
1583
+    }
1584
+    protected function _initDetab() {
1585
+    #
1586
+    # Check for the availability of the function in the `utf8_strlen` property
1587
+    # (initially `mb_strlen`). If the function is not available, create a 
1588
+    # function that will loosely count the number of UTF-8 characters with a
1589
+    # regular expression.
1590
+    #
1591
+        if (function_exists($this->utf8_strlen)) return;
1592
+        $this->utf8_strlen = create_function('$text', 'return preg_match_all(
1593 1593
 			"/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/", 
1594 1594
 			$text, $m);');
1595
-	}
1596
-
1597
-
1598
-	protected function unhash($text) {
1599
-	#
1600
-	# Swap back in all the tags hashed by _HashHTMLBlocks.
1601
-	#
1602
-		return preg_replace_callback('/(.)\x1A[0-9]+\1/', 
1603
-			array($this, '_unhash_callback'), $text);
1604
-	}
1605
-	protected function _unhash_callback($matches) {
1606
-		return $this->html_hashes[$matches[0]];
1607
-	}
1595
+    }
1596
+
1597
+
1598
+    protected function unhash($text) {
1599
+    #
1600
+    # Swap back in all the tags hashed by _HashHTMLBlocks.
1601
+    #
1602
+        return preg_replace_callback('/(.)\x1A[0-9]+\1/', 
1603
+            array($this, '_unhash_callback'), $text);
1604
+    }
1605
+    protected function _unhash_callback($matches) {
1606
+        return $this->html_hashes[$matches[0]];
1607
+    }
1608 1608
 
1609 1609
 }
Please login to merge, or discard this patch.
vendor/michelf/php-markdown/Michelf/MarkdownExtra.php 1 patch
Indentation   +1150 added lines, -1150 removed lines patch added patch discarded remove patch
@@ -19,179 +19,179 @@  discard block
 block discarded – undo
19 19
 
20 20
 class MarkdownExtra extends \Michelf\Markdown {
21 21
 
22
-	### Configuration Variables ###
22
+    ### Configuration Variables ###
23 23
 
24
-	# Prefix for footnote ids.
25
-	public $fn_id_prefix = "";
24
+    # Prefix for footnote ids.
25
+    public $fn_id_prefix = "";
26 26
 	
27
-	# Optional title attribute for footnote links and backlinks.
28
-	public $fn_link_title = "";
29
-	public $fn_backlink_title = "";
27
+    # Optional title attribute for footnote links and backlinks.
28
+    public $fn_link_title = "";
29
+    public $fn_backlink_title = "";
30 30
 	
31
-	# Optional class attribute for footnote links and backlinks.
32
-	public $fn_link_class = "footnote-ref";
33
-	public $fn_backlink_class = "footnote-backref";
34
-
35
-	# Class name for table cell alignment (%% replaced left/center/right)
36
-	# For instance: 'go-%%' becomes 'go-left' or 'go-right' or 'go-center'
37
-	# If empty, the align attribute is used instead of a class name.
38
-	public $table_align_class_tmpl = '';
39
-
40
-	# Optional class prefix for fenced code block.
41
-	public $code_class_prefix = "";
42
-	# Class attribute for code blocks goes on the `code` tag;
43
-	# setting this to true will put attributes on the `pre` tag instead.
44
-	public $code_attr_on_pre = false;
31
+    # Optional class attribute for footnote links and backlinks.
32
+    public $fn_link_class = "footnote-ref";
33
+    public $fn_backlink_class = "footnote-backref";
34
+
35
+    # Class name for table cell alignment (%% replaced left/center/right)
36
+    # For instance: 'go-%%' becomes 'go-left' or 'go-right' or 'go-center'
37
+    # If empty, the align attribute is used instead of a class name.
38
+    public $table_align_class_tmpl = '';
39
+
40
+    # Optional class prefix for fenced code block.
41
+    public $code_class_prefix = "";
42
+    # Class attribute for code blocks goes on the `code` tag;
43
+    # setting this to true will put attributes on the `pre` tag instead.
44
+    public $code_attr_on_pre = false;
45 45
 	
46
-	# Predefined abbreviations.
47
-	public $predef_abbr = array();
48
-
49
-	### Parser Implementation ###
50
-
51
-	public function __construct() {
52
-	#
53
-	# Constructor function. Initialize the parser object.
54
-	#
55
-		# Add extra escapable characters before parent constructor 
56
-		# initialize the table.
57
-		$this->escape_chars .= ':|';
46
+    # Predefined abbreviations.
47
+    public $predef_abbr = array();
48
+
49
+    ### Parser Implementation ###
50
+
51
+    public function __construct() {
52
+    #
53
+    # Constructor function. Initialize the parser object.
54
+    #
55
+        # Add extra escapable characters before parent constructor 
56
+        # initialize the table.
57
+        $this->escape_chars .= ':|';
58 58
 		
59
-		# Insert extra document, block, and span transformations. 
60
-		# Parent constructor will do the sorting.
61
-		$this->document_gamut += array(
62
-			"doFencedCodeBlocks" => 5,
63
-			"stripFootnotes"     => 15,
64
-			"stripAbbreviations" => 25,
65
-			"appendFootnotes"    => 50,
66
-			);
67
-		$this->block_gamut += array(
68
-			"doFencedCodeBlocks" => 5,
69
-			"doTables"           => 15,
70
-			"doDefLists"         => 45,
71
-			);
72
-		$this->span_gamut += array(
73
-			"doFootnotes"        => 5,
74
-			"doAbbreviations"    => 70,
75
-			);
59
+        # Insert extra document, block, and span transformations. 
60
+        # Parent constructor will do the sorting.
61
+        $this->document_gamut += array(
62
+            "doFencedCodeBlocks" => 5,
63
+            "stripFootnotes"     => 15,
64
+            "stripAbbreviations" => 25,
65
+            "appendFootnotes"    => 50,
66
+            );
67
+        $this->block_gamut += array(
68
+            "doFencedCodeBlocks" => 5,
69
+            "doTables"           => 15,
70
+            "doDefLists"         => 45,
71
+            );
72
+        $this->span_gamut += array(
73
+            "doFootnotes"        => 5,
74
+            "doAbbreviations"    => 70,
75
+            );
76 76
 		
77
-		$this->enhanced_ordered_list = true;
78
-		parent::__construct();
79
-	}
77
+        $this->enhanced_ordered_list = true;
78
+        parent::__construct();
79
+    }
80 80
 	
81 81
 	
82
-	# Extra variables used during extra transformations.
83
-	protected $footnotes = array();
84
-	protected $footnotes_ordered = array();
85
-	protected $footnotes_ref_count = array();
86
-	protected $footnotes_numbers = array();
87
-	protected $abbr_desciptions = array();
88
-	protected $abbr_word_re = '';
82
+    # Extra variables used during extra transformations.
83
+    protected $footnotes = array();
84
+    protected $footnotes_ordered = array();
85
+    protected $footnotes_ref_count = array();
86
+    protected $footnotes_numbers = array();
87
+    protected $abbr_desciptions = array();
88
+    protected $abbr_word_re = '';
89 89
 	
90
-	# Give the current footnote number.
91
-	protected $footnote_counter = 1;
90
+    # Give the current footnote number.
91
+    protected $footnote_counter = 1;
92 92
 	
93 93
 	
94
-	protected function setup() {
95
-	#
96
-	# Setting up Extra-specific variables.
97
-	#
98
-		parent::setup();
94
+    protected function setup() {
95
+    #
96
+    # Setting up Extra-specific variables.
97
+    #
98
+        parent::setup();
99 99
 		
100
-		$this->footnotes = array();
101
-		$this->footnotes_ordered = array();
102
-		$this->footnotes_ref_count = array();
103
-		$this->footnotes_numbers = array();
104
-		$this->abbr_desciptions = array();
105
-		$this->abbr_word_re = '';
106
-		$this->footnote_counter = 1;
100
+        $this->footnotes = array();
101
+        $this->footnotes_ordered = array();
102
+        $this->footnotes_ref_count = array();
103
+        $this->footnotes_numbers = array();
104
+        $this->abbr_desciptions = array();
105
+        $this->abbr_word_re = '';
106
+        $this->footnote_counter = 1;
107 107
 		
108
-		foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
109
-			if ($this->abbr_word_re)
110
-				$this->abbr_word_re .= '|';
111
-			$this->abbr_word_re .= preg_quote($abbr_word);
112
-			$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
113
-		}
114
-	}
108
+        foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
109
+            if ($this->abbr_word_re)
110
+                $this->abbr_word_re .= '|';
111
+            $this->abbr_word_re .= preg_quote($abbr_word);
112
+            $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
113
+        }
114
+    }
115 115
 	
116
-	protected function teardown() {
117
-	#
118
-	# Clearing Extra-specific variables.
119
-	#
120
-		$this->footnotes = array();
121
-		$this->footnotes_ordered = array();
122
-		$this->footnotes_ref_count = array();
123
-		$this->footnotes_numbers = array();
124
-		$this->abbr_desciptions = array();
125
-		$this->abbr_word_re = '';
116
+    protected function teardown() {
117
+    #
118
+    # Clearing Extra-specific variables.
119
+    #
120
+        $this->footnotes = array();
121
+        $this->footnotes_ordered = array();
122
+        $this->footnotes_ref_count = array();
123
+        $this->footnotes_numbers = array();
124
+        $this->abbr_desciptions = array();
125
+        $this->abbr_word_re = '';
126 126
 		
127
-		parent::teardown();
128
-	}
127
+        parent::teardown();
128
+    }
129 129
 	
130 130
 	
131
-	### Extra Attribute Parser ###
132
-
133
-	# Expression to use to catch attributes (includes the braces)
134
-	protected $id_class_attr_catch_re = '\{((?:[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,})[ ]*\}';
135
-	# Expression to use when parsing in a context when no capture is desired
136
-	protected $id_class_attr_nocatch_re = '\{(?:[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}';
137
-
138
-	protected function doExtraAttributes($tag_name, $attr, $defaultIdValue = null) {
139
-	#
140
-	# Parse attributes caught by the $this->id_class_attr_catch_re expression
141
-	# and return the HTML-formatted list of attributes.
142
-	#
143
-	# Currently supported attributes are .class and #id.
144
-	#
145
-	# In addition, this method also supports supplying a default Id value,
146
-	# which will be used to populate the id attribute in case it was not
147
-	# overridden.
148
-		if (empty($attr) && !$defaultIdValue) return "";
131
+    ### Extra Attribute Parser ###
132
+
133
+    # Expression to use to catch attributes (includes the braces)
134
+    protected $id_class_attr_catch_re = '\{((?:[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,})[ ]*\}';
135
+    # Expression to use when parsing in a context when no capture is desired
136
+    protected $id_class_attr_nocatch_re = '\{(?:[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}';
137
+
138
+    protected function doExtraAttributes($tag_name, $attr, $defaultIdValue = null) {
139
+    #
140
+    # Parse attributes caught by the $this->id_class_attr_catch_re expression
141
+    # and return the HTML-formatted list of attributes.
142
+    #
143
+    # Currently supported attributes are .class and #id.
144
+    #
145
+    # In addition, this method also supports supplying a default Id value,
146
+    # which will be used to populate the id attribute in case it was not
147
+    # overridden.
148
+        if (empty($attr) && !$defaultIdValue) return "";
149 149
 		
150
-		# Split on components
151
-		preg_match_all('/[#.a-z][-_:a-zA-Z0-9=]+/', $attr, $matches);
152
-		$elements = $matches[0];
153
-
154
-		# handle classes and ids (only first id taken into account)
155
-		$classes = array();
156
-		$attributes = array();
157
-		$id = false;
158
-		foreach ($elements as $element) {
159
-			if ($element{0} == '.') {
160
-				$classes[] = substr($element, 1);
161
-			} else if ($element{0} == '#') {
162
-				if ($id === false) $id = substr($element, 1);
163
-			} else if (strpos($element, '=') > 0) {
164
-				$parts = explode('=', $element, 2);
165
-				$attributes[] = $parts[0] . '="' . $parts[1] . '"';
166
-			}
167
-		}
168
-
169
-		if (!$id) $id = $defaultIdValue;
170
-
171
-		# compose attributes as string
172
-		$attr_str = "";
173
-		if (!empty($id)) {
174
-			$attr_str .= ' id="'.$this->encodeAttribute($id) .'"';
175
-		}
176
-		if (!empty($classes)) {
177
-			$attr_str .= ' class="'. implode(" ", $classes) . '"';
178
-		}
179
-		if (!$this->no_markup && !empty($attributes)) {
180
-			$attr_str .= ' '.implode(" ", $attributes);
181
-		}
182
-		return $attr_str;
183
-	}
184
-
185
-
186
-	protected function stripLinkDefinitions($text) {
187
-	#
188
-	# Strips link definitions from text, stores the URLs and titles in
189
-	# hash references.
190
-	#
191
-		$less_than_tab = $this->tab_width - 1;
192
-
193
-		# Link defs are in the form: ^[id]: url "optional title"
194
-		$text = preg_replace_callback('{
150
+        # Split on components
151
+        preg_match_all('/[#.a-z][-_:a-zA-Z0-9=]+/', $attr, $matches);
152
+        $elements = $matches[0];
153
+
154
+        # handle classes and ids (only first id taken into account)
155
+        $classes = array();
156
+        $attributes = array();
157
+        $id = false;
158
+        foreach ($elements as $element) {
159
+            if ($element{0} == '.') {
160
+                $classes[] = substr($element, 1);
161
+            } else if ($element{0} == '#') {
162
+                if ($id === false) $id = substr($element, 1);
163
+            } else if (strpos($element, '=') > 0) {
164
+                $parts = explode('=', $element, 2);
165
+                $attributes[] = $parts[0] . '="' . $parts[1] . '"';
166
+            }
167
+        }
168
+
169
+        if (!$id) $id = $defaultIdValue;
170
+
171
+        # compose attributes as string
172
+        $attr_str = "";
173
+        if (!empty($id)) {
174
+            $attr_str .= ' id="'.$this->encodeAttribute($id) .'"';
175
+        }
176
+        if (!empty($classes)) {
177
+            $attr_str .= ' class="'. implode(" ", $classes) . '"';
178
+        }
179
+        if (!$this->no_markup && !empty($attributes)) {
180
+            $attr_str .= ' '.implode(" ", $attributes);
181
+        }
182
+        return $attr_str;
183
+    }
184
+
185
+
186
+    protected function stripLinkDefinitions($text) {
187
+    #
188
+    # Strips link definitions from text, stores the URLs and titles in
189
+    # hash references.
190
+    #
191
+        $less_than_tab = $this->tab_width - 1;
192
+
193
+        # Link defs are in the form: ^[id]: url "optional title"
194
+        $text = preg_replace_callback('{
195 195
 							^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?:	# id = $1
196 196
 							  [ ]*
197 197
 							  \n?				# maybe *one* newline
@@ -214,106 +214,106 @@  discard block
 block discarded – undo
214 214
 					(?:[ ]* '.$this->id_class_attr_catch_re.' )?  # $5 = extra id & class attr
215 215
 							(?:\n+|\Z)
216 216
 			}xm',
217
-			array($this, '_stripLinkDefinitions_callback'),
218
-			$text);
219
-		return $text;
220
-	}
221
-	protected function _stripLinkDefinitions_callback($matches) {
222
-		$link_id = strtolower($matches[1]);
223
-		$url = $matches[2] == '' ? $matches[3] : $matches[2];
224
-		$this->urls[$link_id] = $url;
225
-		$this->titles[$link_id] =& $matches[4];
226
-		$this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]);
227
-		return ''; # String that will replace the block
228
-	}
229
-
230
-
231
-	### HTML Block Parser ###
217
+            array($this, '_stripLinkDefinitions_callback'),
218
+            $text);
219
+        return $text;
220
+    }
221
+    protected function _stripLinkDefinitions_callback($matches) {
222
+        $link_id = strtolower($matches[1]);
223
+        $url = $matches[2] == '' ? $matches[3] : $matches[2];
224
+        $this->urls[$link_id] = $url;
225
+        $this->titles[$link_id] =& $matches[4];
226
+        $this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]);
227
+        return ''; # String that will replace the block
228
+    }
229
+
230
+
231
+    ### HTML Block Parser ###
232 232
 	
233
-	# Tags that are always treated as block tags:
234
-	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';
233
+    # Tags that are always treated as block tags:
234
+    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';
235 235
 						   
236
-	# Tags treated as block tags only if the opening tag is alone on its line:
237
-	protected $context_block_tags_re = 'script|noscript|style|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video';
236
+    # Tags treated as block tags only if the opening tag is alone on its line:
237
+    protected $context_block_tags_re = 'script|noscript|style|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video';
238 238
 	
239
-	# Tags where markdown="1" default to span mode:
240
-	protected $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
239
+    # Tags where markdown="1" default to span mode:
240
+    protected $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
241 241
 	
242
-	# Tags which must not have their contents modified, no matter where 
243
-	# they appear:
244
-	protected $clean_tags_re = 'script|style|math|svg';
242
+    # Tags which must not have their contents modified, no matter where 
243
+    # they appear:
244
+    protected $clean_tags_re = 'script|style|math|svg';
245 245
 	
246
-	# Tags that do not need to be closed.
247
-	protected $auto_close_tags_re = 'hr|img|param|source|track';
246
+    # Tags that do not need to be closed.
247
+    protected $auto_close_tags_re = 'hr|img|param|source|track';
248 248
 	
249 249
 
250
-	protected function hashHTMLBlocks($text) {
251
-	#
252
-	# Hashify HTML Blocks and "clean tags".
253
-	#
254
-	# We only want to do this for block-level HTML tags, such as headers,
255
-	# lists, and tables. That's because we still want to wrap <p>s around
256
-	# "paragraphs" that are wrapped in non-block-level tags, such as anchors,
257
-	# phrase emphasis, and spans. The list of tags we're looking for is
258
-	# hard-coded.
259
-	#
260
-	# This works by calling _HashHTMLBlocks_InMarkdown, which then calls
261
-	# _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1" 
262
-	# attribute is found within a tag, _HashHTMLBlocks_InHTML calls back
263
-	#  _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
264
-	# These two functions are calling each other. It's recursive!
265
-	#
266
-		if ($this->no_markup)  return $text;
267
-
268
-		#
269
-		# Call the HTML-in-Markdown hasher.
270
-		#
271
-		list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
250
+    protected function hashHTMLBlocks($text) {
251
+    #
252
+    # Hashify HTML Blocks and "clean tags".
253
+    #
254
+    # We only want to do this for block-level HTML tags, such as headers,
255
+    # lists, and tables. That's because we still want to wrap <p>s around
256
+    # "paragraphs" that are wrapped in non-block-level tags, such as anchors,
257
+    # phrase emphasis, and spans. The list of tags we're looking for is
258
+    # hard-coded.
259
+    #
260
+    # This works by calling _HashHTMLBlocks_InMarkdown, which then calls
261
+    # _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1" 
262
+    # attribute is found within a tag, _HashHTMLBlocks_InHTML calls back
263
+    #  _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
264
+    # These two functions are calling each other. It's recursive!
265
+    #
266
+        if ($this->no_markup)  return $text;
267
+
268
+        #
269
+        # Call the HTML-in-Markdown hasher.
270
+        #
271
+        list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
272 272
 		
273
-		return $text;
274
-	}
275
-	protected function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
276
-										$enclosing_tag_re = '', $span = false)
277
-	{
278
-	#
279
-	# Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
280
-	#
281
-	# *   $indent is the number of space to be ignored when checking for code 
282
-	#     blocks. This is important because if we don't take the indent into 
283
-	#     account, something like this (which looks right) won't work as expected:
284
-	#
285
-	#     <div>
286
-	#         <div markdown="1">
287
-	#         Hello World.  <-- Is this a Markdown code block or text?
288
-	#         </div>  <-- Is this a Markdown code block or a real tag?
289
-	#     <div>
290
-	#
291
-	#     If you don't like this, just don't indent the tag on which
292
-	#     you apply the markdown="1" attribute.
293
-	#
294
-	# *   If $enclosing_tag_re is not empty, stops at the first unmatched closing 
295
-	#     tag with that name. Nested tags supported.
296
-	#
297
-	# *   If $span is true, text inside must treated as span. So any double 
298
-	#     newline will be replaced by a single newline so that it does not create 
299
-	#     paragraphs.
300
-	#
301
-	# Returns an array of that form: ( processed text , remaining text )
302
-	#
303
-		if ($text === '') return array('', '');
304
-
305
-		# Regex to check for the presense of newlines around a block tag.
306
-		$newline_before_re = '/(?:^\n?|\n\n)*$/';
307
-		$newline_after_re = 
308
-			'{
273
+        return $text;
274
+    }
275
+    protected function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
276
+                                        $enclosing_tag_re = '', $span = false)
277
+    {
278
+    #
279
+    # Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
280
+    #
281
+    # *   $indent is the number of space to be ignored when checking for code 
282
+    #     blocks. This is important because if we don't take the indent into 
283
+    #     account, something like this (which looks right) won't work as expected:
284
+    #
285
+    #     <div>
286
+    #         <div markdown="1">
287
+    #         Hello World.  <-- Is this a Markdown code block or text?
288
+    #         </div>  <-- Is this a Markdown code block or a real tag?
289
+    #     <div>
290
+    #
291
+    #     If you don't like this, just don't indent the tag on which
292
+    #     you apply the markdown="1" attribute.
293
+    #
294
+    # *   If $enclosing_tag_re is not empty, stops at the first unmatched closing 
295
+    #     tag with that name. Nested tags supported.
296
+    #
297
+    # *   If $span is true, text inside must treated as span. So any double 
298
+    #     newline will be replaced by a single newline so that it does not create 
299
+    #     paragraphs.
300
+    #
301
+    # Returns an array of that form: ( processed text , remaining text )
302
+    #
303
+        if ($text === '') return array('', '');
304
+
305
+        # Regex to check for the presense of newlines around a block tag.
306
+        $newline_before_re = '/(?:^\n?|\n\n)*$/';
307
+        $newline_after_re = 
308
+            '{
309 309
 				^						# Start of text following the tag.
310 310
 				(?>[ ]*<!--.*?-->)?		# Optional comment.
311 311
 				[ ]*\n					# Must be followed by newline.
312 312
 			}xs';
313 313
 		
314
-		# Regex to match any tag.
315
-		$block_tag_re =
316
-			'{
314
+        # Regex to match any tag.
315
+        $block_tag_re =
316
+            '{
317 317
 				(					# $2: Capture whole tag.
318 318
 					</?					# Any opening or closing tag.
319 319
 						(?>				# Tag name.
@@ -368,169 +368,169 @@  discard block
 block discarded – undo
368 368
 			}xs';
369 369
 
370 370
 		
371
-		$depth = 0;		# Current depth inside the tag tree.
372
-		$parsed = "";	# Parsed text that will be returned.
373
-
374
-		#
375
-		# Loop through every tag until we find the closing tag of the parent
376
-		# or loop until reaching the end of text if no parent tag specified.
377
-		#
378
-		do {
379
-			#
380
-			# Split the text using the first $tag_match pattern found.
381
-			# Text before  pattern will be first in the array, text after
382
-			# pattern will be at the end, and between will be any catches made 
383
-			# by the pattern.
384
-			#
385
-			$parts = preg_split($block_tag_re, $text, 2, 
386
-								PREG_SPLIT_DELIM_CAPTURE);
371
+        $depth = 0;		# Current depth inside the tag tree.
372
+        $parsed = "";	# Parsed text that will be returned.
373
+
374
+        #
375
+        # Loop through every tag until we find the closing tag of the parent
376
+        # or loop until reaching the end of text if no parent tag specified.
377
+        #
378
+        do {
379
+            #
380
+            # Split the text using the first $tag_match pattern found.
381
+            # Text before  pattern will be first in the array, text after
382
+            # pattern will be at the end, and between will be any catches made 
383
+            # by the pattern.
384
+            #
385
+            $parts = preg_split($block_tag_re, $text, 2, 
386
+                                PREG_SPLIT_DELIM_CAPTURE);
387 387
 			
388
-			# If in Markdown span mode, add a empty-string span-level hash 
389
-			# after each newline to prevent triggering any block element.
390
-			if ($span) {
391
-				$void = $this->hashPart("", ':');
392
-				$newline = "$void\n";
393
-				$parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
394
-			}
388
+            # If in Markdown span mode, add a empty-string span-level hash 
389
+            # after each newline to prevent triggering any block element.
390
+            if ($span) {
391
+                $void = $this->hashPart("", ':');
392
+                $newline = "$void\n";
393
+                $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
394
+            }
395 395
 			
396
-			$parsed .= $parts[0]; # Text before current tag.
396
+            $parsed .= $parts[0]; # Text before current tag.
397 397
 			
398
-			# If end of $text has been reached. Stop loop.
399
-			if (count($parts) < 3) {
400
-				$text = "";
401
-				break;
402
-			}
398
+            # If end of $text has been reached. Stop loop.
399
+            if (count($parts) < 3) {
400
+                $text = "";
401
+                break;
402
+            }
403 403
 			
404
-			$tag  = $parts[1]; # Tag to handle.
405
-			$text = $parts[2]; # Remaining text after current tag.
406
-			$tag_re = preg_quote($tag); # For use in a regular expression.
404
+            $tag  = $parts[1]; # Tag to handle.
405
+            $text = $parts[2]; # Remaining text after current tag.
406
+            $tag_re = preg_quote($tag); # For use in a regular expression.
407 407
 			
408
-			#
409
-			# Check for: Fenced code block marker.
410
-			# Note: need to recheck the whole tag to disambiguate backtick
411
-			# fences from code spans
412
-			#
413
-			if (preg_match('{^\n?([ ]{0,'.($indent+3).'})(~{3,}|`{3,})[ ]*(?:\.?[-_:a-zA-Z0-9]+|'.$this->id_class_attr_nocatch_re.')?[ ]*\n?$}', $tag, $capture)) {
414
-				# Fenced code block marker: find matching end marker.
415
-				$fence_indent = strlen($capture[1]); # use captured indent in re
416
-				$fence_re = $capture[2]; # use captured fence in re
417
-				if (preg_match('{^(?>.*\n)*?[ ]{'.($fence_indent).'}'.$fence_re.'[ ]*(?:\n|$)}', $text,
418
-					$matches)) 
419
-				{
420
-					# End marker found: pass text unchanged until marker.
421
-					$parsed .= $tag . $matches[0];
422
-					$text = substr($text, strlen($matches[0]));
423
-				}
424
-				else {
425
-					# No end marker: just skip it.
426
-					$parsed .= $tag;
427
-				}
428
-			}
429
-			#
430
-			# Check for: Indented code block.
431
-			#
432
-			else if ($tag{0} == "\n" || $tag{0} == " ") {
433
-				# Indented code block: pass it unchanged, will be handled 
434
-				# later.
435
-				$parsed .= $tag;
436
-			}
437
-			#
438
-			# Check for: Code span marker
439
-			# Note: need to check this after backtick fenced code blocks
440
-			#
441
-			else if ($tag{0} == "`") {
442
-				# Find corresponding end marker.
443
-				$tag_re = preg_quote($tag);
444
-				if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)'.$tag_re.'(?!`)}',
445
-					$text, $matches))
446
-				{
447
-					# End marker found: pass text unchanged until marker.
448
-					$parsed .= $tag . $matches[0];
449
-					$text = substr($text, strlen($matches[0]));
450
-				}
451
-				else {
452
-					# Unmatched marker: just skip it.
453
-					$parsed .= $tag;
454
-				}
455
-			}
456
-			#
457
-			# Check for: Opening Block level tag or
458
-			#            Opening Context Block tag (like ins and del) 
459
-			#               used as a block tag (tag is alone on it's line).
460
-			#
461
-			else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) ||
462
-				(	preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) &&
463
-					preg_match($newline_before_re, $parsed) &&
464
-					preg_match($newline_after_re, $text)	)
465
-				)
466
-			{
467
-				# Need to parse tag and following text using the HTML parser.
468
-				list($block_text, $text) = 
469
-					$this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
408
+            #
409
+            # Check for: Fenced code block marker.
410
+            # Note: need to recheck the whole tag to disambiguate backtick
411
+            # fences from code spans
412
+            #
413
+            if (preg_match('{^\n?([ ]{0,'.($indent+3).'})(~{3,}|`{3,})[ ]*(?:\.?[-_:a-zA-Z0-9]+|'.$this->id_class_attr_nocatch_re.')?[ ]*\n?$}', $tag, $capture)) {
414
+                # Fenced code block marker: find matching end marker.
415
+                $fence_indent = strlen($capture[1]); # use captured indent in re
416
+                $fence_re = $capture[2]; # use captured fence in re
417
+                if (preg_match('{^(?>.*\n)*?[ ]{'.($fence_indent).'}'.$fence_re.'[ ]*(?:\n|$)}', $text,
418
+                    $matches)) 
419
+                {
420
+                    # End marker found: pass text unchanged until marker.
421
+                    $parsed .= $tag . $matches[0];
422
+                    $text = substr($text, strlen($matches[0]));
423
+                }
424
+                else {
425
+                    # No end marker: just skip it.
426
+                    $parsed .= $tag;
427
+                }
428
+            }
429
+            #
430
+            # Check for: Indented code block.
431
+            #
432
+            else if ($tag{0} == "\n" || $tag{0} == " ") {
433
+                # Indented code block: pass it unchanged, will be handled 
434
+                # later.
435
+                $parsed .= $tag;
436
+            }
437
+            #
438
+            # Check for: Code span marker
439
+            # Note: need to check this after backtick fenced code blocks
440
+            #
441
+            else if ($tag{0} == "`") {
442
+                # Find corresponding end marker.
443
+                $tag_re = preg_quote($tag);
444
+                if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)'.$tag_re.'(?!`)}',
445
+                    $text, $matches))
446
+                {
447
+                    # End marker found: pass text unchanged until marker.
448
+                    $parsed .= $tag . $matches[0];
449
+                    $text = substr($text, strlen($matches[0]));
450
+                }
451
+                else {
452
+                    # Unmatched marker: just skip it.
453
+                    $parsed .= $tag;
454
+                }
455
+            }
456
+            #
457
+            # Check for: Opening Block level tag or
458
+            #            Opening Context Block tag (like ins and del) 
459
+            #               used as a block tag (tag is alone on it's line).
460
+            #
461
+            else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) ||
462
+                (	preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) &&
463
+                    preg_match($newline_before_re, $parsed) &&
464
+                    preg_match($newline_after_re, $text)	)
465
+                )
466
+            {
467
+                # Need to parse tag and following text using the HTML parser.
468
+                list($block_text, $text) = 
469
+                    $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
470 470
 				
471
-				# Make sure it stays outside of any paragraph by adding newlines.
472
-				$parsed .= "\n\n$block_text\n\n";
473
-			}
474
-			#
475
-			# Check for: Clean tag (like script, math)
476
-			#            HTML Comments, processing instructions.
477
-			#
478
-			else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) ||
479
-				$tag{1} == '!' || $tag{1} == '?')
480
-			{
481
-				# Need to parse tag and following text using the HTML parser.
482
-				# (don't check for markdown attribute)
483
-				list($block_text, $text) = 
484
-					$this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
471
+                # Make sure it stays outside of any paragraph by adding newlines.
472
+                $parsed .= "\n\n$block_text\n\n";
473
+            }
474
+            #
475
+            # Check for: Clean tag (like script, math)
476
+            #            HTML Comments, processing instructions.
477
+            #
478
+            else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) ||
479
+                $tag{1} == '!' || $tag{1} == '?')
480
+            {
481
+                # Need to parse tag and following text using the HTML parser.
482
+                # (don't check for markdown attribute)
483
+                list($block_text, $text) = 
484
+                    $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
485 485
 				
486
-				$parsed .= $block_text;
487
-			}
488
-			#
489
-			# Check for: Tag with same name as enclosing tag.
490
-			#
491
-			else if ($enclosing_tag_re !== '' &&
492
-				# Same name as enclosing tag.
493
-				preg_match('{^</?(?:'.$enclosing_tag_re.')\b}', $tag))
494
-			{
495
-				#
496
-				# Increase/decrease nested tag count.
497
-				#
498
-				if ($tag{1} == '/')						$depth--;
499
-				else if ($tag{strlen($tag)-2} != '/')	$depth++;
500
-
501
-				if ($depth < 0) {
502
-					#
503
-					# Going out of parent element. Clean up and break so we
504
-					# return to the calling function.
505
-					#
506
-					$text = $tag . $text;
507
-					break;
508
-				}
486
+                $parsed .= $block_text;
487
+            }
488
+            #
489
+            # Check for: Tag with same name as enclosing tag.
490
+            #
491
+            else if ($enclosing_tag_re !== '' &&
492
+                # Same name as enclosing tag.
493
+                preg_match('{^</?(?:'.$enclosing_tag_re.')\b}', $tag))
494
+            {
495
+                #
496
+                # Increase/decrease nested tag count.
497
+                #
498
+                if ($tag{1} == '/')						$depth--;
499
+                else if ($tag{strlen($tag)-2} != '/')	$depth++;
500
+
501
+                if ($depth < 0) {
502
+                    #
503
+                    # Going out of parent element. Clean up and break so we
504
+                    # return to the calling function.
505
+                    #
506
+                    $text = $tag . $text;
507
+                    break;
508
+                }
509 509
 				
510
-				$parsed .= $tag;
511
-			}
512
-			else {
513
-				$parsed .= $tag;
514
-			}
515
-		} while ($depth >= 0);
510
+                $parsed .= $tag;
511
+            }
512
+            else {
513
+                $parsed .= $tag;
514
+            }
515
+        } while ($depth >= 0);
516 516
 		
517
-		return array($parsed, $text);
518
-	}
519
-	protected function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
520
-	#
521
-	# Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
522
-	#
523
-	# *   Calls $hash_method to convert any blocks.
524
-	# *   Stops when the first opening tag closes.
525
-	# *   $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
526
-	#     (it is not inside clean tags)
527
-	#
528
-	# Returns an array of that form: ( processed text , remaining text )
529
-	#
530
-		if ($text === '') return array('', '');
517
+        return array($parsed, $text);
518
+    }
519
+    protected function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
520
+    #
521
+    # Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
522
+    #
523
+    # *   Calls $hash_method to convert any blocks.
524
+    # *   Stops when the first opening tag closes.
525
+    # *   $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
526
+    #     (it is not inside clean tags)
527
+    #
528
+    # Returns an array of that form: ( processed text , remaining text )
529
+    #
530
+        if ($text === '') return array('', '');
531 531
 		
532
-		# Regex to match `markdown` attribute inside of a tag.
533
-		$markdown_attr_re = '
532
+        # Regex to match `markdown` attribute inside of a tag.
533
+        $markdown_attr_re = '
534 534
 			{
535 535
 				\s*			# Eat whitespace before the `markdown` attribute
536 536
 				markdown
@@ -545,8 +545,8 @@  discard block
 block discarded – undo
545 545
 				()				# $4: make $3 always defined (avoid warnings)
546 546
 			}xs';
547 547
 		
548
-		# Regex to match any tag.
549
-		$tag_re = '{
548
+        # Regex to match any tag.
549
+        $tag_re = '{
550 550
 				(					# $2: Capture whole tag.
551 551
 					</?					# Any opening or closing tag.
552 552
 						[\w:$]+			# Tag name.
@@ -568,150 +568,150 @@  discard block
 block discarded – undo
568 568
 				)
569 569
 			}xs';
570 570
 		
571
-		$original_text = $text;		# Save original text in case of faliure.
571
+        $original_text = $text;		# Save original text in case of faliure.
572 572
 		
573
-		$depth		= 0;	# Current depth inside the tag tree.
574
-		$block_text	= "";	# Temporary text holder for current text.
575
-		$parsed		= "";	# Parsed text that will be returned.
576
-
577
-		#
578
-		# Get the name of the starting tag.
579
-		# (This pattern makes $base_tag_name_re safe without quoting.)
580
-		#
581
-		if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
582
-			$base_tag_name_re = $matches[1];
583
-
584
-		#
585
-		# Loop through every tag until we find the corresponding closing tag.
586
-		#
587
-		do {
588
-			#
589
-			# Split the text using the first $tag_match pattern found.
590
-			# Text before  pattern will be first in the array, text after
591
-			# pattern will be at the end, and between will be any catches made 
592
-			# by the pattern.
593
-			#
594
-			$parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
573
+        $depth		= 0;	# Current depth inside the tag tree.
574
+        $block_text	= "";	# Temporary text holder for current text.
575
+        $parsed		= "";	# Parsed text that will be returned.
576
+
577
+        #
578
+        # Get the name of the starting tag.
579
+        # (This pattern makes $base_tag_name_re safe without quoting.)
580
+        #
581
+        if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
582
+            $base_tag_name_re = $matches[1];
583
+
584
+        #
585
+        # Loop through every tag until we find the corresponding closing tag.
586
+        #
587
+        do {
588
+            #
589
+            # Split the text using the first $tag_match pattern found.
590
+            # Text before  pattern will be first in the array, text after
591
+            # pattern will be at the end, and between will be any catches made 
592
+            # by the pattern.
593
+            #
594
+            $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
595 595
 			
596
-			if (count($parts) < 3) {
597
-				#
598
-				# End of $text reached with unbalenced tag(s).
599
-				# In that case, we return original text unchanged and pass the
600
-				# first character as filtered to prevent an infinite loop in the 
601
-				# parent function.
602
-				#
603
-				return array($original_text{0}, substr($original_text, 1));
604
-			}
596
+            if (count($parts) < 3) {
597
+                #
598
+                # End of $text reached with unbalenced tag(s).
599
+                # In that case, we return original text unchanged and pass the
600
+                # first character as filtered to prevent an infinite loop in the 
601
+                # parent function.
602
+                #
603
+                return array($original_text{0}, substr($original_text, 1));
604
+            }
605 605
 			
606
-			$block_text .= $parts[0]; # Text before current tag.
607
-			$tag         = $parts[1]; # Tag to handle.
608
-			$text        = $parts[2]; # Remaining text after current tag.
606
+            $block_text .= $parts[0]; # Text before current tag.
607
+            $tag         = $parts[1]; # Tag to handle.
608
+            $text        = $parts[2]; # Remaining text after current tag.
609 609
 			
610
-			#
611
-			# Check for: Auto-close tag (like <hr/>)
612
-			#			 Comments and Processing Instructions.
613
-			#
614
-			if (preg_match('{^</?(?:'.$this->auto_close_tags_re.')\b}', $tag) ||
615
-				$tag{1} == '!' || $tag{1} == '?')
616
-			{
617
-				# Just add the tag to the block as if it was text.
618
-				$block_text .= $tag;
619
-			}
620
-			else {
621
-				#
622
-				# Increase/decrease nested tag count. Only do so if
623
-				# the tag's name match base tag's.
624
-				#
625
-				if (preg_match('{^</?'.$base_tag_name_re.'\b}', $tag)) {
626
-					if ($tag{1} == '/')						$depth--;
627
-					else if ($tag{strlen($tag)-2} != '/')	$depth++;
628
-				}
610
+            #
611
+            # Check for: Auto-close tag (like <hr/>)
612
+            #			 Comments and Processing Instructions.
613
+            #
614
+            if (preg_match('{^</?(?:'.$this->auto_close_tags_re.')\b}', $tag) ||
615
+                $tag{1} == '!' || $tag{1} == '?')
616
+            {
617
+                # Just add the tag to the block as if it was text.
618
+                $block_text .= $tag;
619
+            }
620
+            else {
621
+                #
622
+                # Increase/decrease nested tag count. Only do so if
623
+                # the tag's name match base tag's.
624
+                #
625
+                if (preg_match('{^</?'.$base_tag_name_re.'\b}', $tag)) {
626
+                    if ($tag{1} == '/')						$depth--;
627
+                    else if ($tag{strlen($tag)-2} != '/')	$depth++;
628
+                }
629 629
 				
630
-				#
631
-				# Check for `markdown="1"` attribute and handle it.
632
-				#
633
-				if ($md_attr && 
634
-					preg_match($markdown_attr_re, $tag, $attr_m) &&
635
-					preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
636
-				{
637
-					# Remove `markdown` attribute from opening tag.
638
-					$tag = preg_replace($markdown_attr_re, '', $tag);
630
+                #
631
+                # Check for `markdown="1"` attribute and handle it.
632
+                #
633
+                if ($md_attr && 
634
+                    preg_match($markdown_attr_re, $tag, $attr_m) &&
635
+                    preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
636
+                {
637
+                    # Remove `markdown` attribute from opening tag.
638
+                    $tag = preg_replace($markdown_attr_re, '', $tag);
639 639
 					
640
-					# Check if text inside this tag must be parsed in span mode.
641
-					$this->mode = $attr_m[2] . $attr_m[3];
642
-					$span_mode = $this->mode == 'span' || $this->mode != 'block' &&
643
-						preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag);
640
+                    # Check if text inside this tag must be parsed in span mode.
641
+                    $this->mode = $attr_m[2] . $attr_m[3];
642
+                    $span_mode = $this->mode == 'span' || $this->mode != 'block' &&
643
+                        preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag);
644 644
 					
645
-					# Calculate indent before tag.
646
-					if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
647
-						$strlen = $this->utf8_strlen;
648
-						$indent = $strlen($matches[1], 'UTF-8');
649
-					} else {
650
-						$indent = 0;
651
-					}
645
+                    # Calculate indent before tag.
646
+                    if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
647
+                        $strlen = $this->utf8_strlen;
648
+                        $indent = $strlen($matches[1], 'UTF-8');
649
+                    } else {
650
+                        $indent = 0;
651
+                    }
652 652
 					
653
-					# End preceding block with this tag.
654
-					$block_text .= $tag;
655
-					$parsed .= $this->$hash_method($block_text);
653
+                    # End preceding block with this tag.
654
+                    $block_text .= $tag;
655
+                    $parsed .= $this->$hash_method($block_text);
656 656
 					
657
-					# Get enclosing tag name for the ParseMarkdown function.
658
-					# (This pattern makes $tag_name_re safe without quoting.)
659
-					preg_match('/^<([\w:$]*)\b/', $tag, $matches);
660
-					$tag_name_re = $matches[1];
657
+                    # Get enclosing tag name for the ParseMarkdown function.
658
+                    # (This pattern makes $tag_name_re safe without quoting.)
659
+                    preg_match('/^<([\w:$]*)\b/', $tag, $matches);
660
+                    $tag_name_re = $matches[1];
661 661
 					
662
-					# Parse the content using the HTML-in-Markdown parser.
663
-					list ($block_text, $text)
664
-						= $this->_hashHTMLBlocks_inMarkdown($text, $indent, 
665
-							$tag_name_re, $span_mode);
662
+                    # Parse the content using the HTML-in-Markdown parser.
663
+                    list ($block_text, $text)
664
+                        = $this->_hashHTMLBlocks_inMarkdown($text, $indent, 
665
+                            $tag_name_re, $span_mode);
666 666
 					
667
-					# Outdent markdown text.
668
-					if ($indent > 0) {
669
-						$block_text = preg_replace("/^[ ]{1,$indent}/m", "", 
670
-													$block_text);
671
-					}
667
+                    # Outdent markdown text.
668
+                    if ($indent > 0) {
669
+                        $block_text = preg_replace("/^[ ]{1,$indent}/m", "", 
670
+                                                    $block_text);
671
+                    }
672 672
 					
673
-					# Append tag content to parsed text.
674
-					if (!$span_mode)	$parsed .= "\n\n$block_text\n\n";
675
-					else				$parsed .= "$block_text";
673
+                    # Append tag content to parsed text.
674
+                    if (!$span_mode)	$parsed .= "\n\n$block_text\n\n";
675
+                    else				$parsed .= "$block_text";
676 676
 					
677
-					# Start over with a new block.
678
-					$block_text = "";
679
-				}
680
-				else $block_text .= $tag;
681
-			}
677
+                    # Start over with a new block.
678
+                    $block_text = "";
679
+                }
680
+                else $block_text .= $tag;
681
+            }
682 682
 			
683
-		} while ($depth > 0);
683
+        } while ($depth > 0);
684 684
 		
685
-		#
686
-		# Hash last block text that wasn't processed inside the loop.
687
-		#
688
-		$parsed .= $this->$hash_method($block_text);
685
+        #
686
+        # Hash last block text that wasn't processed inside the loop.
687
+        #
688
+        $parsed .= $this->$hash_method($block_text);
689 689
 		
690
-		return array($parsed, $text);
691
-	}
692
-
693
-
694
-	protected function hashClean($text) {
695
-	#
696
-	# Called whenever a tag must be hashed when a function inserts a "clean" tag
697
-	# in $text, it passes through this function and is automaticaly escaped, 
698
-	# blocking invalid nested overlap.
699
-	#
700
-		return $this->hashPart($text, 'C');
701
-	}
702
-
703
-
704
-	protected function doAnchors($text) {
705
-	#
706
-	# Turn Markdown link shortcuts into XHTML <a> tags.
707
-	#
708
-		if ($this->in_anchor) return $text;
709
-		$this->in_anchor = true;
690
+        return array($parsed, $text);
691
+    }
692
+
693
+
694
+    protected function hashClean($text) {
695
+    #
696
+    # Called whenever a tag must be hashed when a function inserts a "clean" tag
697
+    # in $text, it passes through this function and is automaticaly escaped, 
698
+    # blocking invalid nested overlap.
699
+    #
700
+        return $this->hashPart($text, 'C');
701
+    }
702
+
703
+
704
+    protected function doAnchors($text) {
705
+    #
706
+    # Turn Markdown link shortcuts into XHTML <a> tags.
707
+    #
708
+        if ($this->in_anchor) return $text;
709
+        $this->in_anchor = true;
710 710
 		
711
-		#
712
-		# First, handle reference-style links: [link text] [id]
713
-		#
714
-		$text = preg_replace_callback('{
711
+        #
712
+        # First, handle reference-style links: [link text] [id]
713
+        #
714
+        $text = preg_replace_callback('{
715 715
 			(					# wrap whole match in $1
716 716
 			  \[
717 717
 				('.$this->nested_brackets_re.')	# link text = $2
@@ -725,12 +725,12 @@  discard block
 block discarded – undo
725 725
 			  \]
726 726
 			)
727 727
 			}xs',
728
-			array($this, '_doAnchors_reference_callback'), $text);
728
+            array($this, '_doAnchors_reference_callback'), $text);
729 729
 
730
-		#
731
-		# Next, inline-style links: [link text](url "optional title")
732
-		#
733
-		$text = preg_replace_callback('{
730
+        #
731
+        # Next, inline-style links: [link text](url "optional title")
732
+        #
733
+        $text = preg_replace_callback('{
734 734
 			(				# wrap whole match in $1
735 735
 			  \[
736 736
 				('.$this->nested_brackets_re.')	# link text = $2
@@ -753,98 +753,98 @@  discard block
 block discarded – undo
753 753
 			  (?:[ ]? '.$this->id_class_attr_catch_re.' )?	 # $8 = id/class attributes
754 754
 			)
755 755
 			}xs',
756
-			array($this, '_doAnchors_inline_callback'), $text);
757
-
758
-		#
759
-		# Last, handle reference-style shortcuts: [link text]
760
-		# These must come last in case you've also got [link text][1]
761
-		# or [link text](/foo)
762
-		#
763
-		$text = preg_replace_callback('{
756
+            array($this, '_doAnchors_inline_callback'), $text);
757
+
758
+        #
759
+        # Last, handle reference-style shortcuts: [link text]
760
+        # These must come last in case you've also got [link text][1]
761
+        # or [link text](/foo)
762
+        #
763
+        $text = preg_replace_callback('{
764 764
 			(					# wrap whole match in $1
765 765
 			  \[
766 766
 				([^\[\]]+)		# link text = $2; can\'t contain [ or ]
767 767
 			  \]
768 768
 			)
769 769
 			}xs',
770
-			array($this, '_doAnchors_reference_callback'), $text);
771
-
772
-		$this->in_anchor = false;
773
-		return $text;
774
-	}
775
-	protected function _doAnchors_reference_callback($matches) {
776
-		$whole_match =  $matches[1];
777
-		$link_text   =  $matches[2];
778
-		$link_id     =& $matches[3];
779
-
780
-		if ($link_id == "") {
781
-			# for shortcut links like [this][] or [this].
782
-			$link_id = $link_text;
783
-		}
770
+            array($this, '_doAnchors_reference_callback'), $text);
771
+
772
+        $this->in_anchor = false;
773
+        return $text;
774
+    }
775
+    protected function _doAnchors_reference_callback($matches) {
776
+        $whole_match =  $matches[1];
777
+        $link_text   =  $matches[2];
778
+        $link_id     =& $matches[3];
779
+
780
+        if ($link_id == "") {
781
+            # for shortcut links like [this][] or [this].
782
+            $link_id = $link_text;
783
+        }
784 784
 		
785
-		# lower-case and turn embedded newlines into spaces
786
-		$link_id = strtolower($link_id);
787
-		$link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
785
+        # lower-case and turn embedded newlines into spaces
786
+        $link_id = strtolower($link_id);
787
+        $link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
788 788
 
789
-		if (isset($this->urls[$link_id])) {
790
-			$url = $this->urls[$link_id];
791
-			$url = $this->encodeURLAttribute($url);
789
+        if (isset($this->urls[$link_id])) {
790
+            $url = $this->urls[$link_id];
791
+            $url = $this->encodeURLAttribute($url);
792 792
 			
793
-			$result = "<a href=\"$url\"";
794
-			if ( isset( $this->titles[$link_id] ) ) {
795
-				$title = $this->titles[$link_id];
796
-				$title = $this->encodeAttribute($title);
797
-				$result .=  " title=\"$title\"";
798
-			}
799
-			if (isset($this->ref_attr[$link_id]))
800
-				$result .= $this->ref_attr[$link_id];
793
+            $result = "<a href=\"$url\"";
794
+            if ( isset( $this->titles[$link_id] ) ) {
795
+                $title = $this->titles[$link_id];
796
+                $title = $this->encodeAttribute($title);
797
+                $result .=  " title=\"$title\"";
798
+            }
799
+            if (isset($this->ref_attr[$link_id]))
800
+                $result .= $this->ref_attr[$link_id];
801 801
 		
802
-			$link_text = $this->runSpanGamut($link_text);
803
-			$result .= ">$link_text</a>";
804
-			$result = $this->hashPart($result);
805
-		}
806
-		else {
807
-			$result = $whole_match;
808
-		}
809
-		return $result;
810
-	}
811
-	protected function _doAnchors_inline_callback($matches) {
812
-		$whole_match	=  $matches[1];
813
-		$link_text		=  $this->runSpanGamut($matches[2]);
814
-		$url			=  $matches[3] == '' ? $matches[4] : $matches[3];
815
-		$title			=& $matches[7];
816
-		$attr  = $this->doExtraAttributes("a", $dummy =& $matches[8]);
817
-
818
-		// if the URL was of the form <s p a c e s> it got caught by the HTML
819
-		// tag parser and hashed. Need to reverse the process before using the URL.
820
-		$unhashed = $this->unhash($url);
821
-		if ($unhashed != $url)
822
-			$url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
823
-
824
-		$url = $this->encodeURLAttribute($url);
825
-
826
-		$result = "<a href=\"$url\"";
827
-		if (isset($title)) {
828
-			$title = $this->encodeAttribute($title);
829
-			$result .=  " title=\"$title\"";
830
-		}
831
-		$result .= $attr;
802
+            $link_text = $this->runSpanGamut($link_text);
803
+            $result .= ">$link_text</a>";
804
+            $result = $this->hashPart($result);
805
+        }
806
+        else {
807
+            $result = $whole_match;
808
+        }
809
+        return $result;
810
+    }
811
+    protected function _doAnchors_inline_callback($matches) {
812
+        $whole_match	=  $matches[1];
813
+        $link_text		=  $this->runSpanGamut($matches[2]);
814
+        $url			=  $matches[3] == '' ? $matches[4] : $matches[3];
815
+        $title			=& $matches[7];
816
+        $attr  = $this->doExtraAttributes("a", $dummy =& $matches[8]);
817
+
818
+        // if the URL was of the form <s p a c e s> it got caught by the HTML
819
+        // tag parser and hashed. Need to reverse the process before using the URL.
820
+        $unhashed = $this->unhash($url);
821
+        if ($unhashed != $url)
822
+            $url = preg_replace('/^<(.*)>$/', '\1', $unhashed);
823
+
824
+        $url = $this->encodeURLAttribute($url);
825
+
826
+        $result = "<a href=\"$url\"";
827
+        if (isset($title)) {
828
+            $title = $this->encodeAttribute($title);
829
+            $result .=  " title=\"$title\"";
830
+        }
831
+        $result .= $attr;
832 832
 		
833
-		$link_text = $this->runSpanGamut($link_text);
834
-		$result .= ">$link_text</a>";
833
+        $link_text = $this->runSpanGamut($link_text);
834
+        $result .= ">$link_text</a>";
835 835
 
836
-		return $this->hashPart($result);
837
-	}
836
+        return $this->hashPart($result);
837
+    }
838 838
 
839 839
 
840
-	protected function doImages($text) {
841
-	#
842
-	# Turn Markdown image shortcuts into <img> tags.
843
-	#
844
-		#
845
-		# First, handle reference-style labeled images: ![alt text][id]
846
-		#
847
-		$text = preg_replace_callback('{
840
+    protected function doImages($text) {
841
+    #
842
+    # Turn Markdown image shortcuts into <img> tags.
843
+    #
844
+        #
845
+        # First, handle reference-style labeled images: ![alt text][id]
846
+        #
847
+        $text = preg_replace_callback('{
848 848
 			(				# wrap whole match in $1
849 849
 			  !\[
850 850
 				('.$this->nested_brackets_re.')		# alt text = $2
@@ -859,13 +859,13 @@  discard block
 block discarded – undo
859 859
 
860 860
 			)
861 861
 			}xs', 
862
-			array($this, '_doImages_reference_callback'), $text);
862
+            array($this, '_doImages_reference_callback'), $text);
863 863
 
864
-		#
865
-		# Next, handle inline images:  ![alt text](url "optional title")
866
-		# Don't forget: encode * and _
867
-		#
868
-		$text = preg_replace_callback('{
864
+        #
865
+        # Next, handle inline images:  ![alt text](url "optional title")
866
+        # Don't forget: encode * and _
867
+        #
868
+        $text = preg_replace_callback('{
869 869
 			(				# wrap whole match in $1
870 870
 			  !\[
871 871
 				('.$this->nested_brackets_re.')		# alt text = $2
@@ -889,88 +889,88 @@  discard block
 block discarded – undo
889 889
 			  (?:[ ]? '.$this->id_class_attr_catch_re.' )?	 # $8 = id/class attributes
890 890
 			)
891 891
 			}xs',
892
-			array($this, '_doImages_inline_callback'), $text);
893
-
894
-		return $text;
895
-	}
896
-	protected function _doImages_reference_callback($matches) {
897
-		$whole_match = $matches[1];
898
-		$alt_text    = $matches[2];
899
-		$link_id     = strtolower($matches[3]);
900
-
901
-		if ($link_id == "") {
902
-			$link_id = strtolower($alt_text); # for shortcut links like ![this][].
903
-		}
904
-
905
-		$alt_text = $this->encodeAttribute($alt_text);
906
-		if (isset($this->urls[$link_id])) {
907
-			$url = $this->encodeURLAttribute($this->urls[$link_id]);
908
-			$result = "<img src=\"$url\" alt=\"$alt_text\"";
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
-			$result .= $this->empty_element_suffix;
917
-			$result = $this->hashPart($result);
918
-		}
919
-		else {
920
-			# If there's no such link ID, leave intact:
921
-			$result = $whole_match;
922
-		}
923
-
924
-		return $result;
925
-	}
926
-	protected function _doImages_inline_callback($matches) {
927
-		$whole_match	= $matches[1];
928
-		$alt_text		= $matches[2];
929
-		$url			= $matches[3] == '' ? $matches[4] : $matches[3];
930
-		$title			=& $matches[7];
931
-		$attr  = $this->doExtraAttributes("img", $dummy =& $matches[8]);
932
-
933
-		$alt_text = $this->encodeAttribute($alt_text);
934
-		$url = $this->encodeURLAttribute($url);
935
-		$result = "<img src=\"$url\" alt=\"$alt_text\"";
936
-		if (isset($title)) {
937
-			$title = $this->encodeAttribute($title);
938
-			$result .=  " title=\"$title\""; # $title already quoted
939
-		}
940
-		$result .= $attr;
941
-		$result .= $this->empty_element_suffix;
942
-
943
-		return $this->hashPart($result);
944
-	}
945
-
946
-
947
-	protected function doHeaders($text) {
948
-	#
949
-	# Redefined to add id and class attribute support.
950
-	#
951
-		# Setext-style headers:
952
-		#	  Header 1  {#header1}
953
-		#	  ========
954
-		#  
955
-		#	  Header 2  {#header2 .class1 .class2}
956
-		#	  --------
957
-		#
958
-		$text = preg_replace_callback(
959
-			'{
892
+            array($this, '_doImages_inline_callback'), $text);
893
+
894
+        return $text;
895
+    }
896
+    protected function _doImages_reference_callback($matches) {
897
+        $whole_match = $matches[1];
898
+        $alt_text    = $matches[2];
899
+        $link_id     = strtolower($matches[3]);
900
+
901
+        if ($link_id == "") {
902
+            $link_id = strtolower($alt_text); # for shortcut links like ![this][].
903
+        }
904
+
905
+        $alt_text = $this->encodeAttribute($alt_text);
906
+        if (isset($this->urls[$link_id])) {
907
+            $url = $this->encodeURLAttribute($this->urls[$link_id]);
908
+            $result = "<img src=\"$url\" alt=\"$alt_text\"";
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
+            $result .= $this->empty_element_suffix;
917
+            $result = $this->hashPart($result);
918
+        }
919
+        else {
920
+            # If there's no such link ID, leave intact:
921
+            $result = $whole_match;
922
+        }
923
+
924
+        return $result;
925
+    }
926
+    protected function _doImages_inline_callback($matches) {
927
+        $whole_match	= $matches[1];
928
+        $alt_text		= $matches[2];
929
+        $url			= $matches[3] == '' ? $matches[4] : $matches[3];
930
+        $title			=& $matches[7];
931
+        $attr  = $this->doExtraAttributes("img", $dummy =& $matches[8]);
932
+
933
+        $alt_text = $this->encodeAttribute($alt_text);
934
+        $url = $this->encodeURLAttribute($url);
935
+        $result = "<img src=\"$url\" alt=\"$alt_text\"";
936
+        if (isset($title)) {
937
+            $title = $this->encodeAttribute($title);
938
+            $result .=  " title=\"$title\""; # $title already quoted
939
+        }
940
+        $result .= $attr;
941
+        $result .= $this->empty_element_suffix;
942
+
943
+        return $this->hashPart($result);
944
+    }
945
+
946
+
947
+    protected function doHeaders($text) {
948
+    #
949
+    # Redefined to add id and class attribute support.
950
+    #
951
+        # Setext-style headers:
952
+        #	  Header 1  {#header1}
953
+        #	  ========
954
+        #  
955
+        #	  Header 2  {#header2 .class1 .class2}
956
+        #	  --------
957
+        #
958
+        $text = preg_replace_callback(
959
+            '{
960 960
 				(^.+?)								# $1: Header text
961 961
 				(?:[ ]+ '.$this->id_class_attr_catch_re.' )?	 # $3 = id/class attributes
962 962
 				[ ]*\n(=+|-+)[ ]*\n+				# $3: Header footer
963 963
 			}mx',
964
-			array($this, '_doHeaders_callback_setext'), $text);
965
-
966
-		# atx-style headers:
967
-		#	# Header 1        {#header1}
968
-		#	## Header 2       {#header2}
969
-		#	## Header 2 with closing hashes ##  {#header3.class1.class2}
970
-		#	...
971
-		#	###### Header 6   {.class2}
972
-		#
973
-		$text = preg_replace_callback('{
964
+            array($this, '_doHeaders_callback_setext'), $text);
965
+
966
+        # atx-style headers:
967
+        #	# Header 1        {#header1}
968
+        #	## Header 2       {#header2}
969
+        #	## Header 2 with closing hashes ##  {#header3.class1.class2}
970
+        #	...
971
+        #	###### Header 6   {.class2}
972
+        #
973
+        $text = preg_replace_callback('{
974 974
 				^(\#{1,6})	# $1 = string of #\'s
975 975
 				[ ]*
976 976
 				(.+?)		# $2 = Header text
@@ -980,46 +980,46 @@  discard block
 block discarded – undo
980 980
 				[ ]*
981 981
 				\n+
982 982
 			}xm',
983
-			array($this, '_doHeaders_callback_atx'), $text);
984
-
985
-		return $text;
986
-	}
987
-	protected function _doHeaders_callback_setext($matches) {
988
-		if ($matches[3] == '-' && preg_match('{^- }', $matches[1]))
989
-			return $matches[0];
990
-
991
-		$level = $matches[3]{0} == '=' ? 1 : 2;
992
-
993
-		$defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[1]) : null;
994
-
995
-		$attr  = $this->doExtraAttributes("h$level", $dummy =& $matches[2], $defaultId);
996
-		$block = "<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>";
997
-		return "\n" . $this->hashBlock($block) . "\n\n";
998
-	}
999
-	protected function _doHeaders_callback_atx($matches) {
1000
-		$level = strlen($matches[1]);
1001
-
1002
-		$defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[2]) : null;
1003
-		$attr  = $this->doExtraAttributes("h$level", $dummy =& $matches[3], $defaultId);
1004
-		$block = "<h$level$attr>".$this->runSpanGamut($matches[2])."</h$level>";
1005
-		return "\n" . $this->hashBlock($block) . "\n\n";
1006
-	}
1007
-
1008
-
1009
-	protected function doTables($text) {
1010
-	#
1011
-	# Form HTML tables.
1012
-	#
1013
-		$less_than_tab = $this->tab_width - 1;
1014
-		#
1015
-		# Find tables with leading pipe.
1016
-		#
1017
-		#	| Header 1 | Header 2
1018
-		#	| -------- | --------
1019
-		#	| Cell 1   | Cell 2
1020
-		#	| Cell 3   | Cell 4
1021
-		#
1022
-		$text = preg_replace_callback('
983
+            array($this, '_doHeaders_callback_atx'), $text);
984
+
985
+        return $text;
986
+    }
987
+    protected function _doHeaders_callback_setext($matches) {
988
+        if ($matches[3] == '-' && preg_match('{^- }', $matches[1]))
989
+            return $matches[0];
990
+
991
+        $level = $matches[3]{0} == '=' ? 1 : 2;
992
+
993
+        $defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[1]) : null;
994
+
995
+        $attr  = $this->doExtraAttributes("h$level", $dummy =& $matches[2], $defaultId);
996
+        $block = "<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>";
997
+        return "\n" . $this->hashBlock($block) . "\n\n";
998
+    }
999
+    protected function _doHeaders_callback_atx($matches) {
1000
+        $level = strlen($matches[1]);
1001
+
1002
+        $defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[2]) : null;
1003
+        $attr  = $this->doExtraAttributes("h$level", $dummy =& $matches[3], $defaultId);
1004
+        $block = "<h$level$attr>".$this->runSpanGamut($matches[2])."</h$level>";
1005
+        return "\n" . $this->hashBlock($block) . "\n\n";
1006
+    }
1007
+
1008
+
1009
+    protected function doTables($text) {
1010
+    #
1011
+    # Form HTML tables.
1012
+    #
1013
+        $less_than_tab = $this->tab_width - 1;
1014
+        #
1015
+        # Find tables with leading pipe.
1016
+        #
1017
+        #	| Header 1 | Header 2
1018
+        #	| -------- | --------
1019
+        #	| Cell 1   | Cell 2
1020
+        #	| Cell 3   | Cell 4
1021
+        #
1022
+        $text = preg_replace_callback('
1023 1023
 			{
1024 1024
 				^							# Start of a line
1025 1025
 				[ ]{0,'.$less_than_tab.'}	# Allowed whitespace.
@@ -1037,17 +1037,17 @@  discard block
 block discarded – undo
1037 1037
 				)
1038 1038
 				(?=\n|\Z)					# Stop at final double newline.
1039 1039
 			}xm',
1040
-			array($this, '_doTable_leadingPipe_callback'), $text);
1040
+            array($this, '_doTable_leadingPipe_callback'), $text);
1041 1041
 		
1042
-		#
1043
-		# Find tables without leading pipe.
1044
-		#
1045
-		#	Header 1 | Header 2
1046
-		#	-------- | --------
1047
-		#	Cell 1   | Cell 2
1048
-		#	Cell 3   | Cell 4
1049
-		#
1050
-		$text = preg_replace_callback('
1042
+        #
1043
+        # Find tables without leading pipe.
1044
+        #
1045
+        #	Header 1 | Header 2
1046
+        #	-------- | --------
1047
+        #	Cell 1   | Cell 2
1048
+        #	Cell 3   | Cell 4
1049
+        #
1050
+        $text = preg_replace_callback('
1051 1051
 			{
1052 1052
 				^							# Start of a line
1053 1053
 				[ ]{0,'.$less_than_tab.'}	# Allowed whitespace.
@@ -1063,100 +1063,100 @@  discard block
 block discarded – undo
1063 1063
 				)
1064 1064
 				(?=\n|\Z)					# Stop at final double newline.
1065 1065
 			}xm',
1066
-			array($this, '_DoTable_callback'), $text);
1067
-
1068
-		return $text;
1069
-	}
1070
-	protected function _doTable_leadingPipe_callback($matches) {
1071
-		$head		= $matches[1];
1072
-		$underline	= $matches[2];
1073
-		$content	= $matches[3];
1066
+            array($this, '_DoTable_callback'), $text);
1067
+
1068
+        return $text;
1069
+    }
1070
+    protected function _doTable_leadingPipe_callback($matches) {
1071
+        $head		= $matches[1];
1072
+        $underline	= $matches[2];
1073
+        $content	= $matches[3];
1074 1074
 		
1075
-		# Remove leading pipe for each row.
1076
-		$content	= preg_replace('/^ *[|]/m', '', $content);
1075
+        # Remove leading pipe for each row.
1076
+        $content	= preg_replace('/^ *[|]/m', '', $content);
1077 1077
 		
1078
-		return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
1079
-	}
1080
-	protected function _doTable_makeAlignAttr($alignname)
1081
-	{
1082
-		if (empty($this->table_align_class_tmpl))
1083
-			return " align=\"$alignname\"";
1084
-
1085
-		$classname = str_replace('%%', $alignname, $this->table_align_class_tmpl);
1086
-		return " class=\"$classname\"";
1087
-	}
1088
-	protected function _doTable_callback($matches) {
1089
-		$head		= $matches[1];
1090
-		$underline	= $matches[2];
1091
-		$content	= $matches[3];
1092
-
1093
-		# Remove any tailing pipes for each line.
1094
-		$head		= preg_replace('/[|] *$/m', '', $head);
1095
-		$underline	= preg_replace('/[|] *$/m', '', $underline);
1096
-		$content	= preg_replace('/[|] *$/m', '', $content);
1078
+        return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
1079
+    }
1080
+    protected function _doTable_makeAlignAttr($alignname)
1081
+    {
1082
+        if (empty($this->table_align_class_tmpl))
1083
+            return " align=\"$alignname\"";
1084
+
1085
+        $classname = str_replace('%%', $alignname, $this->table_align_class_tmpl);
1086
+        return " class=\"$classname\"";
1087
+    }
1088
+    protected function _doTable_callback($matches) {
1089
+        $head		= $matches[1];
1090
+        $underline	= $matches[2];
1091
+        $content	= $matches[3];
1092
+
1093
+        # Remove any tailing pipes for each line.
1094
+        $head		= preg_replace('/[|] *$/m', '', $head);
1095
+        $underline	= preg_replace('/[|] *$/m', '', $underline);
1096
+        $content	= preg_replace('/[|] *$/m', '', $content);
1097 1097
 		
1098
-		# Reading alignement from header underline.
1099
-		$separators	= preg_split('/ *[|] */', $underline);
1100
-		foreach ($separators as $n => $s) {
1101
-			if (preg_match('/^ *-+: *$/', $s))
1102
-				$attr[$n] = $this->_doTable_makeAlignAttr('right');
1103
-			else if (preg_match('/^ *:-+: *$/', $s))
1104
-				$attr[$n] = $this->_doTable_makeAlignAttr('center');
1105
-			else if (preg_match('/^ *:-+ *$/', $s))
1106
-				$attr[$n] = $this->_doTable_makeAlignAttr('left');
1107
-			else
1108
-				$attr[$n] = '';
1109
-		}
1098
+        # Reading alignement from header underline.
1099
+        $separators	= preg_split('/ *[|] */', $underline);
1100
+        foreach ($separators as $n => $s) {
1101
+            if (preg_match('/^ *-+: *$/', $s))
1102
+                $attr[$n] = $this->_doTable_makeAlignAttr('right');
1103
+            else if (preg_match('/^ *:-+: *$/', $s))
1104
+                $attr[$n] = $this->_doTable_makeAlignAttr('center');
1105
+            else if (preg_match('/^ *:-+ *$/', $s))
1106
+                $attr[$n] = $this->_doTable_makeAlignAttr('left');
1107
+            else
1108
+                $attr[$n] = '';
1109
+        }
1110 1110
 		
1111
-		# Parsing span elements, including code spans, character escapes, 
1112
-		# and inline HTML tags, so that pipes inside those gets ignored.
1113
-		$head		= $this->parseSpan($head);
1114
-		$headers	= preg_split('/ *[|] */', $head);
1115
-		$col_count	= count($headers);
1116
-		$attr       = array_pad($attr, $col_count, '');
1111
+        # Parsing span elements, including code spans, character escapes, 
1112
+        # and inline HTML tags, so that pipes inside those gets ignored.
1113
+        $head		= $this->parseSpan($head);
1114
+        $headers	= preg_split('/ *[|] */', $head);
1115
+        $col_count	= count($headers);
1116
+        $attr       = array_pad($attr, $col_count, '');
1117 1117
 		
1118
-		# Write column headers.
1119
-		$text = "<table>\n";
1120
-		$text .= "<thead>\n";
1121
-		$text .= "<tr>\n";
1122
-		foreach ($headers as $n => $header)
1123
-			$text .= "  <th$attr[$n]>".$this->runSpanGamut(trim($header))."</th>\n";
1124
-		$text .= "</tr>\n";
1125
-		$text .= "</thead>\n";
1118
+        # Write column headers.
1119
+        $text = "<table>\n";
1120
+        $text .= "<thead>\n";
1121
+        $text .= "<tr>\n";
1122
+        foreach ($headers as $n => $header)
1123
+            $text .= "  <th$attr[$n]>".$this->runSpanGamut(trim($header))."</th>\n";
1124
+        $text .= "</tr>\n";
1125
+        $text .= "</thead>\n";
1126 1126
 		
1127
-		# Split content by row.
1128
-		$rows = explode("\n", trim($content, "\n"));
1127
+        # Split content by row.
1128
+        $rows = explode("\n", trim($content, "\n"));
1129 1129
 		
1130
-		$text .= "<tbody>\n";
1131
-		foreach ($rows as $row) {
1132
-			# Parsing span elements, including code spans, character escapes, 
1133
-			# and inline HTML tags, so that pipes inside those gets ignored.
1134
-			$row = $this->parseSpan($row);
1130
+        $text .= "<tbody>\n";
1131
+        foreach ($rows as $row) {
1132
+            # Parsing span elements, including code spans, character escapes, 
1133
+            # and inline HTML tags, so that pipes inside those gets ignored.
1134
+            $row = $this->parseSpan($row);
1135 1135
 			
1136
-			# Split row by cell.
1137
-			$row_cells = preg_split('/ *[|] */', $row, $col_count);
1138
-			$row_cells = array_pad($row_cells, $col_count, '');
1136
+            # Split row by cell.
1137
+            $row_cells = preg_split('/ *[|] */', $row, $col_count);
1138
+            $row_cells = array_pad($row_cells, $col_count, '');
1139 1139
 			
1140
-			$text .= "<tr>\n";
1141
-			foreach ($row_cells as $n => $cell)
1142
-				$text .= "  <td$attr[$n]>".$this->runSpanGamut(trim($cell))."</td>\n";
1143
-			$text .= "</tr>\n";
1144
-		}
1145
-		$text .= "</tbody>\n";
1146
-		$text .= "</table>";
1140
+            $text .= "<tr>\n";
1141
+            foreach ($row_cells as $n => $cell)
1142
+                $text .= "  <td$attr[$n]>".$this->runSpanGamut(trim($cell))."</td>\n";
1143
+            $text .= "</tr>\n";
1144
+        }
1145
+        $text .= "</tbody>\n";
1146
+        $text .= "</table>";
1147 1147
 		
1148
-		return $this->hashBlock($text) . "\n";
1149
-	}
1148
+        return $this->hashBlock($text) . "\n";
1149
+    }
1150 1150
 
1151 1151
 	
1152
-	protected function doDefLists($text) {
1153
-	#
1154
-	# Form HTML definition lists.
1155
-	#
1156
-		$less_than_tab = $this->tab_width - 1;
1157
-
1158
-		# Re-usable pattern to match any entire dl list:
1159
-		$whole_list_re = '(?>
1152
+    protected function doDefLists($text) {
1153
+    #
1154
+    # Form HTML definition lists.
1155
+    #
1156
+        $less_than_tab = $this->tab_width - 1;
1157
+
1158
+        # Re-usable pattern to match any entire dl list:
1159
+        $whole_list_re = '(?>
1160 1160
 			(								# $1 = whole list
1161 1161
 			  (								# $2
1162 1162
 				[ ]{0,'.$less_than_tab.'}
@@ -1183,38 +1183,38 @@  discard block
 block discarded – undo
1183 1183
 			)
1184 1184
 		)'; // mx
1185 1185
 
1186
-		$text = preg_replace_callback('{
1186
+        $text = preg_replace_callback('{
1187 1187
 				(?>\A\n?|(?<=\n\n))
1188 1188
 				'.$whole_list_re.'
1189 1189
 			}mx',
1190
-			array($this, '_doDefLists_callback'), $text);
1190
+            array($this, '_doDefLists_callback'), $text);
1191 1191
 
1192
-		return $text;
1193
-	}
1194
-	protected function _doDefLists_callback($matches) {
1195
-		# Re-usable patterns to match list item bullets and number markers:
1196
-		$list = $matches[1];
1192
+        return $text;
1193
+    }
1194
+    protected function _doDefLists_callback($matches) {
1195
+        # Re-usable patterns to match list item bullets and number markers:
1196
+        $list = $matches[1];
1197 1197
 		
1198
-		# Turn double returns into triple returns, so that we can make a
1199
-		# paragraph for the last item in a list, if necessary:
1200
-		$result = trim($this->processDefListItems($list));
1201
-		$result = "<dl>\n" . $result . "\n</dl>";
1202
-		return $this->hashBlock($result) . "\n\n";
1203
-	}
1204
-
1205
-
1206
-	protected function processDefListItems($list_str) {
1207
-	#
1208
-	#	Process the contents of a single definition list, splitting it
1209
-	#	into individual term and definition list items.
1210
-	#
1211
-		$less_than_tab = $this->tab_width - 1;
1198
+        # Turn double returns into triple returns, so that we can make a
1199
+        # paragraph for the last item in a list, if necessary:
1200
+        $result = trim($this->processDefListItems($list));
1201
+        $result = "<dl>\n" . $result . "\n</dl>";
1202
+        return $this->hashBlock($result) . "\n\n";
1203
+    }
1204
+
1205
+
1206
+    protected function processDefListItems($list_str) {
1207
+    #
1208
+    #	Process the contents of a single definition list, splitting it
1209
+    #	into individual term and definition list items.
1210
+    #
1211
+        $less_than_tab = $this->tab_width - 1;
1212 1212
 		
1213
-		# trim trailing blank lines:
1214
-		$list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
1213
+        # trim trailing blank lines:
1214
+        $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
1215 1215
 
1216
-		# Process definition terms.
1217
-		$list_str = preg_replace_callback('{
1216
+        # Process definition terms.
1217
+        $list_str = preg_replace_callback('{
1218 1218
 			(?>\A\n?|\n\n+)					# leading line
1219 1219
 			(								# definition terms = $1
1220 1220
 				[ ]{0,'.$less_than_tab.'}	# leading whitespace
@@ -1225,10 +1225,10 @@  discard block
 block discarded – undo
1225 1225
 			(?=\n?[ ]{0,3}:[ ])				# lookahead for following line feed 
1226 1226
 											#   with a definition mark.
1227 1227
 			}xm',
1228
-			array($this, '_processDefListItems_callback_dt'), $list_str);
1228
+            array($this, '_processDefListItems_callback_dt'), $list_str);
1229 1229
 
1230
-		# Process actual definitions.
1231
-		$list_str = preg_replace_callback('{
1230
+        # Process actual definitions.
1231
+        $list_str = preg_replace_callback('{
1232 1232
 			\n(\n+)?						# leading line = $1
1233 1233
 			(								# marker space = $2
1234 1234
 				[ ]{0,'.$less_than_tab.'}	# whitespace before colon
@@ -1242,50 +1242,50 @@  discard block
 block discarded – undo
1242 1242
 				)						
1243 1243
 			)					
1244 1244
 			}xm',
1245
-			array($this, '_processDefListItems_callback_dd'), $list_str);
1246
-
1247
-		return $list_str;
1248
-	}
1249
-	protected function _processDefListItems_callback_dt($matches) {
1250
-		$terms = explode("\n", trim($matches[1]));
1251
-		$text = '';
1252
-		foreach ($terms as $term) {
1253
-			$term = $this->runSpanGamut(trim($term));
1254
-			$text .= "\n<dt>" . $term . "</dt>";
1255
-		}
1256
-		return $text . "\n";
1257
-	}
1258
-	protected function _processDefListItems_callback_dd($matches) {
1259
-		$leading_line	= $matches[1];
1260
-		$marker_space	= $matches[2];
1261
-		$def			= $matches[3];
1262
-
1263
-		if ($leading_line || preg_match('/\n{2,}/', $def)) {
1264
-			# Replace marker with the appropriate whitespace indentation
1265
-			$def = str_repeat(' ', strlen($marker_space)) . $def;
1266
-			$def = $this->runBlockGamut($this->outdent($def . "\n\n"));
1267
-			$def = "\n". $def ."\n";
1268
-		}
1269
-		else {
1270
-			$def = rtrim($def);
1271
-			$def = $this->runSpanGamut($this->outdent($def));
1272
-		}
1273
-
1274
-		return "\n<dd>" . $def . "</dd>\n";
1275
-	}
1276
-
1277
-
1278
-	protected function doFencedCodeBlocks($text) {
1279
-	#
1280
-	# Adding the fenced code block syntax to regular Markdown:
1281
-	#
1282
-	# ~~~
1283
-	# Code block
1284
-	# ~~~
1285
-	#
1286
-		$less_than_tab = $this->tab_width;
1245
+            array($this, '_processDefListItems_callback_dd'), $list_str);
1246
+
1247
+        return $list_str;
1248
+    }
1249
+    protected function _processDefListItems_callback_dt($matches) {
1250
+        $terms = explode("\n", trim($matches[1]));
1251
+        $text = '';
1252
+        foreach ($terms as $term) {
1253
+            $term = $this->runSpanGamut(trim($term));
1254
+            $text .= "\n<dt>" . $term . "</dt>";
1255
+        }
1256
+        return $text . "\n";
1257
+    }
1258
+    protected function _processDefListItems_callback_dd($matches) {
1259
+        $leading_line	= $matches[1];
1260
+        $marker_space	= $matches[2];
1261
+        $def			= $matches[3];
1262
+
1263
+        if ($leading_line || preg_match('/\n{2,}/', $def)) {
1264
+            # Replace marker with the appropriate whitespace indentation
1265
+            $def = str_repeat(' ', strlen($marker_space)) . $def;
1266
+            $def = $this->runBlockGamut($this->outdent($def . "\n\n"));
1267
+            $def = "\n". $def ."\n";
1268
+        }
1269
+        else {
1270
+            $def = rtrim($def);
1271
+            $def = $this->runSpanGamut($this->outdent($def));
1272
+        }
1273
+
1274
+        return "\n<dd>" . $def . "</dd>\n";
1275
+    }
1276
+
1277
+
1278
+    protected function doFencedCodeBlocks($text) {
1279
+    #
1280
+    # Adding the fenced code block syntax to regular Markdown:
1281
+    #
1282
+    # ~~~
1283
+    # Code block
1284
+    # ~~~
1285
+    #
1286
+        $less_than_tab = $this->tab_width;
1287 1287
 		
1288
-		$text = preg_replace_callback('{
1288
+        $text = preg_replace_callback('{
1289 1289
 				(?:\n|\A)
1290 1290
 				# 1: Opening marker
1291 1291
 				(
@@ -1310,105 +1310,105 @@  discard block
 block discarded – undo
1310 1310
 				# Closing marker.
1311 1311
 				\1 [ ]* (?= \n )
1312 1312
 			}xm',
1313
-			array($this, '_doFencedCodeBlocks_callback'), $text);
1314
-
1315
-		return $text;
1316
-	}
1317
-	protected function _doFencedCodeBlocks_callback($matches) {
1318
-		$classname =& $matches[2];
1319
-		$attrs     =& $matches[3];
1320
-		$codeblock = $matches[4];
1321
-		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
1322
-		$codeblock = preg_replace_callback('/^\n+/',
1323
-			array($this, '_doFencedCodeBlocks_newlines'), $codeblock);
1324
-
1325
-		if ($classname != "") {
1326
-			if ($classname{0} == '.')
1327
-				$classname = substr($classname, 1);
1328
-			$attr_str = ' class="'.$this->code_class_prefix.$classname.'"';
1329
-		} else {
1330
-			$attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs);
1331
-		}
1332
-		$pre_attr_str  = $this->code_attr_on_pre ? $attr_str : '';
1333
-		$code_attr_str = $this->code_attr_on_pre ? '' : $attr_str;
1334
-		$codeblock  = "<pre$pre_attr_str><code$code_attr_str>$codeblock</code></pre>";
1313
+            array($this, '_doFencedCodeBlocks_callback'), $text);
1314
+
1315
+        return $text;
1316
+    }
1317
+    protected function _doFencedCodeBlocks_callback($matches) {
1318
+        $classname =& $matches[2];
1319
+        $attrs     =& $matches[3];
1320
+        $codeblock = $matches[4];
1321
+        $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
1322
+        $codeblock = preg_replace_callback('/^\n+/',
1323
+            array($this, '_doFencedCodeBlocks_newlines'), $codeblock);
1324
+
1325
+        if ($classname != "") {
1326
+            if ($classname{0} == '.')
1327
+                $classname = substr($classname, 1);
1328
+            $attr_str = ' class="'.$this->code_class_prefix.$classname.'"';
1329
+        } else {
1330
+            $attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs);
1331
+        }
1332
+        $pre_attr_str  = $this->code_attr_on_pre ? $attr_str : '';
1333
+        $code_attr_str = $this->code_attr_on_pre ? '' : $attr_str;
1334
+        $codeblock  = "<pre$pre_attr_str><code$code_attr_str>$codeblock</code></pre>";
1335 1335
 		
1336
-		return "\n\n".$this->hashBlock($codeblock)."\n\n";
1337
-	}
1338
-	protected function _doFencedCodeBlocks_newlines($matches) {
1339
-		return str_repeat("<br$this->empty_element_suffix", 
1340
-			strlen($matches[0]));
1341
-	}
1342
-
1343
-
1344
-	#
1345
-	# Redefining emphasis markers so that emphasis by underscore does not
1346
-	# work in the middle of a word.
1347
-	#
1348
-	protected $em_relist = array(
1349
-		''  => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?![\.,:;]?\s)',
1350
-		'*' => '(?<![\s*])\*(?!\*)',
1351
-		'_' => '(?<![\s_])_(?![a-zA-Z0-9_])',
1352
-		);
1353
-	protected $strong_relist = array(
1354
-		''   => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?![\.,:;]?\s)',
1355
-		'**' => '(?<![\s*])\*\*(?!\*)',
1356
-		'__' => '(?<![\s_])__(?![a-zA-Z0-9_])',
1357
-		);
1358
-	protected $em_strong_relist = array(
1359
-		''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?![\.,:;]?\s)',
1360
-		'***' => '(?<![\s*])\*\*\*(?!\*)',
1361
-		'___' => '(?<![\s_])___(?![a-zA-Z0-9_])',
1362
-		);
1363
-
1364
-
1365
-	protected function formParagraphs($text) {
1366
-	#
1367
-	#	Params:
1368
-	#		$text - string to process with html <p> tags
1369
-	#
1370
-		# Strip leading and trailing lines:
1371
-		$text = preg_replace('/\A\n+|\n+\z/', '', $text);
1336
+        return "\n\n".$this->hashBlock($codeblock)."\n\n";
1337
+    }
1338
+    protected function _doFencedCodeBlocks_newlines($matches) {
1339
+        return str_repeat("<br$this->empty_element_suffix", 
1340
+            strlen($matches[0]));
1341
+    }
1342
+
1343
+
1344
+    #
1345
+    # Redefining emphasis markers so that emphasis by underscore does not
1346
+    # work in the middle of a word.
1347
+    #
1348
+    protected $em_relist = array(
1349
+        ''  => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?![\.,:;]?\s)',
1350
+        '*' => '(?<![\s*])\*(?!\*)',
1351
+        '_' => '(?<![\s_])_(?![a-zA-Z0-9_])',
1352
+        );
1353
+    protected $strong_relist = array(
1354
+        ''   => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?![\.,:;]?\s)',
1355
+        '**' => '(?<![\s*])\*\*(?!\*)',
1356
+        '__' => '(?<![\s_])__(?![a-zA-Z0-9_])',
1357
+        );
1358
+    protected $em_strong_relist = array(
1359
+        ''    => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?![\.,:;]?\s)',
1360
+        '***' => '(?<![\s*])\*\*\*(?!\*)',
1361
+        '___' => '(?<![\s_])___(?![a-zA-Z0-9_])',
1362
+        );
1363
+
1364
+
1365
+    protected function formParagraphs($text) {
1366
+    #
1367
+    #	Params:
1368
+    #		$text - string to process with html <p> tags
1369
+    #
1370
+        # Strip leading and trailing lines:
1371
+        $text = preg_replace('/\A\n+|\n+\z/', '', $text);
1372 1372
 		
1373
-		$grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
1373
+        $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
1374 1374
 
1375
-		#
1376
-		# Wrap <p> tags and unhashify HTML blocks
1377
-		#
1378
-		foreach ($grafs as $key => $value) {
1379
-			$value = trim($this->runSpanGamut($value));
1375
+        #
1376
+        # Wrap <p> tags and unhashify HTML blocks
1377
+        #
1378
+        foreach ($grafs as $key => $value) {
1379
+            $value = trim($this->runSpanGamut($value));
1380 1380
 			
1381
-			# Check if this should be enclosed in a paragraph.
1382
-			# Clean tag hashes & block tag hashes are left alone.
1383
-			$is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
1381
+            # Check if this should be enclosed in a paragraph.
1382
+            # Clean tag hashes & block tag hashes are left alone.
1383
+            $is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
1384 1384
 			
1385
-			if ($is_p) {
1386
-				$value = "<p>$value</p>";
1387
-			}
1388
-			$grafs[$key] = $value;
1389
-		}
1385
+            if ($is_p) {
1386
+                $value = "<p>$value</p>";
1387
+            }
1388
+            $grafs[$key] = $value;
1389
+        }
1390 1390
 		
1391
-		# Join grafs in one text, then unhash HTML tags. 
1392
-		$text = implode("\n\n", $grafs);
1391
+        # Join grafs in one text, then unhash HTML tags. 
1392
+        $text = implode("\n\n", $grafs);
1393 1393
 		
1394
-		# Finish by removing any tag hashes still present in $text.
1395
-		$text = $this->unhash($text);
1394
+        # Finish by removing any tag hashes still present in $text.
1395
+        $text = $this->unhash($text);
1396 1396
 		
1397
-		return $text;
1398
-	}
1397
+        return $text;
1398
+    }
1399 1399
 	
1400 1400
 	
1401
-	### Footnotes
1401
+    ### Footnotes
1402 1402
 	
1403
-	protected function stripFootnotes($text) {
1404
-	#
1405
-	# Strips link definitions from text, stores the URLs and titles in
1406
-	# hash references.
1407
-	#
1408
-		$less_than_tab = $this->tab_width - 1;
1409
-
1410
-		# Link defs are in the form: [^id]: url "optional title"
1411
-		$text = preg_replace_callback('{
1403
+    protected function stripFootnotes($text) {
1404
+    #
1405
+    # Strips link definitions from text, stores the URLs and titles in
1406
+    # hash references.
1407
+    #
1408
+        $less_than_tab = $this->tab_width - 1;
1409
+
1410
+        # Link defs are in the form: [^id]: url "optional title"
1411
+        $text = preg_replace_callback('{
1412 1412
 			^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?:	# note_id = $1
1413 1413
 			  [ ]*
1414 1414
 			  \n?					# maybe *one* newline
@@ -1423,192 +1423,192 @@  discard block
 block discarded – undo
1423 1423
 				)*
1424 1424
 			)		
1425 1425
 			}xm',
1426
-			array($this, '_stripFootnotes_callback'),
1427
-			$text);
1428
-		return $text;
1429
-	}
1430
-	protected function _stripFootnotes_callback($matches) {
1431
-		$note_id = $this->fn_id_prefix . $matches[1];
1432
-		$this->footnotes[$note_id] = $this->outdent($matches[2]);
1433
-		return ''; # String that will replace the block
1434
-	}
1435
-
1436
-
1437
-	protected function doFootnotes($text) {
1438
-	#
1439
-	# Replace footnote references in $text [^id] with a special text-token 
1440
-	# which will be replaced by the actual footnote marker in appendFootnotes.
1441
-	#
1442
-		if (!$this->in_anchor) {
1443
-			$text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
1444
-		}
1445
-		return $text;
1446
-	}
1426
+            array($this, '_stripFootnotes_callback'),
1427
+            $text);
1428
+        return $text;
1429
+    }
1430
+    protected function _stripFootnotes_callback($matches) {
1431
+        $note_id = $this->fn_id_prefix . $matches[1];
1432
+        $this->footnotes[$note_id] = $this->outdent($matches[2]);
1433
+        return ''; # String that will replace the block
1434
+    }
1435
+
1436
+
1437
+    protected function doFootnotes($text) {
1438
+    #
1439
+    # Replace footnote references in $text [^id] with a special text-token 
1440
+    # which will be replaced by the actual footnote marker in appendFootnotes.
1441
+    #
1442
+        if (!$this->in_anchor) {
1443
+            $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
1444
+        }
1445
+        return $text;
1446
+    }
1447 1447
 
1448 1448
 	
1449
-	protected function appendFootnotes($text) {
1450
-	#
1451
-	# Append footnote list to text.
1452
-	#
1453
-		$text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', 
1454
-			array($this, '_appendFootnotes_callback'), $text);
1449
+    protected function appendFootnotes($text) {
1450
+    #
1451
+    # Append footnote list to text.
1452
+    #
1453
+        $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', 
1454
+            array($this, '_appendFootnotes_callback'), $text);
1455 1455
 	
1456
-		if (!empty($this->footnotes_ordered)) {
1457
-			$text .= "\n\n";
1458
-			$text .= "<div class=\"footnotes\">\n";
1459
-			$text .= "<hr". $this->empty_element_suffix ."\n";
1460
-			$text .= "<ol>\n\n";
1461
-
1462
-			$attr = "";
1463
-			if ($this->fn_backlink_class != "") {
1464
-				$class = $this->fn_backlink_class;
1465
-				$class = $this->encodeAttribute($class);
1466
-				$attr .= " class=\"$class\"";
1467
-			}
1468
-			if ($this->fn_backlink_title != "") {
1469
-				$title = $this->fn_backlink_title;
1470
-				$title = $this->encodeAttribute($title);
1471
-				$attr .= " title=\"$title\"";
1472
-			}
1473
-			$num = 0;
1456
+        if (!empty($this->footnotes_ordered)) {
1457
+            $text .= "\n\n";
1458
+            $text .= "<div class=\"footnotes\">\n";
1459
+            $text .= "<hr". $this->empty_element_suffix ."\n";
1460
+            $text .= "<ol>\n\n";
1461
+
1462
+            $attr = "";
1463
+            if ($this->fn_backlink_class != "") {
1464
+                $class = $this->fn_backlink_class;
1465
+                $class = $this->encodeAttribute($class);
1466
+                $attr .= " class=\"$class\"";
1467
+            }
1468
+            if ($this->fn_backlink_title != "") {
1469
+                $title = $this->fn_backlink_title;
1470
+                $title = $this->encodeAttribute($title);
1471
+                $attr .= " title=\"$title\"";
1472
+            }
1473
+            $num = 0;
1474 1474
 			
1475
-			while (!empty($this->footnotes_ordered)) {
1476
-				$footnote = reset($this->footnotes_ordered);
1477
-				$note_id = key($this->footnotes_ordered);
1478
-				unset($this->footnotes_ordered[$note_id]);
1479
-				$ref_count = $this->footnotes_ref_count[$note_id];
1480
-				unset($this->footnotes_ref_count[$note_id]);
1481
-				unset($this->footnotes[$note_id]);
1475
+            while (!empty($this->footnotes_ordered)) {
1476
+                $footnote = reset($this->footnotes_ordered);
1477
+                $note_id = key($this->footnotes_ordered);
1478
+                unset($this->footnotes_ordered[$note_id]);
1479
+                $ref_count = $this->footnotes_ref_count[$note_id];
1480
+                unset($this->footnotes_ref_count[$note_id]);
1481
+                unset($this->footnotes[$note_id]);
1482 1482
 				
1483
-				$footnote .= "\n"; # Need to append newline before parsing.
1484
-				$footnote = $this->runBlockGamut("$footnote\n");				
1485
-				$footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', 
1486
-					array($this, '_appendFootnotes_callback'), $footnote);
1483
+                $footnote .= "\n"; # Need to append newline before parsing.
1484
+                $footnote = $this->runBlockGamut("$footnote\n");				
1485
+                $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', 
1486
+                    array($this, '_appendFootnotes_callback'), $footnote);
1487 1487
 				
1488
-				$attr = str_replace("%%", ++$num, $attr);
1489
-				$note_id = $this->encodeAttribute($note_id);
1490
-
1491
-				# Prepare backlink, multiple backlinks if multiple references
1492
-				$backlink = "<a href=\"#fnref:$note_id\"$attr>&#8617;</a>";
1493
-				for ($ref_num = 2; $ref_num <= $ref_count; ++$ref_num) {
1494
-					$backlink .= " <a href=\"#fnref$ref_num:$note_id\"$attr>&#8617;</a>";
1495
-				}
1496
-				# Add backlink to last paragraph; create new paragraph if needed.
1497
-				if (preg_match('{</p>$}', $footnote)) {
1498
-					$footnote = substr($footnote, 0, -4) . "&#160;$backlink</p>";
1499
-				} else {
1500
-					$footnote .= "\n\n<p>$backlink</p>";
1501
-				}
1488
+                $attr = str_replace("%%", ++$num, $attr);
1489
+                $note_id = $this->encodeAttribute($note_id);
1490
+
1491
+                # Prepare backlink, multiple backlinks if multiple references
1492
+                $backlink = "<a href=\"#fnref:$note_id\"$attr>&#8617;</a>";
1493
+                for ($ref_num = 2; $ref_num <= $ref_count; ++$ref_num) {
1494
+                    $backlink .= " <a href=\"#fnref$ref_num:$note_id\"$attr>&#8617;</a>";
1495
+                }
1496
+                # Add backlink to last paragraph; create new paragraph if needed.
1497
+                if (preg_match('{</p>$}', $footnote)) {
1498
+                    $footnote = substr($footnote, 0, -4) . "&#160;$backlink</p>";
1499
+                } else {
1500
+                    $footnote .= "\n\n<p>$backlink</p>";
1501
+                }
1502 1502
 				
1503
-				$text .= "<li id=\"fn:$note_id\">\n";
1504
-				$text .= $footnote . "\n";
1505
-				$text .= "</li>\n\n";
1506
-			}
1503
+                $text .= "<li id=\"fn:$note_id\">\n";
1504
+                $text .= $footnote . "\n";
1505
+                $text .= "</li>\n\n";
1506
+            }
1507 1507
 			
1508
-			$text .= "</ol>\n";
1509
-			$text .= "</div>";
1510
-		}
1511
-		return $text;
1512
-	}
1513
-	protected function _appendFootnotes_callback($matches) {
1514
-		$node_id = $this->fn_id_prefix . $matches[1];
1508
+            $text .= "</ol>\n";
1509
+            $text .= "</div>";
1510
+        }
1511
+        return $text;
1512
+    }
1513
+    protected function _appendFootnotes_callback($matches) {
1514
+        $node_id = $this->fn_id_prefix . $matches[1];
1515 1515
 		
1516
-		# Create footnote marker only if it has a corresponding footnote *and*
1517
-		# the footnote hasn't been used by another marker.
1518
-		if (isset($this->footnotes[$node_id])) {
1519
-			$num =& $this->footnotes_numbers[$node_id];
1520
-			if (!isset($num)) {
1521
-				# Transfer footnote content to the ordered list and give it its
1522
-				# number
1523
-				$this->footnotes_ordered[$node_id] = $this->footnotes[$node_id];
1524
-				$this->footnotes_ref_count[$node_id] = 1;
1525
-				$num = $this->footnote_counter++;
1526
-				$ref_count_mark = '';
1527
-			} else {
1528
-				$ref_count_mark = $this->footnotes_ref_count[$node_id] += 1;
1529
-			}
1530
-
1531
-			$attr = "";
1532
-			if ($this->fn_link_class != "") {
1533
-				$class = $this->fn_link_class;
1534
-				$class = $this->encodeAttribute($class);
1535
-				$attr .= " class=\"$class\"";
1536
-			}
1537
-			if ($this->fn_link_title != "") {
1538
-				$title = $this->fn_link_title;
1539
-				$title = $this->encodeAttribute($title);
1540
-				$attr .= " title=\"$title\"";
1541
-			}
1516
+        # Create footnote marker only if it has a corresponding footnote *and*
1517
+        # the footnote hasn't been used by another marker.
1518
+        if (isset($this->footnotes[$node_id])) {
1519
+            $num =& $this->footnotes_numbers[$node_id];
1520
+            if (!isset($num)) {
1521
+                # Transfer footnote content to the ordered list and give it its
1522
+                # number
1523
+                $this->footnotes_ordered[$node_id] = $this->footnotes[$node_id];
1524
+                $this->footnotes_ref_count[$node_id] = 1;
1525
+                $num = $this->footnote_counter++;
1526
+                $ref_count_mark = '';
1527
+            } else {
1528
+                $ref_count_mark = $this->footnotes_ref_count[$node_id] += 1;
1529
+            }
1530
+
1531
+            $attr = "";
1532
+            if ($this->fn_link_class != "") {
1533
+                $class = $this->fn_link_class;
1534
+                $class = $this->encodeAttribute($class);
1535
+                $attr .= " class=\"$class\"";
1536
+            }
1537
+            if ($this->fn_link_title != "") {
1538
+                $title = $this->fn_link_title;
1539
+                $title = $this->encodeAttribute($title);
1540
+                $attr .= " title=\"$title\"";
1541
+            }
1542 1542
 			
1543
-			$attr = str_replace("%%", $num, $attr);
1544
-			$node_id = $this->encodeAttribute($node_id);
1543
+            $attr = str_replace("%%", $num, $attr);
1544
+            $node_id = $this->encodeAttribute($node_id);
1545 1545
 			
1546
-			return
1547
-				"<sup id=\"fnref$ref_count_mark:$node_id\">".
1548
-				"<a href=\"#fn:$node_id\"$attr>$num</a>".
1549
-				"</sup>";
1550
-		}
1546
+            return
1547
+                "<sup id=\"fnref$ref_count_mark:$node_id\">".
1548
+                "<a href=\"#fn:$node_id\"$attr>$num</a>".
1549
+                "</sup>";
1550
+        }
1551 1551
 		
1552
-		return "[^".$matches[1]."]";
1553
-	}
1552
+        return "[^".$matches[1]."]";
1553
+    }
1554 1554
 		
1555 1555
 	
1556
-	### Abbreviations ###
1556
+    ### Abbreviations ###
1557 1557
 	
1558
-	protected function stripAbbreviations($text) {
1559
-	#
1560
-	# Strips abbreviations from text, stores titles in hash references.
1561
-	#
1562
-		$less_than_tab = $this->tab_width - 1;
1563
-
1564
-		# Link defs are in the form: [id]*: url "optional title"
1565
-		$text = preg_replace_callback('{
1558
+    protected function stripAbbreviations($text) {
1559
+    #
1560
+    # Strips abbreviations from text, stores titles in hash references.
1561
+    #
1562
+        $less_than_tab = $this->tab_width - 1;
1563
+
1564
+        # Link defs are in the form: [id]*: url "optional title"
1565
+        $text = preg_replace_callback('{
1566 1566
 			^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?:	# abbr_id = $1
1567 1567
 			(.*)					# text = $2 (no blank lines allowed)	
1568 1568
 			}xm',
1569
-			array($this, '_stripAbbreviations_callback'),
1570
-			$text);
1571
-		return $text;
1572
-	}
1573
-	protected function _stripAbbreviations_callback($matches) {
1574
-		$abbr_word = $matches[1];
1575
-		$abbr_desc = $matches[2];
1576
-		if ($this->abbr_word_re)
1577
-			$this->abbr_word_re .= '|';
1578
-		$this->abbr_word_re .= preg_quote($abbr_word);
1579
-		$this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
1580
-		return ''; # String that will replace the block
1581
-	}
1569
+            array($this, '_stripAbbreviations_callback'),
1570
+            $text);
1571
+        return $text;
1572
+    }
1573
+    protected function _stripAbbreviations_callback($matches) {
1574
+        $abbr_word = $matches[1];
1575
+        $abbr_desc = $matches[2];
1576
+        if ($this->abbr_word_re)
1577
+            $this->abbr_word_re .= '|';
1578
+        $this->abbr_word_re .= preg_quote($abbr_word);
1579
+        $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
1580
+        return ''; # String that will replace the block
1581
+    }
1582 1582
 	
1583 1583
 	
1584
-	protected function doAbbreviations($text) {
1585
-	#
1586
-	# Find defined abbreviations in text and wrap them in <abbr> elements.
1587
-	#
1588
-		if ($this->abbr_word_re) {
1589
-			// cannot use the /x modifier because abbr_word_re may 
1590
-			// contain significant spaces:
1591
-			$text = preg_replace_callback('{'.
1592
-				'(?<![\w\x1A])'.
1593
-				'(?:'.$this->abbr_word_re.')'.
1594
-				'(?![\w\x1A])'.
1595
-				'}', 
1596
-				array($this, '_doAbbreviations_callback'), $text);
1597
-		}
1598
-		return $text;
1599
-	}
1600
-	protected function _doAbbreviations_callback($matches) {
1601
-		$abbr = $matches[0];
1602
-		if (isset($this->abbr_desciptions[$abbr])) {
1603
-			$desc = $this->abbr_desciptions[$abbr];
1604
-			if (empty($desc)) {
1605
-				return $this->hashPart("<abbr>$abbr</abbr>");
1606
-			} else {
1607
-				$desc = $this->encodeAttribute($desc);
1608
-				return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>");
1609
-			}
1610
-		} else {
1611
-			return $matches[0];
1612
-		}
1613
-	}
1584
+    protected function doAbbreviations($text) {
1585
+    #
1586
+    # Find defined abbreviations in text and wrap them in <abbr> elements.
1587
+    #
1588
+        if ($this->abbr_word_re) {
1589
+            // cannot use the /x modifier because abbr_word_re may 
1590
+            // contain significant spaces:
1591
+            $text = preg_replace_callback('{'.
1592
+                '(?<![\w\x1A])'.
1593
+                '(?:'.$this->abbr_word_re.')'.
1594
+                '(?![\w\x1A])'.
1595
+                '}', 
1596
+                array($this, '_doAbbreviations_callback'), $text);
1597
+        }
1598
+        return $text;
1599
+    }
1600
+    protected function _doAbbreviations_callback($matches) {
1601
+        $abbr = $matches[0];
1602
+        if (isset($this->abbr_desciptions[$abbr])) {
1603
+            $desc = $this->abbr_desciptions[$abbr];
1604
+            if (empty($desc)) {
1605
+                return $this->hashPart("<abbr>$abbr</abbr>");
1606
+            } else {
1607
+                $desc = $this->encodeAttribute($desc);
1608
+                return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>");
1609
+            }
1610
+        } else {
1611
+            return $matches[0];
1612
+        }
1613
+    }
1614 1614
 }
Please login to merge, or discard this patch.
vendor/michelf/php-markdown/Michelf/MarkdownInterface.php 1 patch
Indentation   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -19,16 +19,16 @@
 block discarded – undo
19 19
 
20 20
 interface MarkdownInterface {
21 21
 
22
-  #
23
-  # Initialize the parser and return the result of its transform method.
24
-  # This will work fine for derived classes too.
25
-  #
26
-  public static function defaultTransform($text);
22
+    #
23
+    # Initialize the parser and return the result of its transform method.
24
+    # This will work fine for derived classes too.
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
-  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
+    public function transform($text);
33 33
 
34 34
 }
Please login to merge, or discard this patch.
vendor/michelf/php-markdown/Readme.php 1 patch
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-0-compatible class autoloader
8 8
 spl_autoload_register(function($class){
9
-	require preg_replace('{\\\\|_(?!.*\\\\)}', DIRECTORY_SEPARATOR, ltrim($class, '\\')).'.php';
9
+    require preg_replace('{\\\\|_(?!.*\\\\)}', DIRECTORY_SEPARATOR, ltrim($class, '\\')).'.php';
10 10
 });
11 11
 
12 12
 # Get Markdown class
@@ -24,8 +24,8 @@  discard block
 block discarded – undo
24 24
     </head>
25 25
     <body>
26 26
 		<?php
27
-			# Put HTML content in the document
28
-			echo $html;
29
-		?>
27
+            # Put HTML content in the document
28
+            echo $html;
29
+        ?>
30 30
     </body>
31 31
 </html>
Please login to merge, or discard this patch.