]*
-// \b
-// markdown\s*=\s* ([\'"]) # $2 = attr quote char
-// 1
-// \2
-// [^>]*
-// >
-// )
-// ( # $3 = contents
-// .*
-// )
-// (
) # $4 = closing tag
-// \z
-// }xs', $block, $matches))
-// {
-// list(, $div_open, , $div_content, $div_close) = $matches;
-//
-// # We can't call Markdown(), because that resets the hash;
-// # that initialization code should be pulled into its own sub, though.
-// $div_content = $this->hashHTMLBlocks($div_content);
-//
-// # Run document gamut methods on the content.
-// foreach ($this->document_gamut as $method => $priority) {
-// $div_content = $this->$method($div_content);
-// }
-//
-// $div_open = preg_replace(
-// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open);
-//
-// $graf = $div_open . "\n" . $div_content . "\n" . $div_close;
-// }
+ if (preg_match('{
+ \A
+ ( # $1 =
tag
+
]*
+ \b
+ markdown\s*=\s* ([\'"]) # $2 = attr quote char
+ 1
+ \2
+ [^>]*
+ >
+ )
+ ( # $3 = contents
+ .*
+ )
+ (
) # $4 = closing tag
+ \z
+ }xs', $block, $matches))
+ {
+ list(, $div_open, , $div_content, $div_close) = $matches;
+
+ # We can't call Markdown(), because that resets the hash;
+ # that initialization code should be pulled into its own sub, though.
+ $div_content = $this->hashHTMLBlocks($div_content);
+
+ # Run document gamut methods on the content.
+ foreach ($this->document_gamut as $method => $priority) {
+ $div_content = $this->$method($div_content);
+ }
+
+ $div_open = preg_replace(
+ '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open);
+
+ $graf = $div_open . "\n" . $div_content . "\n" . $div_close;
+ }
$grafs[$key] = $graf;
}
}
@@ -1366,7 +1390,6 @@ class Markdown_Parser {
}
function _doAutoLinks_email_callback($matches) {
$address = $matches[1];
- $address = $this->unescapeSpecialChars($address);
$link = $this->encodeEmailAddress($address);
return $this->hashSpan($link);
}
@@ -1413,15 +1436,6 @@ class Markdown_Parser {
}
- function unescapeSpecialChars($text) {
- #
- # Swap back in all the special characters we've hidden.
- #
- return str_replace(array_values($this->escape_table),
- array_keys($this->escape_table), $text);
- }
-
-
function tokenizeHTML($str) {
#
# Parameter: String containing HTML + Markdown markup.
@@ -1599,8 +1613,8 @@ class MarkdownExtra_Parser extends Markdown_Parser {
"doDefLists" => 45,
);
$this->span_gamut += array(
- "doFootnotes" => 4,
- "doAbbreviations" => 5,
+ "doFootnotes" => 5,
+ "doAbbreviations" => 70,
);
parent::Markdown_Parser();
@@ -1614,6 +1628,9 @@ class MarkdownExtra_Parser extends Markdown_Parser {
var $abbr_matches = array();
var $html_cleans = array();
+ # Status flag to avoid invalid nesting.
+ var $in_footnote = false;
+
function transform($text) {
#
@@ -1763,8 +1780,9 @@ class MarkdownExtra_Parser extends Markdown_Parser {
# If in Markdown span mode, add a empty-string span-level hash
# after each newline to prevent triggering any block element.
if ($span) {
- $newline = $this->hashSpan("") . "\n";
- $parts[0] = str_replace("\n", $newline, $parts[0]);
+ $void = $this->hashSpan("", true) ;
+ $newline = $this->hashSpan("", true) . "\n";
+ $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
}
$parsed .= $parts[0]; # Text before current tag.
@@ -1879,9 +1897,14 @@ class MarkdownExtra_Parser extends Markdown_Parser {
\s* # Eat whitespace before the `markdown` attribute
markdown
\s*=\s*
- (["\']) # $1: quote delimiter
- (.*?) # $2: attribute value
- \1 # matching delimiter
+ (?:
+ (["\']) # $1: quote delimiter
+ (.*?) # $2: attribute value
+ \1 # matching delimiter
+ |
+ ([^\s>]*) # $3: unquoted attribute value
+ )
+ () # $4: make $3 always defined (avoid warnings)
}xs';
# Regex to match any tag.
@@ -1967,14 +1990,14 @@ class MarkdownExtra_Parser extends Markdown_Parser {
# Check for `markdown="1"` attribute and handle it.
#
if ($md_attr &&
- preg_match($markdown_attr_match, $tag, $attr_matches) &&
- preg_match('/^1|block|span$/', $attr_matches[2]))
+ preg_match($markdown_attr_match, $tag, $attr_m) &&
+ preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
{
# Remove `markdown` attribute from opening tag.
$tag = preg_replace($markdown_attr_match, '', $tag);
# Check if text inside this tag must be parsed in span mode.
- $this->mode = $attr_matches[2];
+ $this->mode = $attr_m[2] . $attr_m[3];
$span_mode = $this->mode == 'span' || $this->mode != 'block' &&
preg_match("{^<(?:$this->contain_span_tags)\b}", $tag);
@@ -2033,7 +2056,7 @@ class MarkdownExtra_Parser extends Markdown_Parser {
$text = $this->unhash($text);
# Then hash the tag.
- $key = md5($text);
+ $key = "C\x1A". md5($text);
$this->html_cleans[$key] = $text;
$this->html_hashes[$key] = $text;
return $key; # String that will replace the clean tag.
@@ -2052,10 +2075,10 @@ class MarkdownExtra_Parser extends Markdown_Parser {
# --------
#
$text = preg_replace_callback(
- '{ (^.+?) (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? [ \t]*\n=+[ \t]*\n+ }mx',
+ '{ (^.+?) (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? [ ]*\n=+[ ]*\n+ }mx',
array(&$this, '_doHeaders_callback_setext_h1'), $text);
$text = preg_replace_callback(
- '{ (^.+?) (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? [ \t]*\n-+[ \t]*\n+ }mx',
+ '{ (^.+?) (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? [ ]*\n-+[ ]*\n+ }mx',
array(&$this, '_doHeaders_callback_setext_h2'), $text);
# atx-style headers:
@@ -2067,12 +2090,12 @@ class MarkdownExtra_Parser extends Markdown_Parser {
#
$text = preg_replace_callback('{
^(\#{1,6}) # $1 = string of #\'s
- [ \t]*
+ [ ]*
(.+?) # $2 = Header text
- [ \t]*
+ [ ]*
\#* # optional closing #\'s (not counted)
(?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # id attribute
- [ \t]*
+ [ ]*
\n+
}xm',
array(&$this, '_doHeaders_callback_atx'), $text);
@@ -2368,14 +2391,14 @@ class MarkdownExtra_Parser extends Markdown_Parser {
(?=\S) # Not followed by whitespace
(?!__) # or two others marker chars.
( # $2: Content
- (?:
+ (?>
[^_]+? # Anthing not em markers.
|
# Balence any regular _ emphasis inside.
(?
[^*]+? # Anthing not em markers.
|
# Balence any regular * emphasis inside.
\* (?=\S) (.+?) (?<=\S) \*
+ |
+ \* # Allow unbalenced as last resort.
)+?
)
(?<=\S) \*\* # End mark not preceded by whitespace.
@@ -2401,7 +2426,7 @@ class MarkdownExtra_Parser extends Markdown_Parser {
# Then
:
$text = preg_replace_callback(array(
'{ ( (?html_blocks[$block_key]) &&
!isset($this->html_cleans[$clean_key]));
@@ -2461,7 +2486,7 @@ class MarkdownExtra_Parser extends Markdown_Parser {
# Link defs are in the form: [^id]: url "optional title"
$text = preg_replace_callback('{
^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?: # note_id = $1
- [ \t]*
+ [ ]*
\n? # maybe *one* newline
( # text = $2 (no blank lines allowed)
(?:
@@ -2479,7 +2504,7 @@ class MarkdownExtra_Parser extends Markdown_Parser {
return $text;
}
function _stripFootnotes_callback($matches) {
- $note_id = $matches[1];
+ $note_id = $this->fn_id_prefix . $matches[1];
$this->footnotes[$note_id] = $this->outdent($matches[2]);
return ''; # String that will replace the block
}
@@ -2490,7 +2515,9 @@ class MarkdownExtra_Parser extends Markdown_Parser {
# Replace footnote references in $text [^id] with a special text-token
# which will be can be
#
- $text = preg_replace('{\[\^(.+?)\]}', "a\0fn:\\1\0z", $text);
+ if (!$this->in_footnote && !$this->in_anchor) {
+ $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
+ }
return $text;
}
@@ -2499,7 +2526,8 @@ class MarkdownExtra_Parser extends Markdown_Parser {
#
# Append footnote list to text.
#
- $text = preg_replace_callback('{a\0fn:(.*?)\0z}',
+
+ $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
array(&$this, '_appendFootnotes_callback'), $text);
if (!empty($this->footnotes_ordered)) {
@@ -2523,6 +2551,8 @@ class MarkdownExtra_Parser extends Markdown_Parser {
}
$num = 0;
+ $this->in_footnote = true;
+
foreach ($this->footnotes_ordered as $note_id => $footnote) {
$footnote .= "\n"; # Need to append newline before parsing.
$footnote = $this->runBlockGamut("$footnote\n");
@@ -2542,10 +2572,10 @@ class MarkdownExtra_Parser extends Markdown_Parser {
$text .= "\n\n";
}
+ $this->in_footnote = false;
+
$text .= "\n";
$text .= "";
-
- $text = preg_replace('{a\{fn:(.*?)\}z}', '[^\\1]', $text);
}
return $text;
}
@@ -2589,8 +2619,7 @@ class MarkdownExtra_Parser extends Markdown_Parser {
function stripAbbreviations($text) {
#
- # Strips abbreviations from text, stores the URLs and titles in
- # hash references.
+ # Strips abbreviations from text, stores titles in hash references.
#
$less_than_tab = $this->tab_width - 1;
@@ -2614,12 +2643,16 @@ class MarkdownExtra_Parser extends Markdown_Parser {
function doAbbreviations($text) {
#
- # Replace footnote references in $text [^id] with a link to the footnote.
+ # Find defined abbreviations in text and wrap them in