|
|
@ -3,7 +3,7 @@ |
|
|
# Markdown - A text-to-HTML conversion tool for web writers
|
|
|
# Markdown - A text-to-HTML conversion tool for web writers
|
|
|
#
|
|
|
#
|
|
|
# PHP Markdown
|
|
|
# PHP Markdown
|
|
|
# Copyright (c) 2004-2013 Michel Fortin
|
|
|
|
|
|
|
|
|
# Copyright (c) 2004-2014 Michel Fortin
|
|
|
# <http://michelf.com/projects/php-markdown/>
|
|
|
# <http://michelf.com/projects/php-markdown/>
|
|
|
#
|
|
|
#
|
|
|
# Original Markdown
|
|
|
# Original Markdown
|
|
|
@ -21,7 +21,7 @@ class Markdown implements MarkdownInterface { |
|
|
|
|
|
|
|
|
### Version ###
|
|
|
### Version ###
|
|
|
|
|
|
|
|
|
const MARKDOWNLIB_VERSION = "1.4.0"; |
|
|
|
|
|
|
|
|
const MARKDOWNLIB_VERSION = "1.4.1"; |
|
|
|
|
|
|
|
|
### Simple Function Interface ###
|
|
|
### Simple Function Interface ###
|
|
|
|
|
|
|
|
|
@ -59,6 +59,9 @@ class Markdown implements MarkdownInterface { |
|
|
public $predef_urls = array(); |
|
|
public $predef_urls = array(); |
|
|
public $predef_titles = array(); |
|
|
public $predef_titles = array(); |
|
|
|
|
|
|
|
|
|
|
|
# Optional filter function for URLs
|
|
|
|
|
|
public $url_filter_func = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### Parser Implementation ###
|
|
|
### Parser Implementation ###
|
|
|
|
|
|
|
|
|
@ -209,7 +212,7 @@ class Markdown implements MarkdownInterface { |
|
|
)? # title is optional
|
|
|
)? # title is optional
|
|
|
(?:\n+|\Z) |
|
|
(?:\n+|\Z) |
|
|
}xm', |
|
|
}xm', |
|
|
array(&$this, '_stripLinkDefinitions_callback'), |
|
|
|
|
|
|
|
|
array($this, '_stripLinkDefinitions_callback'), |
|
|
$text); |
|
|
$text); |
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
@ -242,7 +245,7 @@ class Markdown implements MarkdownInterface { |
|
|
#
|
|
|
#
|
|
|
$block_tags_a_re = 'ins|del'; |
|
|
$block_tags_a_re = 'ins|del'; |
|
|
$block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'. |
|
|
$block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'. |
|
|
'script|noscript|form|fieldset|iframe|math|svg|'. |
|
|
|
|
|
|
|
|
'script|noscript|style|form|fieldset|iframe|math|svg|'. |
|
|
'article|section|nav|aside|hgroup|header|footer|'. |
|
|
'article|section|nav|aside|hgroup|header|footer|'. |
|
|
'figure'; |
|
|
'figure'; |
|
|
|
|
|
|
|
|
@ -297,9 +300,9 @@ class Markdown implements MarkdownInterface { |
|
|
# match will start at the first `<div>` and stop at the first `</div>`.
|
|
|
# match will start at the first `<div>` and stop at the first `</div>`.
|
|
|
$text = preg_replace_callback('{(?>
|
|
|
$text = preg_replace_callback('{(?>
|
|
|
(?>
|
|
|
(?>
|
|
|
(?<=\n\n) # Starting after a blank line
|
|
|
|
|
|
|
|
|
(?<=\n) # Starting on its own line
|
|
|
| # or
|
|
|
| # or
|
|
|
\A\n? # the beginning of the doc
|
|
|
|
|
|
|
|
|
\A\n? # the at beginning of the doc
|
|
|
) |
|
|
) |
|
|
( # save in $1
|
|
|
( # save in $1
|
|
|
|
|
|
|
|
|
@ -356,7 +359,7 @@ class Markdown implements MarkdownInterface { |
|
|
|
|
|
|
|
|
) |
|
|
) |
|
|
)}Sxmi', |
|
|
)}Sxmi', |
|
|
array(&$this, '_hashHTMLBlocks_callback'), |
|
|
|
|
|
|
|
|
array($this, '_hashHTMLBlocks_callback'), |
|
|
$text); |
|
|
$text); |
|
|
|
|
|
|
|
|
return $text; |
|
|
return $text; |
|
|
@ -500,7 +503,7 @@ class Markdown implements MarkdownInterface { |
|
|
protected function doHardBreaks($text) { |
|
|
protected function doHardBreaks($text) { |
|
|
# Do hard breaks:
|
|
|
# Do hard breaks:
|
|
|
return preg_replace_callback('/ {2,}\n/', |
|
|
return preg_replace_callback('/ {2,}\n/', |
|
|
array(&$this, '_doHardBreaks_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doHardBreaks_callback'), $text); |
|
|
} |
|
|
} |
|
|
protected function _doHardBreaks_callback($matches) { |
|
|
protected function _doHardBreaks_callback($matches) { |
|
|
return $this->hashPart("<br$this->empty_element_suffix\n"); |
|
|
return $this->hashPart("<br$this->empty_element_suffix\n"); |
|
|
@ -531,7 +534,7 @@ class Markdown implements MarkdownInterface { |
|
|
\] |
|
|
\] |
|
|
) |
|
|
) |
|
|
}xs', |
|
|
}xs', |
|
|
array(&$this, '_doAnchors_reference_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doAnchors_reference_callback'), $text); |
|
|
|
|
|
|
|
|
#
|
|
|
#
|
|
|
# Next, inline-style links: [link text](url "optional title")
|
|
|
# Next, inline-style links: [link text](url "optional title")
|
|
|
@ -558,7 +561,7 @@ class Markdown implements MarkdownInterface { |
|
|
\) |
|
|
\) |
|
|
) |
|
|
) |
|
|
}xs', |
|
|
}xs', |
|
|
array(&$this, '_doAnchors_inline_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doAnchors_inline_callback'), $text); |
|
|
|
|
|
|
|
|
#
|
|
|
#
|
|
|
# Last, handle reference-style shortcuts: [link text]
|
|
|
# Last, handle reference-style shortcuts: [link text]
|
|
|
@ -572,7 +575,7 @@ class Markdown implements MarkdownInterface { |
|
|
\] |
|
|
\] |
|
|
) |
|
|
) |
|
|
}xs', |
|
|
}xs', |
|
|
array(&$this, '_doAnchors_reference_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doAnchors_reference_callback'), $text); |
|
|
|
|
|
|
|
|
$this->in_anchor = false; |
|
|
$this->in_anchor = false; |
|
|
return $text; |
|
|
return $text; |
|
|
@ -593,7 +596,7 @@ class Markdown implements MarkdownInterface { |
|
|
|
|
|
|
|
|
if (isset($this->urls[$link_id])) { |
|
|
if (isset($this->urls[$link_id])) { |
|
|
$url = $this->urls[$link_id]; |
|
|
$url = $this->urls[$link_id]; |
|
|
$url = $this->encodeAttribute($url); |
|
|
|
|
|
|
|
|
$url = $this->encodeURLAttribute($url); |
|
|
|
|
|
|
|
|
$result = "<a href=\"$url\"";
|
|
|
$result = "<a href=\"$url\"";
|
|
|
if ( isset( $this->titles[$link_id] ) ) { |
|
|
if ( isset( $this->titles[$link_id] ) ) { |
|
|
@ -617,7 +620,13 @@ class Markdown implements MarkdownInterface { |
|
|
$url = $matches[3] == '' ? $matches[4] : $matches[3]; |
|
|
$url = $matches[3] == '' ? $matches[4] : $matches[3]; |
|
|
$title =& $matches[7]; |
|
|
$title =& $matches[7]; |
|
|
|
|
|
|
|
|
$url = $this->encodeAttribute($url); |
|
|
|
|
|
|
|
|
// if the URL was of the form <s p a c e s> it got caught by the HTML
|
|
|
|
|
|
// tag parser and hashed. Need to reverse the process before using the URL.
|
|
|
|
|
|
$unhashed = $this->unhash($url); |
|
|
|
|
|
if ($unhashed != $url) |
|
|
|
|
|
$url = preg_replace('/^<(.*)>$/', '\1', $unhashed); |
|
|
|
|
|
|
|
|
|
|
|
$url = $this->encodeURLAttribute($url); |
|
|
|
|
|
|
|
|
$result = "<a href=\"$url\"";
|
|
|
$result = "<a href=\"$url\"";
|
|
|
if (isset($title)) { |
|
|
if (isset($title)) { |
|
|
@ -654,7 +663,7 @@ class Markdown implements MarkdownInterface { |
|
|
|
|
|
|
|
|
) |
|
|
) |
|
|
}xs', |
|
|
}xs', |
|
|
array(&$this, '_doImages_reference_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doImages_reference_callback'), $text); |
|
|
|
|
|
|
|
|
#
|
|
|
#
|
|
|
# Next, handle inline images: 
|
|
|
# Next, handle inline images: 
|
|
|
@ -683,7 +692,7 @@ class Markdown implements MarkdownInterface { |
|
|
\) |
|
|
\) |
|
|
) |
|
|
) |
|
|
}xs', |
|
|
}xs', |
|
|
array(&$this, '_doImages_inline_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doImages_inline_callback'), $text); |
|
|
|
|
|
|
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
@ -698,7 +707,7 @@ class Markdown implements MarkdownInterface { |
|
|
|
|
|
|
|
|
$alt_text = $this->encodeAttribute($alt_text); |
|
|
$alt_text = $this->encodeAttribute($alt_text); |
|
|
if (isset($this->urls[$link_id])) { |
|
|
if (isset($this->urls[$link_id])) { |
|
|
$url = $this->encodeAttribute($this->urls[$link_id]); |
|
|
|
|
|
|
|
|
$url = $this->encodeURLAttribute($this->urls[$link_id]); |
|
|
$result = "<img src=\"$url\" alt=\"$alt_text\"";
|
|
|
$result = "<img src=\"$url\" alt=\"$alt_text\"";
|
|
|
if (isset($this->titles[$link_id])) { |
|
|
if (isset($this->titles[$link_id])) { |
|
|
$title = $this->titles[$link_id]; |
|
|
$title = $this->titles[$link_id]; |
|
|
@ -722,7 +731,7 @@ class Markdown implements MarkdownInterface { |
|
|
$title =& $matches[7]; |
|
|
$title =& $matches[7]; |
|
|
|
|
|
|
|
|
$alt_text = $this->encodeAttribute($alt_text); |
|
|
$alt_text = $this->encodeAttribute($alt_text); |
|
|
$url = $this->encodeAttribute($url); |
|
|
|
|
|
|
|
|
$url = $this->encodeURLAttribute($url); |
|
|
$result = "<img src=\"$url\" alt=\"$alt_text\"";
|
|
|
$result = "<img src=\"$url\" alt=\"$alt_text\"";
|
|
|
if (isset($title)) { |
|
|
if (isset($title)) { |
|
|
$title = $this->encodeAttribute($title); |
|
|
$title = $this->encodeAttribute($title); |
|
|
@ -743,7 +752,7 @@ class Markdown implements MarkdownInterface { |
|
|
# --------
|
|
|
# --------
|
|
|
#
|
|
|
#
|
|
|
$text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx', |
|
|
$text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx', |
|
|
array(&$this, '_doHeaders_callback_setext'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doHeaders_callback_setext'), $text); |
|
|
|
|
|
|
|
|
# atx-style headers:
|
|
|
# atx-style headers:
|
|
|
# # Header 1
|
|
|
# # Header 1
|
|
|
@ -760,7 +769,7 @@ class Markdown implements MarkdownInterface { |
|
|
\#* # optional closing #\'s (not counted)
|
|
|
\#* # optional closing #\'s (not counted)
|
|
|
\n+ |
|
|
\n+ |
|
|
}xm', |
|
|
}xm', |
|
|
array(&$this, '_doHeaders_callback_atx'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doHeaders_callback_atx'), $text); |
|
|
|
|
|
|
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
@ -789,7 +798,6 @@ class Markdown implements MarkdownInterface { |
|
|
# Re-usable patterns to match list item bullets and number markers:
|
|
|
# Re-usable patterns to match list item bullets and number markers:
|
|
|
$marker_ul_re = '[*+-]'; |
|
|
$marker_ul_re = '[*+-]'; |
|
|
$marker_ol_re = '\d+[\.]'; |
|
|
$marker_ol_re = '\d+[\.]'; |
|
|
$marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; |
|
|
|
|
|
|
|
|
|
|
|
$markers_relist = array( |
|
|
$markers_relist = array( |
|
|
$marker_ul_re => $marker_ol_re, |
|
|
$marker_ul_re => $marker_ol_re, |
|
|
@ -833,14 +841,14 @@ class Markdown implements MarkdownInterface { |
|
|
^ |
|
|
^ |
|
|
'.$whole_list_re.' |
|
|
'.$whole_list_re.' |
|
|
}mx', |
|
|
}mx', |
|
|
array(&$this, '_doLists_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doLists_callback'), $text); |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
$text = preg_replace_callback('{ |
|
|
$text = preg_replace_callback('{ |
|
|
(?:(?<=\n)\n|\A\n?) # Must eat the newline
|
|
|
(?:(?<=\n)\n|\A\n?) # Must eat the newline
|
|
|
'.$whole_list_re.' |
|
|
'.$whole_list_re.' |
|
|
}mx', |
|
|
}mx', |
|
|
array(&$this, '_doLists_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doLists_callback'), $text); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -907,7 +915,7 @@ class Markdown implements MarkdownInterface { |
|
|
(?:(\n+(?=\n))|\n) # tailing blank line = $5
|
|
|
(?:(\n+(?=\n))|\n) # tailing blank line = $5
|
|
|
(?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n)))) |
|
|
(?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n)))) |
|
|
}xm', |
|
|
}xm', |
|
|
array(&$this, '_processListItems_callback'), $list_str); |
|
|
|
|
|
|
|
|
array($this, '_processListItems_callback'), $list_str); |
|
|
|
|
|
|
|
|
$this->list_level--; |
|
|
$this->list_level--; |
|
|
return $list_str; |
|
|
return $list_str; |
|
|
@ -951,7 +959,7 @@ class Markdown implements MarkdownInterface { |
|
|
) |
|
|
) |
|
|
((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
|
|
|
((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
|
|
|
}xm', |
|
|
}xm', |
|
|
array(&$this, '_doCodeBlocks_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doCodeBlocks_callback'), $text); |
|
|
|
|
|
|
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
@ -979,19 +987,19 @@ class Markdown implements MarkdownInterface { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected $em_relist = array( |
|
|
protected $em_relist = array( |
|
|
'' => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?=\S|$)(?![\.,:;]\s)', |
|
|
|
|
|
'*' => '(?<=\S|^)(?<!\*)\*(?!\*)', |
|
|
|
|
|
'_' => '(?<=\S|^)(?<!_)_(?!_)', |
|
|
|
|
|
|
|
|
'' => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?![\.,:;]?\s)', |
|
|
|
|
|
'*' => '(?<![\s*])\*(?!\*)', |
|
|
|
|
|
'_' => '(?<![\s_])_(?!_)', |
|
|
); |
|
|
); |
|
|
protected $strong_relist = array( |
|
|
protected $strong_relist = array( |
|
|
'' => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?=\S|$)(?![\.,:;]\s)', |
|
|
|
|
|
'**' => '(?<=\S|^)(?<!\*)\*\*(?!\*)', |
|
|
|
|
|
'__' => '(?<=\S|^)(?<!_)__(?!_)', |
|
|
|
|
|
|
|
|
'' => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?![\.,:;]?\s)', |
|
|
|
|
|
'**' => '(?<![\s*])\*\*(?!\*)', |
|
|
|
|
|
'__' => '(?<![\s_])__(?!_)', |
|
|
); |
|
|
); |
|
|
protected $em_strong_relist = array( |
|
|
protected $em_strong_relist = array( |
|
|
'' => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?=\S|$)(?![\.,:;]\s)', |
|
|
|
|
|
'***' => '(?<=\S|^)(?<!\*)\*\*\*(?!\*)', |
|
|
|
|
|
'___' => '(?<=\S|^)(?<!_)___(?!_)', |
|
|
|
|
|
|
|
|
'' => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?![\.,:;]?\s)', |
|
|
|
|
|
'***' => '(?<![\s*])\*\*\*(?!\*)', |
|
|
|
|
|
'___' => '(?<![\s_])___(?!_)', |
|
|
); |
|
|
); |
|
|
protected $em_strong_prepared_relist; |
|
|
protected $em_strong_prepared_relist; |
|
|
|
|
|
|
|
|
@ -1151,7 +1159,7 @@ class Markdown implements MarkdownInterface { |
|
|
)+ |
|
|
)+ |
|
|
) |
|
|
) |
|
|
/xm', |
|
|
/xm', |
|
|
array(&$this, '_doBlockQuotes_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doBlockQuotes_callback'), $text); |
|
|
|
|
|
|
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
@ -1165,7 +1173,7 @@ class Markdown implements MarkdownInterface { |
|
|
# These leading spaces cause problem with <pre> content,
|
|
|
# These leading spaces cause problem with <pre> content,
|
|
|
# so we need to fix that:
|
|
|
# so we need to fix that:
|
|
|
$bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx', |
|
|
$bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx', |
|
|
array(&$this, '_doBlockQuotes_callback2'), $bq); |
|
|
|
|
|
|
|
|
array($this, '_doBlockQuotes_callback2'), $bq); |
|
|
|
|
|
|
|
|
return "\n". $this->hashBlock("<blockquote>\n$bq\n</blockquote>")."\n\n"; |
|
|
return "\n". $this->hashBlock("<blockquote>\n$bq\n</blockquote>")."\n\n"; |
|
|
} |
|
|
} |
|
|
@ -1255,6 +1263,33 @@ class Markdown implements MarkdownInterface { |
|
|
$text = str_replace('"', '"', $text); |
|
|
$text = str_replace('"', '"', $text); |
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected function encodeURLAttribute($url, &$text = null) { |
|
|
|
|
|
#
|
|
|
|
|
|
# Encode text for a double-quoted HTML attribute containing a URL,
|
|
|
|
|
|
# applying the URL filter if set. Also generates the textual
|
|
|
|
|
|
# representation for the URL (removing mailto: or tel:) storing it in $text.
|
|
|
|
|
|
# This function is *not* suitable for attributes enclosed in single quotes.
|
|
|
|
|
|
#
|
|
|
|
|
|
if ($this->url_filter_func) |
|
|
|
|
|
$url = call_user_func($this->url_filter_func, $url); |
|
|
|
|
|
|
|
|
|
|
|
if (preg_match('{^mailto:}i', $url)) |
|
|
|
|
|
$url = $this->encodeEntityObfuscatedAttribute($url, $text, 7); |
|
|
|
|
|
else if (preg_match('{^tel:}i', $url)) |
|
|
|
|
|
{ |
|
|
|
|
|
$url = $this->encodeAttribute($url); |
|
|
|
|
|
$text = substr($url, 4); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
$url = $this->encodeAttribute($url); |
|
|
|
|
|
$text = $url; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return $url; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected function encodeAmpsAndAngles($text) { |
|
|
protected function encodeAmpsAndAngles($text) { |
|
|
@ -1279,8 +1314,8 @@ class Markdown implements MarkdownInterface { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected function doAutoLinks($text) { |
|
|
protected function doAutoLinks($text) { |
|
|
$text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i', |
|
|
|
|
|
array(&$this, '_doAutoLinks_url_callback'), $text); |
|
|
|
|
|
|
|
|
$text = preg_replace_callback('{<((https?|ftp|dict|tel):[^\'">\s]+)>}i', |
|
|
|
|
|
array($this, '_doAutoLinks_url_callback'), $text); |
|
|
|
|
|
|
|
|
# Email addresses: <address@domain.foo>
|
|
|
# Email addresses: <address@domain.foo>
|
|
|
$text = preg_replace_callback('{ |
|
|
$text = preg_replace_callback('{ |
|
|
@ -1301,49 +1336,47 @@ class Markdown implements MarkdownInterface { |
|
|
) |
|
|
) |
|
|
> |
|
|
> |
|
|
}xi', |
|
|
}xi', |
|
|
array(&$this, '_doAutoLinks_email_callback'), $text); |
|
|
|
|
|
$text = preg_replace_callback('{<(tel:([^\'">\s]+))>}i',array(&$this, '_doAutoLinks_tel_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doAutoLinks_email_callback'), $text); |
|
|
|
|
|
|
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
protected function _doAutoLinks_tel_callback($matches) { |
|
|
|
|
|
$url = $this->encodeAttribute($matches[1]); |
|
|
|
|
|
$tel = $this->encodeAttribute($matches[2]); |
|
|
|
|
|
$link = "<a href=\"$url\">$tel</a>";
|
|
|
|
|
|
return $this->hashPart($link); |
|
|
|
|
|
} |
|
|
|
|
|
protected function _doAutoLinks_url_callback($matches) { |
|
|
protected function _doAutoLinks_url_callback($matches) { |
|
|
$url = $this->encodeAttribute($matches[1]); |
|
|
|
|
|
$link = "<a href=\"$url\">$url</a>";
|
|
|
|
|
|
|
|
|
$url = $this->encodeURLAttribute($matches[1], $text); |
|
|
|
|
|
$link = "<a href=\"$url\">$text</a>";
|
|
|
return $this->hashPart($link); |
|
|
return $this->hashPart($link); |
|
|
} |
|
|
} |
|
|
protected function _doAutoLinks_email_callback($matches) { |
|
|
protected function _doAutoLinks_email_callback($matches) { |
|
|
$address = $matches[1]; |
|
|
|
|
|
$link = $this->encodeEmailAddress($address); |
|
|
|
|
|
|
|
|
$addr = $matches[1]; |
|
|
|
|
|
$url = $this->encodeURLAttribute("mailto:$addr", $text); |
|
|
|
|
|
$link = "<a href=\"$url\">$text</a>";
|
|
|
return $this->hashPart($link); |
|
|
return $this->hashPart($link); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected function encodeEmailAddress($addr) { |
|
|
|
|
|
|
|
|
protected function encodeEntityObfuscatedAttribute($text, &$tail = null, $head_length = 0) { |
|
|
#
|
|
|
#
|
|
|
# Input: an email address, e.g. "foo@example.com"
|
|
|
|
|
|
|
|
|
# Input: some text to obfuscate, e.g. "mailto:foo@example.com"
|
|
|
#
|
|
|
#
|
|
|
# Output: the email address as a mailto link, with each character
|
|
|
|
|
|
# of the address encoded as either a decimal or hex entity, in
|
|
|
|
|
|
# the hopes of foiling most address harvesting spam bots. E.g.:
|
|
|
|
|
|
|
|
|
# Output: the same text but with most characters encoded as either a
|
|
|
|
|
|
# decimal or hex entity, in the hopes of foiling most address
|
|
|
|
|
|
# harvesting spam bots. E.g.:
|
|
|
#
|
|
|
#
|
|
|
# <p><a href="mailto:foo
|
|
|
|
|
|
|
|
|
# mailto:foo
|
|
|
# @example.co
|
|
|
# @example.co
|
|
|
# m">foo@exampl
|
|
|
|
|
|
# e.com</a></p>
|
|
|
|
|
|
|
|
|
# m
|
|
|
|
|
|
#
|
|
|
|
|
|
# Note: the additional output $tail is assigned the same value as the
|
|
|
|
|
|
# ouput, minus the number of characters specified by $head_length.
|
|
|
#
|
|
|
#
|
|
|
# Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
|
|
|
# Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
|
|
|
# With some optimizations by Milian Wolff.
|
|
|
|
|
|
|
|
|
# With some optimizations by Milian Wolff. Forced encoding of HTML
|
|
|
|
|
|
# attribute special characters by Allan Odgaard.
|
|
|
#
|
|
|
#
|
|
|
$addr = "mailto:" . $addr; |
|
|
|
|
|
$chars = preg_split('/(?<!^)(?!$)/', $addr); |
|
|
|
|
|
$seed = (int)abs(crc32($addr) / strlen($addr)); # Deterministic seed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ($text == "") return $tail = ""; |
|
|
|
|
|
|
|
|
|
|
|
$chars = preg_split('/(?<!^)(?!$)/', $text); |
|
|
|
|
|
$seed = (int)abs(crc32($text) / strlen($text)); # Deterministic seed.
|
|
|
|
|
|
|
|
|
foreach ($chars as $key => $char) { |
|
|
foreach ($chars as $key => $char) { |
|
|
$ord = ord($char); |
|
|
$ord = ord($char); |
|
|
# Ignore non-ascii chars.
|
|
|
# Ignore non-ascii chars.
|
|
|
@ -1351,17 +1384,17 @@ class Markdown implements MarkdownInterface { |
|
|
$r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
|
|
|
$r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
|
|
|
# roughly 10% raw, 45% hex, 45% dec
|
|
|
# roughly 10% raw, 45% hex, 45% dec
|
|
|
# '@' *must* be encoded. I insist.
|
|
|
# '@' *must* be encoded. I insist.
|
|
|
if ($r > 90 && $char != '@') /* do nothing */; |
|
|
|
|
|
|
|
|
# '"' and '>' have to be encoded inside the attribute
|
|
|
|
|
|
if ($r > 90 && strpos('@"&>', $char) === false) /* do nothing */; |
|
|
else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';'; |
|
|
else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';'; |
|
|
else $chars[$key] = '&#'.$ord.';'; |
|
|
else $chars[$key] = '&#'.$ord.';'; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
$addr = implode('', $chars); |
|
|
|
|
|
$text = implode('', array_slice($chars, 7)); # text without `mailto:`
|
|
|
|
|
|
$addr = "<a href=\"$addr\">$text</a>";
|
|
|
|
|
|
|
|
|
|
|
|
return $addr; |
|
|
|
|
|
|
|
|
$text = implode('', $chars); |
|
|
|
|
|
$tail = $head_length ? implode('', array_slice($chars, $head_length)) : $text; |
|
|
|
|
|
|
|
|
|
|
|
return $text; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1470,7 +1503,7 @@ class Markdown implements MarkdownInterface { |
|
|
# appropriate number of space between each blocks.
|
|
|
# appropriate number of space between each blocks.
|
|
|
|
|
|
|
|
|
$text = preg_replace_callback('/^.*\t.*$/m', |
|
|
$text = preg_replace_callback('/^.*\t.*$/m', |
|
|
array(&$this, '_detab_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_detab_callback'), $text); |
|
|
|
|
|
|
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
@ -1510,7 +1543,7 @@ class Markdown implements MarkdownInterface { |
|
|
# Swap back in all the tags hashed by _HashHTMLBlocks.
|
|
|
# Swap back in all the tags hashed by _HashHTMLBlocks.
|
|
|
#
|
|
|
#
|
|
|
return preg_replace_callback('/(.)\x1A[0-9]+\1/', |
|
|
return preg_replace_callback('/(.)\x1A[0-9]+\1/', |
|
|
array(&$this, '_unhash_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_unhash_callback'), $text); |
|
|
} |
|
|
} |
|
|
protected function _unhash_callback($matches) { |
|
|
protected function _unhash_callback($matches) { |
|
|
return $this->html_hashes[$matches[0]]; |
|
|
return $this->html_hashes[$matches[0]]; |
|
|
@ -1716,7 +1749,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
(?:[ ]* '.$this->id_class_attr_catch_re.' )? # $5 = extra id & class attr
|
|
|
(?:[ ]* '.$this->id_class_attr_catch_re.' )? # $5 = extra id & class attr
|
|
|
(?:\n+|\Z) |
|
|
(?:\n+|\Z) |
|
|
}xm', |
|
|
}xm', |
|
|
array(&$this, '_stripLinkDefinitions_callback'), |
|
|
|
|
|
|
|
|
array($this, '_stripLinkDefinitions_callback'), |
|
|
$text); |
|
|
$text); |
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
@ -1733,17 +1766,17 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
### HTML Block Parser ###
|
|
|
### HTML Block Parser ###
|
|
|
|
|
|
|
|
|
# Tags that are always treated as block tags:
|
|
|
# Tags that are always treated as block tags:
|
|
|
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'; |
|
|
|
|
|
|
|
|
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'; |
|
|
|
|
|
|
|
|
# Tags treated as block tags only if the opening tag is alone on its line:
|
|
|
# Tags treated as block tags only if the opening tag is alone on its line:
|
|
|
protected $context_block_tags_re = 'script|noscript|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video'; |
|
|
|
|
|
|
|
|
protected $context_block_tags_re = 'script|noscript|style|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video'; |
|
|
|
|
|
|
|
|
# Tags where markdown="1" default to span mode:
|
|
|
# Tags where markdown="1" default to span mode:
|
|
|
protected $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address'; |
|
|
protected $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address'; |
|
|
|
|
|
|
|
|
# Tags which must not have their contents modified, no matter where
|
|
|
# Tags which must not have their contents modified, no matter where
|
|
|
# they appear:
|
|
|
# they appear:
|
|
|
protected $clean_tags_re = 'script|math|svg'; |
|
|
|
|
|
|
|
|
protected $clean_tags_re = 'script|style|math|svg'; |
|
|
|
|
|
|
|
|
# Tags that do not need to be closed.
|
|
|
# Tags that do not need to be closed.
|
|
|
protected $auto_close_tags_re = 'hr|img|param|source|track'; |
|
|
protected $auto_close_tags_re = 'hr|img|param|source|track'; |
|
|
@ -2227,7 +2260,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
\] |
|
|
\] |
|
|
) |
|
|
) |
|
|
}xs', |
|
|
}xs', |
|
|
array(&$this, '_doAnchors_reference_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doAnchors_reference_callback'), $text); |
|
|
|
|
|
|
|
|
#
|
|
|
#
|
|
|
# Next, inline-style links: [link text](url "optional title")
|
|
|
# Next, inline-style links: [link text](url "optional title")
|
|
|
@ -2255,7 +2288,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
(?:[ ]? '.$this->id_class_attr_catch_re.' )? # $8 = id/class attributes
|
|
|
(?:[ ]? '.$this->id_class_attr_catch_re.' )? # $8 = id/class attributes
|
|
|
) |
|
|
) |
|
|
}xs', |
|
|
}xs', |
|
|
array(&$this, '_doAnchors_inline_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doAnchors_inline_callback'), $text); |
|
|
|
|
|
|
|
|
#
|
|
|
#
|
|
|
# Last, handle reference-style shortcuts: [link text]
|
|
|
# Last, handle reference-style shortcuts: [link text]
|
|
|
@ -2269,7 +2302,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
\] |
|
|
\] |
|
|
) |
|
|
) |
|
|
}xs', |
|
|
}xs', |
|
|
array(&$this, '_doAnchors_reference_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doAnchors_reference_callback'), $text); |
|
|
|
|
|
|
|
|
$this->in_anchor = false; |
|
|
$this->in_anchor = false; |
|
|
return $text; |
|
|
return $text; |
|
|
@ -2290,7 +2323,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
|
|
|
|
|
|
if (isset($this->urls[$link_id])) { |
|
|
if (isset($this->urls[$link_id])) { |
|
|
$url = $this->urls[$link_id]; |
|
|
$url = $this->urls[$link_id]; |
|
|
$url = $this->encodeAttribute($url); |
|
|
|
|
|
|
|
|
$url = $this->encodeURLAttribute($url); |
|
|
|
|
|
|
|
|
$result = "<a href=\"$url\"";
|
|
|
$result = "<a href=\"$url\"";
|
|
|
if ( isset( $this->titles[$link_id] ) ) { |
|
|
if ( isset( $this->titles[$link_id] ) ) { |
|
|
@ -2317,8 +2350,13 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
$title =& $matches[7]; |
|
|
$title =& $matches[7]; |
|
|
$attr = $this->doExtraAttributes("a", $dummy =& $matches[8]); |
|
|
$attr = $this->doExtraAttributes("a", $dummy =& $matches[8]); |
|
|
|
|
|
|
|
|
|
|
|
// if the URL was of the form <s p a c e s> it got caught by the HTML
|
|
|
|
|
|
// tag parser and hashed. Need to reverse the process before using the URL.
|
|
|
|
|
|
$unhashed = $this->unhash($url); |
|
|
|
|
|
if ($unhashed != $url) |
|
|
|
|
|
$url = preg_replace('/^<(.*)>$/', '\1', $unhashed); |
|
|
|
|
|
|
|
|
$url = $this->encodeAttribute($url); |
|
|
|
|
|
|
|
|
$url = $this->encodeURLAttribute($url); |
|
|
|
|
|
|
|
|
$result = "<a href=\"$url\"";
|
|
|
$result = "<a href=\"$url\"";
|
|
|
if (isset($title)) { |
|
|
if (isset($title)) { |
|
|
@ -2356,7 +2394,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
|
|
|
|
|
|
) |
|
|
) |
|
|
}xs', |
|
|
}xs', |
|
|
array(&$this, '_doImages_reference_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doImages_reference_callback'), $text); |
|
|
|
|
|
|
|
|
#
|
|
|
#
|
|
|
# Next, handle inline images: 
|
|
|
# Next, handle inline images: 
|
|
|
@ -2386,7 +2424,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
(?:[ ]? '.$this->id_class_attr_catch_re.' )? # $8 = id/class attributes
|
|
|
(?:[ ]? '.$this->id_class_attr_catch_re.' )? # $8 = id/class attributes
|
|
|
) |
|
|
) |
|
|
}xs', |
|
|
}xs', |
|
|
array(&$this, '_doImages_inline_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doImages_inline_callback'), $text); |
|
|
|
|
|
|
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
@ -2401,7 +2439,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
|
|
|
|
|
|
$alt_text = $this->encodeAttribute($alt_text); |
|
|
$alt_text = $this->encodeAttribute($alt_text); |
|
|
if (isset($this->urls[$link_id])) { |
|
|
if (isset($this->urls[$link_id])) { |
|
|
$url = $this->encodeAttribute($this->urls[$link_id]); |
|
|
|
|
|
|
|
|
$url = $this->encodeURLAttribute($this->urls[$link_id]); |
|
|
$result = "<img src=\"$url\" alt=\"$alt_text\"";
|
|
|
$result = "<img src=\"$url\" alt=\"$alt_text\"";
|
|
|
if (isset($this->titles[$link_id])) { |
|
|
if (isset($this->titles[$link_id])) { |
|
|
$title = $this->titles[$link_id]; |
|
|
$title = $this->titles[$link_id]; |
|
|
@ -2428,7 +2466,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
$attr = $this->doExtraAttributes("img", $dummy =& $matches[8]); |
|
|
$attr = $this->doExtraAttributes("img", $dummy =& $matches[8]); |
|
|
|
|
|
|
|
|
$alt_text = $this->encodeAttribute($alt_text); |
|
|
$alt_text = $this->encodeAttribute($alt_text); |
|
|
$url = $this->encodeAttribute($url); |
|
|
|
|
|
|
|
|
$url = $this->encodeURLAttribute($url); |
|
|
$result = "<img src=\"$url\" alt=\"$alt_text\"";
|
|
|
$result = "<img src=\"$url\" alt=\"$alt_text\"";
|
|
|
if (isset($title)) { |
|
|
if (isset($title)) { |
|
|
$title = $this->encodeAttribute($title); |
|
|
$title = $this->encodeAttribute($title); |
|
|
@ -2458,7 +2496,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
(?:[ ]+ '.$this->id_class_attr_catch_re.' )? # $3 = id/class attributes
|
|
|
(?:[ ]+ '.$this->id_class_attr_catch_re.' )? # $3 = id/class attributes
|
|
|
[ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer
|
|
|
[ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer
|
|
|
}mx', |
|
|
}mx', |
|
|
array(&$this, '_doHeaders_callback_setext'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doHeaders_callback_setext'), $text); |
|
|
|
|
|
|
|
|
# atx-style headers:
|
|
|
# atx-style headers:
|
|
|
# # Header 1 {#header1}
|
|
|
# # Header 1 {#header1}
|
|
|
@ -2477,7 +2515,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
[ ]* |
|
|
[ ]* |
|
|
\n+ |
|
|
\n+ |
|
|
}xm', |
|
|
}xm', |
|
|
array(&$this, '_doHeaders_callback_atx'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doHeaders_callback_atx'), $text); |
|
|
|
|
|
|
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
@ -2528,7 +2566,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
) |
|
|
) |
|
|
(?=\n|\Z) # Stop at final double newline.
|
|
|
(?=\n|\Z) # Stop at final double newline.
|
|
|
}xm', |
|
|
}xm', |
|
|
array(&$this, '_doTable_leadingPipe_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doTable_leadingPipe_callback'), $text); |
|
|
|
|
|
|
|
|
#
|
|
|
#
|
|
|
# Find tables without leading pipe.
|
|
|
# Find tables without leading pipe.
|
|
|
@ -2554,7 +2592,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
) |
|
|
) |
|
|
(?=\n|\Z) # Stop at final double newline.
|
|
|
(?=\n|\Z) # Stop at final double newline.
|
|
|
}xm', |
|
|
}xm', |
|
|
array(&$this, '_DoTable_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_DoTable_callback'), $text); |
|
|
|
|
|
|
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
@ -2678,7 +2716,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
(?>\A\n?|(?<=\n\n))
|
|
|
(?>\A\n?|(?<=\n\n))
|
|
|
'.$whole_list_re.' |
|
|
'.$whole_list_re.' |
|
|
}mx', |
|
|
}mx', |
|
|
array(&$this, '_doDefLists_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doDefLists_callback'), $text); |
|
|
|
|
|
|
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
@ -2716,7 +2754,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
(?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed
|
|
|
(?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed
|
|
|
# with a definition mark.
|
|
|
# with a definition mark.
|
|
|
}xm', |
|
|
}xm', |
|
|
array(&$this, '_processDefListItems_callback_dt'), $list_str); |
|
|
|
|
|
|
|
|
array($this, '_processDefListItems_callback_dt'), $list_str); |
|
|
|
|
|
|
|
|
# Process actual definitions.
|
|
|
# Process actual definitions.
|
|
|
$list_str = preg_replace_callback('{ |
|
|
$list_str = preg_replace_callback('{ |
|
|
@ -2733,7 +2771,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
) |
|
|
) |
|
|
) |
|
|
) |
|
|
}xm', |
|
|
}xm', |
|
|
array(&$this, '_processDefListItems_callback_dd'), $list_str); |
|
|
|
|
|
|
|
|
array($this, '_processDefListItems_callback_dd'), $list_str); |
|
|
|
|
|
|
|
|
return $list_str; |
|
|
return $list_str; |
|
|
} |
|
|
} |
|
|
@ -2801,7 +2839,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
# Closing marker.
|
|
|
# Closing marker.
|
|
|
\1 [ ]* (?= \n ) |
|
|
\1 [ ]* (?= \n ) |
|
|
}xm', |
|
|
}xm', |
|
|
array(&$this, '_doFencedCodeBlocks_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doFencedCodeBlocks_callback'), $text); |
|
|
|
|
|
|
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
@ -2811,7 +2849,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
$codeblock = $matches[4]; |
|
|
$codeblock = $matches[4]; |
|
|
$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); |
|
|
$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); |
|
|
$codeblock = preg_replace_callback('/^\n+/', |
|
|
$codeblock = preg_replace_callback('/^\n+/', |
|
|
array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock); |
|
|
|
|
|
|
|
|
array($this, '_doFencedCodeBlocks_newlines'), $codeblock); |
|
|
|
|
|
|
|
|
if ($classname != "") { |
|
|
if ($classname != "") { |
|
|
if ($classname{0} == '.') |
|
|
if ($classname{0} == '.') |
|
|
@ -2837,19 +2875,19 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
# work in the middle of a word.
|
|
|
# work in the middle of a word.
|
|
|
#
|
|
|
#
|
|
|
protected $em_relist = array( |
|
|
protected $em_relist = array( |
|
|
'' => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?=\S|$)(?![\.,:;]\s)', |
|
|
|
|
|
'*' => '(?<=\S|^)(?<!\*)\*(?!\*)', |
|
|
|
|
|
'_' => '(?<=\S|^)(?<!_)_(?![a-zA-Z0-9_])', |
|
|
|
|
|
|
|
|
'' => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?![\.,:;]?\s)', |
|
|
|
|
|
'*' => '(?<![\s*])\*(?!\*)', |
|
|
|
|
|
'_' => '(?<![\s_])_(?![a-zA-Z0-9_])', |
|
|
); |
|
|
); |
|
|
protected $strong_relist = array( |
|
|
protected $strong_relist = array( |
|
|
'' => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?=\S|$)(?![\.,:;]\s)', |
|
|
|
|
|
'**' => '(?<=\S|^)(?<!\*)\*\*(?!\*)', |
|
|
|
|
|
'__' => '(?<=\S|^)(?<!_)__(?![a-zA-Z0-9_])', |
|
|
|
|
|
|
|
|
'' => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?![\.,:;]?\s)', |
|
|
|
|
|
'**' => '(?<![\s*])\*\*(?!\*)', |
|
|
|
|
|
'__' => '(?<![\s_])__(?![a-zA-Z0-9_])', |
|
|
); |
|
|
); |
|
|
protected $em_strong_relist = array( |
|
|
protected $em_strong_relist = array( |
|
|
'' => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?=\S|$)(?![\.,:;]\s)', |
|
|
|
|
|
'***' => '(?<=\S|^)(?<!\*)\*\*\*(?!\*)', |
|
|
|
|
|
'___' => '(?<=\S|^)(?<!_)___(?![a-zA-Z0-9_])', |
|
|
|
|
|
|
|
|
'' => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?![\.,:;]?\s)', |
|
|
|
|
|
'***' => '(?<![\s*])\*\*\*(?!\*)', |
|
|
|
|
|
'___' => '(?<![\s_])___(?![a-zA-Z0-9_])', |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -2908,13 +2946,13 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
.+ # actual text
|
|
|
.+ # actual text
|
|
|
| |
|
|
| |
|
|
\n # newlines but
|
|
|
\n # newlines but
|
|
|
(?!\[\^.+?\]:\s)# negative lookahead for footnote marker.
|
|
|
|
|
|
|
|
|
(?!\[.+?\][ ]?:\s)# negative lookahead for footnote or link definition marker.
|
|
|
(?!\n+[ ]{0,3}\S)# ensure line is not blank and followed
|
|
|
(?!\n+[ ]{0,3}\S)# ensure line is not blank and followed
|
|
|
# by non-indented content
|
|
|
# by non-indented content
|
|
|
)* |
|
|
)* |
|
|
) |
|
|
) |
|
|
}xm', |
|
|
}xm', |
|
|
array(&$this, '_stripFootnotes_callback'), |
|
|
|
|
|
|
|
|
array($this, '_stripFootnotes_callback'), |
|
|
$text); |
|
|
$text); |
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
@ -2942,7 +2980,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
# Append footnote list to text.
|
|
|
# Append footnote list to text.
|
|
|
#
|
|
|
#
|
|
|
$text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', |
|
|
$text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', |
|
|
array(&$this, '_appendFootnotes_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_appendFootnotes_callback'), $text); |
|
|
|
|
|
|
|
|
if (!empty($this->footnotes_ordered)) { |
|
|
if (!empty($this->footnotes_ordered)) { |
|
|
$text .= "\n\n"; |
|
|
$text .= "\n\n"; |
|
|
@ -2974,7 +3012,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
$footnote .= "\n"; # Need to append newline before parsing.
|
|
|
$footnote .= "\n"; # Need to append newline before parsing.
|
|
|
$footnote = $this->runBlockGamut("$footnote\n"); |
|
|
$footnote = $this->runBlockGamut("$footnote\n"); |
|
|
$footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', |
|
|
$footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', |
|
|
array(&$this, '_appendFootnotes_callback'), $footnote); |
|
|
|
|
|
|
|
|
array($this, '_appendFootnotes_callback'), $footnote); |
|
|
|
|
|
|
|
|
$attr = str_replace("%%", ++$num, $attr); |
|
|
$attr = str_replace("%%", ++$num, $attr); |
|
|
$note_id = $this->encodeAttribute($note_id); |
|
|
$note_id = $this->encodeAttribute($note_id); |
|
|
@ -3057,7 +3095,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?: # abbr_id = $1
|
|
|
^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?: # abbr_id = $1
|
|
|
(.*) # text = $2 (no blank lines allowed)
|
|
|
(.*) # text = $2 (no blank lines allowed)
|
|
|
}xm', |
|
|
}xm', |
|
|
array(&$this, '_stripAbbreviations_callback'), |
|
|
|
|
|
|
|
|
array($this, '_stripAbbreviations_callback'), |
|
|
$text); |
|
|
$text); |
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
@ -3084,7 +3122,7 @@ abstract class _MarkdownExtra_TmpImpl extends \Michelf\Markdown { |
|
|
'(?:'.$this->abbr_word_re.')'. |
|
|
'(?:'.$this->abbr_word_re.')'. |
|
|
'(?![\w\x1A])'. |
|
|
'(?![\w\x1A])'. |
|
|
'}', |
|
|
'}', |
|
|
array(&$this, '_doAbbreviations_callback'), $text); |
|
|
|
|
|
|
|
|
array($this, '_doAbbreviations_callback'), $text); |
|
|
} |
|
|
} |
|
|
return $text; |
|
|
return $text; |
|
|
} |
|
|
} |
|
|
|