Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / vendor / michelf / php-markdown / Michelf / MarkdownExtra.php
index ac6b1b4f270ad35e9489d70b5a2d2dc69faab644..a8f7f2c5de28c3c1165e3410cc7a01e0eb1208b3 100644 (file)
@@ -4,7 +4,7 @@
  *
  * @package   php-markdown
  * @author    Michel Fortin <michel.fortin@michelf.com>
- * @copyright 2004-2016 Michel Fortin <https://michelf.com/projects/php-markdown/>
+ * @copyright 2004-2018 Michel Fortin <https://michelf.com/projects/php-markdown/>
  * @copyright (Original Markdown) 2004-2006 John Gruber <https://daringfireball.net/projects/markdown/>
  */
 
@@ -23,14 +23,14 @@ class MarkdownExtra extends \Michelf\Markdown {
         * @var string
         */
        public $fn_id_prefix = "";
-       
+
        /**
         * Optional title attribute for footnote links and backlinks.
         * @var string
         */
        public $fn_link_title     = "";
        public $fn_backlink_title = "";
-       
+
        /**
         * Optional class attribute for footnote links and backlinks.
         * @var string
@@ -73,20 +73,26 @@ class MarkdownExtra extends \Michelf\Markdown {
         */
        public $predef_abbr = array();
 
+       /**
+        * Only convert atx-style headers if there's a space between the header and #
+        * @var boolean
+        */
+       public $hashtag_protection = false;
+
        /**
         * Parser implementation
         */
-       
+
        /**
         * Constructor function. Initialize the parser object.
         * @return void
         */
        public function __construct() {
-               // Add extra escapable characters before parent constructor 
+               // Add extra escapable characters before parent constructor
                // initialize the table.
                $this->escape_chars .= ':|';
-               
-               // Insert extra document, block, and span transformations. 
+
+               // Insert extra document, block, and span transformations.
                // Parent constructor will do the sorting.
                $this->document_gamut += array(
                        "doFencedCodeBlocks" => 5,
@@ -103,12 +109,12 @@ class MarkdownExtra extends \Michelf\Markdown {
                        "doFootnotes"        => 5,
                        "doAbbreviations"    => 70,
                );
-               
+
                $this->enhanced_ordered_list = true;
                parent::__construct();
        }
-       
-       
+
+
        /**
         * Extra variables used during extra transformations.
         * @var array
@@ -118,21 +124,21 @@ class MarkdownExtra extends \Michelf\Markdown {
        protected $footnotes_ref_count = array();
        protected $footnotes_numbers = array();
        protected $abbr_desciptions = array();
-       /** @var @string */
+       /** @var string */
        protected $abbr_word_re = '';
-       
+
        /**
         * Give the current footnote number.
         * @var integer
         */
        protected $footnote_counter = 1;
-       
+
        /**
         * Setting up Extra-specific variables.
         */
        protected function setup() {
                parent::setup();
-               
+
                $this->footnotes = array();
                $this->footnotes_ordered = array();
                $this->footnotes_ref_count = array();
@@ -140,7 +146,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                $this->abbr_desciptions = array();
                $this->abbr_word_re = '';
                $this->footnote_counter = 1;
-               
+
                foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
                        if ($this->abbr_word_re)
                                $this->abbr_word_re .= '|';
@@ -159,11 +165,11 @@ class MarkdownExtra extends \Michelf\Markdown {
                $this->footnotes_numbers = array();
                $this->abbr_desciptions = array();
                $this->abbr_word_re = '';
-               
+
                parent::teardown();
        }
-       
-       
+
+
        /**
         * Extra attribute parser
         */
@@ -197,7 +203,7 @@ class MarkdownExtra extends \Michelf\Markdown {
         */
        protected function doExtraAttributes($tag_name, $attr, $defaultIdValue = null, $classes = array()) {
                if (empty($attr) && !$defaultIdValue && empty($classes)) return "";
-               
+
                // Split on components
                preg_match_all('/[#.a-z][-_:a-zA-Z0-9=]+/', $attr, $matches);
                $elements = $matches[0];
@@ -288,38 +294,38 @@ class MarkdownExtra extends \Michelf\Markdown {
        /**
         * HTML block parser
         */
-       
+
        /**
         * Tags that are always treated as block tags
         * @var string
         */
        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
         * @var string
         */
        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:
         * @var string
         */
        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
         * they appear
         * @var string
         */
        protected $clean_tags_re = 'script|style|math|svg';
-       
+
        /**
         * Tags that do not need to be closed.
         * @var string
         */
        protected $auto_close_tags_re = 'hr|img|param|source|track';
-       
+
        /**
         * Hashify HTML Blocks and "clean tags".
         *
@@ -330,7 +336,7 @@ class MarkdownExtra extends \Michelf\Markdown {
         * hard-coded.
         *
         * This works by calling _HashHTMLBlocks_InMarkdown, which then calls
-        * _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1" 
+        * _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1"
         * attribute is found within a tag, _HashHTMLBlocks_InHTML calls back
         *  _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
         * These two functions are calling each other. It's recursive!
@@ -344,15 +350,15 @@ class MarkdownExtra extends \Michelf\Markdown {
 
                // Call the HTML-in-Markdown hasher.
                list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
-               
+
                return $text;
        }
 
        /**
         * Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
         *
-        * *   $indent is the number of space to be ignored when checking for code 
-        *     blocks. This is important because if we don't take the indent into 
+        * *   $indent is the number of space to be ignored when checking for code
+        *     blocks. This is important because if we don't take the indent into
         *     account, something like this (which looks right) won't work as expected:
         *
         *     <div>
@@ -364,11 +370,11 @@ class MarkdownExtra extends \Michelf\Markdown {
         *     If you don't like this, just don't indent the tag on which
         *     you apply the markdown="1" attribute.
         *
-        * *   If $enclosing_tag_re is not empty, stops at the first unmatched closing 
+        * *   If $enclosing_tag_re is not empty, stops at the first unmatched closing
         *     tag with that name. Nested tags supported.
         *
-        * *   If $span is true, text inside must treated as span. So any double 
-        *     newline will be replaced by a single newline so that it does not create 
+        * *   If $span is true, text inside must treated as span. So any double
+        *     newline will be replaced by a single newline so that it does not create
         *     paragraphs.
         *
         * Returns an array of that form: ( processed text , remaining text )
@@ -382,18 +388,18 @@ class MarkdownExtra extends \Michelf\Markdown {
        protected function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
                                                                                $enclosing_tag_re = '', $span = false)
        {
-       
+
                if ($text === '') return array('', '');
 
                // Regex to check for the presense of newlines around a block tag.
                $newline_before_re = '/(?:^\n?|\n\n)*$/';
-               $newline_after_re = 
+               $newline_after_re =
                        '{
                                ^                                               # Start of text following the tag.
                                (?>[ ]*<!--.*?-->)?             # Optional comment.
                                [ ]*\n                                  # Must be followed by newline.
                        }xs';
-               
+
                // Regex to match any tag.
                $block_tag_re =
                        '{
@@ -448,7 +454,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                                )
                        }xs';
 
-               
+
                $depth = 0;             // Current depth inside the tag tree.
                $parsed = "";   // Parsed text that will be returned.
 
@@ -457,31 +463,31 @@ class MarkdownExtra extends \Michelf\Markdown {
                do {
                        // Split the text using the first $tag_match pattern found.
                        // Text before  pattern will be first in the array, text after
-                       // pattern will be at the end, and between will be any catches made 
+                       // pattern will be at the end, and between will be any catches made
                        // by the pattern.
-                       $parts = preg_split($block_tag_re, $text, 2, 
+                       $parts = preg_split($block_tag_re, $text, 2,
                                                                PREG_SPLIT_DELIM_CAPTURE);
-                       
-                       // If in Markdown span mode, add a empty-string span-level hash 
+
+                       // If in Markdown span mode, add a empty-string span-level hash
                        // after each newline to prevent triggering any block element.
                        if ($span) {
                                $void = $this->hashPart("", ':');
                                $newline = "\n$void";
                                $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
                        }
-                       
+
                        $parsed .= $parts[0]; // Text before current tag.
-                       
+
                        // If end of $text has been reached. Stop loop.
                        if (count($parts) < 3) {
                                $text = "";
                                break;
                        }
-                       
+
                        $tag  = $parts[1]; // Tag to handle.
                        $text = $parts[2]; // Remaining text after current tag.
                        $tag_re = preg_quote($tag); // For use in a regular expression.
-                       
+
                        // Check for: Fenced code block marker.
                        // Note: need to recheck the whole tag to disambiguate backtick
                        // fences from code spans
@@ -490,7 +496,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                                $fence_indent = strlen($capture[1]); // use captured indent in re
                                $fence_re = $capture[2]; // use captured fence in re
                                if (preg_match('{^(?>.*\n)*?[ ]{' . ($fence_indent) . '}' . $fence_re . '[ ]*(?:\n|$)}', $text,
-                                       $matches)) 
+                                       $matches))
                                {
                                        // End marker found: pass text unchanged until marker.
                                        $parsed .= $tag . $matches[0];
@@ -503,7 +509,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                        }
                        // Check for: Indented code block.
                        else if ($tag{0} == "\n" || $tag{0} == " ") {
-                               // Indented code block: pass it unchanged, will be handled 
+                               // Indented code block: pass it unchanged, will be handled
                                // later.
                                $parsed .= $tag;
                        }
@@ -525,7 +531,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                                }
                        }
                        // Check for: Opening Block level tag or
-                       //            Opening Context Block tag (like ins and del) 
+                       //            Opening Context Block tag (like ins and del)
                        //               used as a block tag (tag is alone on it's line).
                        else if (preg_match('{^<(?:' . $this->block_tags_re . ')\b}', $tag) ||
                                (       preg_match('{^<(?:' . $this->context_block_tags_re . ')\b}', $tag) &&
@@ -534,9 +540,9 @@ class MarkdownExtra extends \Michelf\Markdown {
                                )
                        {
                                // Need to parse tag and following text using the HTML parser.
-                               list($block_text, $text) = 
+                               list($block_text, $text) =
                                        $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
-                               
+
                                // Make sure it stays outside of any paragraph by adding newlines.
                                $parsed .= "\n\n$block_text\n\n";
                        }
@@ -547,9 +553,9 @@ class MarkdownExtra extends \Michelf\Markdown {
                        {
                                // Need to parse tag and following text using the HTML parser.
                                // (don't check for markdown attribute)
-                               list($block_text, $text) = 
+                               list($block_text, $text) =
                                        $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
-                               
+
                                $parsed .= $block_text;
                        }
                        // Check for: Tag with same name as enclosing tag.
@@ -567,14 +573,14 @@ class MarkdownExtra extends \Michelf\Markdown {
                                        $text = $tag . $text;
                                        break;
                                }
-                               
+
                                $parsed .= $tag;
                        }
                        else {
                                $parsed .= $tag;
                        }
                } while ($depth >= 0);
-               
+
                return array($parsed, $text);
        }
 
@@ -594,7 +600,7 @@ class MarkdownExtra extends \Michelf\Markdown {
         */
        protected function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
                if ($text === '') return array('', '');
-               
+
                // Regex to match `markdown` attribute inside of a tag.
                $markdown_attr_re = '
                        {
@@ -602,15 +608,15 @@ class MarkdownExtra extends \Michelf\Markdown {
                                markdown
                                \s*=\s*
                                (?>
-                                       (["\'])         # $1: quote delimiter           
+                                       (["\'])         # $1: quote delimiter
                                        (.*?)           # $2: attribute value
-                                       \1                      # matching delimiter    
+                                       \1                      # matching delimiter
                                |
                                        ([^\s>]*)       # $3: unquoted attribute value
                                )
                                ()                              # $4: make $3 always defined (avoid warnings)
                        }xs';
-               
+
                // Regex to match any tag.
                $tag_re = '{
                                (                                       # $2: Capture whole tag.
@@ -633,9 +639,9 @@ class MarkdownExtra extends \Michelf\Markdown {
                                        <!\[CDATA\[.*?\]\]>     # CData Block
                                )
                        }xs';
-               
+
                $original_text = $text;         // Save original text in case of faliure.
-               
+
                $depth          = 0;    // Current depth inside the tag tree.
                $block_text     = "";   // Temporary text holder for current text.
                $parsed         = "";   // Parsed text that will be returned.
@@ -649,22 +655,22 @@ class MarkdownExtra extends \Michelf\Markdown {
                do {
                        // Split the text using the first $tag_match pattern found.
                        // Text before  pattern will be first in the array, text after
-                       // pattern will be at the end, and between will be any catches made 
+                       // pattern will be at the end, and between will be any catches made
                        // by the pattern.
                        $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
-                       
+
                        if (count($parts) < 3) {
                                // End of $text reached with unbalenced tag(s).
                                // In that case, we return original text unchanged and pass the
-                               // first character as filtered to prevent an infinite loop in the 
+                               // first character as filtered to prevent an infinite loop in the
                                // parent function.
                                return array($original_text{0}, substr($original_text, 1));
                        }
-                       
+
                        $block_text .= $parts[0]; // Text before current tag.
                        $tag         = $parts[1]; // Tag to handle.
                        $text        = $parts[2]; // Remaining text after current tag.
-                       
+
                        // Check for: Auto-close tag (like <hr/>)
                        //                       Comments and Processing Instructions.
                        if (preg_match('{^</?(?:' . $this->auto_close_tags_re . ')\b}', $tag) ||
@@ -680,20 +686,20 @@ class MarkdownExtra extends \Michelf\Markdown {
                                        if ($tag{1} == '/')                                             $depth--;
                                        else if ($tag{strlen($tag)-2} != '/')   $depth++;
                                }
-                               
+
                                // Check for `markdown="1"` attribute and handle it.
-                               if ($md_attr && 
+                               if ($md_attr &&
                                        preg_match($markdown_attr_re, $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_re, '', $tag);
-                                       
+
                                        // Check if text inside this tag must be parsed in span mode.
                                        $this->mode = $attr_m[2] . $attr_m[3];
                                        $span_mode = $this->mode == 'span' || $this->mode != 'block' &&
                                                preg_match('{^<(?:' . $this->contain_span_tags_re . ')\b}', $tag);
-                                       
+
                                        // Calculate indent before tag.
                                        if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
                                                $strlen = $this->utf8_strlen;
@@ -701,48 +707,48 @@ class MarkdownExtra extends \Michelf\Markdown {
                                        } else {
                                                $indent = 0;
                                        }
-                                       
+
                                        // End preceding block with this tag.
                                        $block_text .= $tag;
                                        $parsed .= $this->$hash_method($block_text);
-                                       
+
                                        // Get enclosing tag name for the ParseMarkdown function.
                                        // (This pattern makes $tag_name_re safe without quoting.)
                                        preg_match('/^<([\w:$]*)\b/', $tag, $matches);
                                        $tag_name_re = $matches[1];
-                                       
+
                                        // Parse the content using the HTML-in-Markdown parser.
                                        list ($block_text, $text)
-                                               = $this->_hashHTMLBlocks_inMarkdown($text, $indent, 
+                                               = $this->_hashHTMLBlocks_inMarkdown($text, $indent,
                                                        $tag_name_re, $span_mode);
-                                       
+
                                        // Outdent markdown text.
                                        if ($indent > 0) {
-                                               $block_text = preg_replace("/^[ ]{1,$indent}/m", "", 
+                                               $block_text = preg_replace("/^[ ]{1,$indent}/m", "",
                                                                                                        $block_text);
                                        }
-                                       
+
                                        // Append tag content to parsed text.
                                        if (!$span_mode)        $parsed .= "\n\n$block_text\n\n";
                                        else                            $parsed .= "$block_text";
-                                       
+
                                        // Start over with a new block.
                                        $block_text = "";
                                }
                                else $block_text .= $tag;
                        }
-                       
+
                } while ($depth > 0);
-               
+
                // Hash last block text that wasn't processed inside the loop.
                $parsed .= $this->$hash_method($block_text);
-               
+
                return array($parsed, $text);
        }
 
        /**
         * Called whenever a tag must be hashed when a function inserts a "clean" tag
-        * in $text, it passes through this function and is automaticaly escaped, 
+        * in $text, it passes through this function and is automaticaly escaped,
         * blocking invalid nested overlap.
         * @param  string $text
         * @return string
@@ -835,7 +841,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                        // for shortcut links like [this][] or [this].
                        $link_id = $link_text;
                }
-               
+
                // lower-case and turn embedded newlines into spaces
                $link_id = strtolower($link_id);
                $link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
@@ -843,7 +849,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                if (isset($this->urls[$link_id])) {
                        $url = $this->urls[$link_id];
                        $url = $this->encodeURLAttribute($url);
-                       
+
                        $result = "<a href=\"$url\"";
                        if ( isset( $this->titles[$link_id] ) ) {
                                $title = $this->titles[$link_id];
@@ -852,7 +858,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                        }
                        if (isset($this->ref_attr[$link_id]))
                                $result .= $this->ref_attr[$link_id];
-               
+
                        $link_text = $this->runSpanGamut($link_text);
                        $result .= ">$link_text</a>";
                        $result = $this->hashPart($result);
@@ -889,7 +895,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                        $result .=  " title=\"$title\"";
                }
                $result .= $attr;
-               
+
                $link_text = $this->runSpanGamut($link_text);
                $result .= ">$link_text</a>";
 
@@ -917,7 +923,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                          \]
 
                        )
-                       }xs', 
+                       }xs',
                        array($this, '_doImages_reference_callback'), $text);
 
                // Next, handle inline images:  ![alt text](url "optional title")
@@ -1021,7 +1027,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                // Setext-style headers:
                //  Header 1  {#header1}
                //        ========
-               //  
+               //
                //        Header 2  {#header2 .class1 .class2}
                //        --------
                //
@@ -1042,7 +1048,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                //
                $text = preg_replace_callback('{
                                ^(\#{1,6})      # $1 = string of #\'s
-                               [ ]*
+                               [ ]'.($this->hashtag_protection ? '+' : '*').'
                                (.+?)           # $2 = Header text
                                [ ]*
                                \#*                     # optional closing #\'s (not counted)
@@ -1107,10 +1113,10 @@ class MarkdownExtra extends \Michelf\Markdown {
                                [ ]{0,' . $less_than_tab . '}   # Allowed whitespace.
                                [|]                                                     # Optional leading pipe (present)
                                (.+) \n                                         # $1: Header row (at least one pipe)
-                               
+
                                [ ]{0,' . $less_than_tab . '}   # Allowed whitespace.
                                [|] ([ ]*[-:]+[-| :]*) \n       # $2: Header underline
-                               
+
                                (                                                       # $3: Cells
                                        (?>
                                                [ ]*                            # Allowed whitespace.
@@ -1132,10 +1138,10 @@ class MarkdownExtra extends \Michelf\Markdown {
                                ^                                                       # Start of a line
                                [ ]{0,' . $less_than_tab . '}   # Allowed whitespace.
                                (\S.*[|].*) \n                          # $1: Header row (at least one pipe)
-                               
+
                                [ ]{0,' . $less_than_tab . '}   # Allowed whitespace.
                                ([-:]+[ ]*[|][-| :]*) \n        # $2: Header underline
-                               
+
                                (                                                       # $3: Cells
                                        (?>
                                                .* [|] .* \n            # Row content
@@ -1159,7 +1165,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                $content        = $matches[3];
 
                $content        = preg_replace('/^ *[|]/m', '', $content);
-               
+
                return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
        }
 
@@ -1192,7 +1198,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                $head           = preg_replace('/[|] *$/m', '', $head);
                $underline      = preg_replace('/[|] *$/m', '', $underline);
                $content        = preg_replace('/[|] *$/m', '', $content);
-               
+
                // Reading alignement from header underline.
                $separators     = preg_split('/ *[|] */', $underline);
                foreach ($separators as $n => $s) {
@@ -1205,14 +1211,14 @@ class MarkdownExtra extends \Michelf\Markdown {
                        else
                                $attr[$n] = '';
                }
-               
-               // Parsing span elements, including code spans, character escapes, 
+
+               // Parsing span elements, including code spans, character escapes,
                // and inline HTML tags, so that pipes inside those gets ignored.
                $head           = $this->parseSpan($head);
                $headers        = preg_split('/ *[|] */', $head);
                $col_count      = count($headers);
                $attr       = array_pad($attr, $col_count, '');
-               
+
                // Write column headers.
                $text = "<table>\n";
                $text .= "<thead>\n";
@@ -1221,20 +1227,20 @@ class MarkdownExtra extends \Michelf\Markdown {
                        $text .= "  <th$attr[$n]>" . $this->runSpanGamut(trim($header)) . "</th>\n";
                $text .= "</tr>\n";
                $text .= "</thead>\n";
-               
+
                // Split content by row.
                $rows = explode("\n", trim($content, "\n"));
-               
+
                $text .= "<tbody>\n";
                foreach ($rows as $row) {
-                       // Parsing span elements, including code spans, character escapes, 
+                       // Parsing span elements, including code spans, character escapes,
                        // and inline HTML tags, so that pipes inside those gets ignored.
                        $row = $this->parseSpan($row);
-                       
+
                        // Split row by cell.
                        $row_cells = preg_split('/ *[|] */', $row, $col_count);
                        $row_cells = array_pad($row_cells, $col_count, '');
-                       
+
                        $text .= "<tr>\n";
                        foreach ($row_cells as $n => $cell)
                                $text .= "  <td$attr[$n]>" . $this->runSpanGamut(trim($cell)) . "</td>\n";
@@ -1242,7 +1248,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                }
                $text .= "</tbody>\n";
                $text .= "</table>";
-               
+
                return $this->hashBlock($text) . "\n";
        }
 
@@ -1299,7 +1305,7 @@ class MarkdownExtra extends \Michelf\Markdown {
        protected function _doDefLists_callback($matches) {
                // Re-usable patterns to match list item bullets and number markers:
                $list = $matches[1];
-               
+
                // Turn double returns into triple returns, so that we can make a
                // paragraph for the last item in a list, if necessary:
                $result = trim($this->processDefListItems($list));
@@ -1314,9 +1320,9 @@ class MarkdownExtra extends \Michelf\Markdown {
         * @return string
         */
        protected function processDefListItems($list_str) {
-       
+
                $less_than_tab = $this->tab_width - 1;
-               
+
                // Trim trailing blank lines:
                $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
 
@@ -1327,9 +1333,9 @@ class MarkdownExtra extends \Michelf\Markdown {
                                [ ]{0,' . $less_than_tab . '}   # leading whitespace
                                (?!\:[ ]|[ ])                                   # negative lookahead for a definition
                                                                                                #   mark (colon) or more whitespace.
-                               (?> \S.* \n)+?                                  # actual term (not whitespace). 
-                       )                       
-                       (?=\n?[ ]{0,3}:[ ])                                     # lookahead for following line feed 
+                               (?> \S.* \n)+?                                  # actual term (not whitespace).
+                       )
+                       (?=\n?[ ]{0,3}:[ ])                                     # lookahead for following line feed
                                                                                                #   with a definition mark.
                        }xm',
                        array($this, '_processDefListItems_callback_dt'), $list_str);
@@ -1346,8 +1352,8 @@ class MarkdownExtra extends \Michelf\Markdown {
                                (?:                                                             # next term or end of text
                                        [ ]{0,' . $less_than_tab . '} \:[ ]     |
                                        <dt> | \z
-                               )                                               
-                       )                                       
+                               )
+                       )
                        }xm',
                        array($this, '_processDefListItems_callback_dd'), $list_str);
 
@@ -1399,14 +1405,14 @@ class MarkdownExtra extends \Michelf\Markdown {
         * ~~~
         * Code block
         * ~~~
-        * 
+        *
         * @param  string $text
         * @return string
         */
        protected function doFencedCodeBlocks($text) {
-       
+
                $less_than_tab = $this->tab_width;
-               
+
                $text = preg_replace_callback('{
                                (?:\n|\A)
                                # 1: Opening marker
@@ -1422,7 +1428,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                                        ' . $this->id_class_attr_catch_re . ' # 3: Extra attributes
                                )?
                                [ ]* \n # Whitespace and newline following marker.
-                               
+
                                # 4: Content
                                (
                                        (?>
@@ -1430,7 +1436,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                                                .*\n+
                                        )+
                                )
-                               
+
                                # Closing marker.
                                \1 [ ]* (?= \n )
                        }xm',
@@ -1468,7 +1474,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                $pre_attr_str  = $this->code_attr_on_pre ? $attr_str : '';
                $code_attr_str = $this->code_attr_on_pre ? '' : $attr_str;
                $codeblock  = "<pre$pre_attr_str><code$code_attr_str>$codeblock</code></pre>";
-               
+
                return "\n\n".$this->hashBlock($codeblock)."\n\n";
        }
 
@@ -1478,7 +1484,7 @@ class MarkdownExtra extends \Michelf\Markdown {
         * @return string
         */
        protected function _doFencedCodeBlocks_newlines($matches) {
-               return str_repeat("<br$this->empty_element_suffix", 
+               return str_repeat("<br$this->empty_element_suffix",
                        strlen($matches[0]));
        }
 
@@ -1518,27 +1524,27 @@ class MarkdownExtra extends \Michelf\Markdown {
                // Wrap <p> tags and unhashify HTML blocks
                foreach ($grafs as $key => $value) {
                        $value = trim($this->runSpanGamut($value));
-                       
+
                        // Check if this should be enclosed in a paragraph.
                        // Clean tag hashes & block tag hashes are left alone.
                        $is_p = $wrap_in_p && !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
-                       
+
                        if ($is_p) {
                                $value = "<p>$value</p>";
                        }
                        $grafs[$key] = $value;
                }
-               
-               // Join grafs in one text, then unhash HTML tags. 
+
+               // Join grafs in one text, then unhash HTML tags.
                $text = implode("\n\n", $grafs);
-               
+
                // Finish by removing any tag hashes still present in $text.
                $text = $this->unhash($text);
-               
+
                return $text;
        }
-       
-       
+
+
        /**
         * Footnotes - Strips link definitions from text, stores the URLs and
         * titles in hash references.
@@ -1554,15 +1560,15 @@ class MarkdownExtra extends \Michelf\Markdown {
                          [ ]*
                          \n?                                   # maybe *one* newline
                        (                                               # text = $2 (no blank lines allowed)
-                               (?:                                     
+                               (?:
                                        .+                              # actual text
                                |
-                                       \n                              # newlines but 
+                                       \n                              # newlines but
                                        (?!\[.+?\][ ]?:\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
                                )*
-                       )               
+                       )
                        }xm',
                        array($this, '_stripFootnotes_callback'),
                        $text);
@@ -1581,7 +1587,7 @@ class MarkdownExtra extends \Michelf\Markdown {
        }
 
        /**
-        * Replace footnote references in $text [^id] with a special text-token 
+        * Replace footnote references in $text [^id] with a special text-token
         * which will be replaced by the actual footnote marker in appendFootnotes.
         * @param  string $text
         * @return string
@@ -1599,12 +1605,12 @@ class MarkdownExtra extends \Michelf\Markdown {
         * @return string
         */
        protected function appendFootnotes($text) {
-               $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', 
+               $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
                        array($this, '_appendFootnotes_callback'), $text);
-       
+
                if (!empty($this->footnotes_ordered)) {
                        $text .= "\n\n";
-                       $text .= "<div class=\"footnotes\">\n";
+                       $text .= "<div class=\"footnotes\" role=\"doc-endnotes\">\n";
                        $text .= "<hr" . $this->empty_element_suffix . "\n";
                        $text .= "<ol>\n\n";
 
@@ -1618,10 +1624,12 @@ class MarkdownExtra extends \Michelf\Markdown {
                                $title = $this->fn_backlink_title;
                                $title = $this->encodeAttribute($title);
                                $attr .= " title=\"$title\"";
+                               $attr .= " aria-label=\"$title\"";
                        }
+                       $attr .= " role=\"doc-backlink\"";
                        $backlink_text = $this->fn_backlink_html;
                        $num = 0;
-                       
+
                        while (!empty($this->footnotes_ordered)) {
                                $footnote = reset($this->footnotes_ordered);
                                $note_id = key($this->footnotes_ordered);
@@ -1629,12 +1637,12 @@ class MarkdownExtra extends \Michelf\Markdown {
                                $ref_count = $this->footnotes_ref_count[$note_id];
                                unset($this->footnotes_ref_count[$note_id]);
                                unset($this->footnotes[$note_id]);
-                               
+
                                $footnote .= "\n"; // Need to append newline before parsing.
-                               $footnote = $this->runBlockGamut("$footnote\n");                                
-                               $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', 
+                               $footnote = $this->runBlockGamut("$footnote\n");
+                               $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
                                        array($this, '_appendFootnotes_callback'), $footnote);
-                               
+
                                $attr = str_replace("%%", ++$num, $attr);
                                $note_id = $this->encodeAttribute($note_id);
 
@@ -1649,12 +1657,12 @@ class MarkdownExtra extends \Michelf\Markdown {
                                } else {
                                        $footnote .= "\n\n<p>$backlink</p>";
                                }
-                               
-                               $text .= "<li id=\"fn:$note_id\">\n";
+
+                               $text .= "<li id=\"fn:$note_id\" role=\"doc-endnote\">\n";
                                $text .= $footnote . "\n";
                                $text .= "</li>\n\n";
                        }
-                       
+
                        $text .= "</ol>\n";
                        $text .= "</div>";
                }
@@ -1668,7 +1676,7 @@ class MarkdownExtra extends \Michelf\Markdown {
         */
        protected function _appendFootnotes_callback($matches) {
                $node_id = $this->fn_id_prefix . $matches[1];
-               
+
                // Create footnote marker only if it has a corresponding footnote *and*
                // the footnote hasn't been used by another marker.
                if (isset($this->footnotes[$node_id])) {
@@ -1695,20 +1703,21 @@ class MarkdownExtra extends \Michelf\Markdown {
                                $title = $this->encodeAttribute($title);
                                $attr .= " title=\"$title\"";
                        }
-                       
+                       $attr .= " role=\"doc-noteref\"";
+
                        $attr = str_replace("%%", $num, $attr);
                        $node_id = $this->encodeAttribute($node_id);
-                       
+
                        return
                                "<sup id=\"fnref$ref_count_mark:$node_id\">".
                                "<a href=\"#fn:$node_id\"$attr>$num</a>".
                                "</sup>";
                }
-               
+
                return "[^" . $matches[1] . "]";
        }
-               
-       
+
+
        /**
         * Abbreviations - strips abbreviations from text, stores titles in hash
         * references.
@@ -1721,7 +1730,7 @@ class MarkdownExtra extends \Michelf\Markdown {
                // Link defs are in the form: [id]*: url "optional title"
                $text = preg_replace_callback('{
                        ^[ ]{0,' . $less_than_tab . '}\*\[(.+?)\][ ]?:  # abbr_id = $1
-                       (.*)                                    # text = $2 (no blank lines allowed)    
+                       (.*)                                    # text = $2 (no blank lines allowed)
                        }xm',
                        array($this, '_stripAbbreviations_callback'),
                        $text);
@@ -1751,7 +1760,7 @@ class MarkdownExtra extends \Michelf\Markdown {
         */
        protected function doAbbreviations($text) {
                if ($this->abbr_word_re) {
-                       // cannot use the /x modifier because abbr_word_re may 
+                       // cannot use the /x modifier because abbr_word_re may
                        // contain significant spaces:
                        $text = preg_replace_callback('{' .
                                '(?<![\w\x1A])' .