Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / vendor / michelf / php-markdown / Michelf / Markdown.php
index c3eaf446444fd7df8b8cb024dfe3d8311bd598c9..e4c2c23615a2a0a694eeb7240242dbe78543bda6 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/>
  */
 
@@ -18,7 +18,7 @@ class Markdown implements MarkdownInterface {
         * Define the package version
         * @var string
         */
-       const MARKDOWNLIB_VERSION = "1.7.0";
+       const MARKDOWNLIB_VERSION = "1.8.0";
 
        /**
         * Simple function interface - Initialize the parser and return the result
@@ -61,14 +61,14 @@ class Markdown implements MarkdownInterface {
         * @var int
         */
        public $tab_width = 4;
-       
+
        /**
         * Change to `true` to disallow markup or entities.
         * @var boolean
         */
        public $no_markup   = false;
        public $no_entities = false;
-       
+
 
        /**
         * Change to `true` to enable line breaks on \n without two trailling spaces
@@ -94,7 +94,7 @@ class Markdown implements MarkdownInterface {
         * @var callable
         */
        public $header_id_func = null;
-       
+
        /**
         * Optional function for converting code block content to HTML
         * @var callable
@@ -111,7 +111,7 @@ class Markdown implements MarkdownInterface {
         * Class attribute to toggle "enhanced ordered list" behaviour
         * setting this to true will allow ordered lists to start from the index
         * number that is defined first.
-        * 
+        *
         * For example:
         * 2. List item two
         * 3. List item three
@@ -155,17 +155,17 @@ class Markdown implements MarkdownInterface {
        public function __construct() {
                $this->_initDetab();
                $this->prepareItalicsAndBold();
-       
-               $this->nested_brackets_re = 
+
+               $this->nested_brackets_re =
                        str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
                        str_repeat('\])*', $this->nested_brackets_depth);
-       
-               $this->nested_url_parenthesis_re = 
+
+               $this->nested_url_parenthesis_re =
                        str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
                        str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
-               
+
                $this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
-               
+
                // Sort document, block, and span gamut in ascendent priority order.
                asort($this->document_gamut);
                asort($this->block_gamut);
@@ -180,13 +180,19 @@ class Markdown implements MarkdownInterface {
        protected $urls        = array();
        protected $titles      = array();
        protected $html_hashes = array();
-       
+
        /**
         * Status flag to avoid invalid nesting.
         * @var boolean
         */
        protected $in_anchor = false;
-       
+
+       /**
+        * Status flag to avoid invalid nesting.
+        * @var boolean
+        */
+       protected $in_emphasis_processing = false;
+
        /**
         * Called before the transformation process starts to setup parser states.
         * @return void
@@ -197,8 +203,9 @@ class Markdown implements MarkdownInterface {
                $this->titles      = $this->predef_titles;
                $this->html_hashes = array();
                $this->in_anchor   = false;
+               $this->in_emphasis_processing = false;
        }
-       
+
        /**
         * Called after the transformation process to clear any variable which may
         * be taking up memory unnecessarly.
@@ -221,7 +228,7 @@ class Markdown implements MarkdownInterface {
         */
        public function transform($text) {
                $this->setup();
-       
+
                # Remove UTF-8 BOM and marker character in input, if present.
                $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
 
@@ -248,7 +255,7 @@ class Markdown implements MarkdownInterface {
                foreach ($this->document_gamut as $method => $priority) {
                        $text = $this->$method($text);
                }
-               
+
                $this->teardown();
 
                return $text . "\n";
@@ -271,7 +278,7 @@ class Markdown implements MarkdownInterface {
         * @return string
         */
        protected function stripLinkDefinitions($text) {
-       
+
                $less_than_tab = $this->tab_width - 1;
 
                // Link defs are in the form: ^[id]: url "optional title"
@@ -338,8 +345,8 @@ class Markdown implements MarkdownInterface {
                 * for is hard-coded:
                 *
                 * *  List "a" is made of tags which can be both inline or block-level.
-                *    These will be treated block-level when the start tag is alone on 
-                *    its line, otherwise they're not matched here and will be taken as 
+                *    These will be treated block-level when the start tag is alone on
+                *    its line, otherwise they're not matched here and will be taken as
                 *    inline later.
                 * *  List "b" is made of tags which are always block-level;
                 */
@@ -363,7 +370,7 @@ class Markdown implements MarkdownInterface {
                          |
                                \'[^\']*\'      # text inside single quotes (tolerate ">")
                          )*
-                       )?      
+                       )?
                        ';
                $content =
                        str_repeat('
@@ -380,7 +387,7 @@ class Markdown implements MarkdownInterface {
                        str_repeat('
                                          </\2\s*>      # closing nested tag
                                        )
-                                 |                             
+                                 |
                                        <(?!/\2\s*>     # other tags with a different name
                                  )
                                )*',
@@ -409,9 +416,9 @@ class Markdown implements MarkdownInterface {
                        )
                        (                                               # save in $1
 
-                         # Match from `\n<tag>` to `</tag>\n`, handling nested tags 
+                         # Match from `\n<tag>` to `</tag>\n`, handling nested tags
                          # in between.
-                                       
+
                                                [ ]{0,'.$less_than_tab.'}
                                                <('.$block_tags_b_re.')# start tag = $2
                                                '.$attr.'>                      # attributes followed by > and \n
@@ -429,28 +436,28 @@ class Markdown implements MarkdownInterface {
                                                </\3>                           # the matching end tag
                                                [ ]*                            # trailing spaces/tabs
                                                (?=\n+|\Z)      # followed by a newline or end of document
-                                       
-                       | # Special case just for <hr />. It was easier to make a special 
+
+                       | # Special case just for <hr />. It was easier to make a special
                          # case than to make the other regex more complicated.
-                       
+
                                                [ ]{0,'.$less_than_tab.'}
                                                <(hr)                           # start tag = $2
                                                '.$attr.'                       # attributes
                                                /?>                                     # the matching end tag
                                                [ ]*
                                                (?=\n{2,}|\Z)           # followed by a blank line or end of document
-                       
+
                        | # Special case for standalone HTML comments:
-                       
+
                                        [ ]{0,'.$less_than_tab.'}
                                        (?s:
                                                <!-- .*? -->
                                        )
                                        [ ]*
                                        (?=\n{2,}|\Z)           # followed by a blank line or end of document
-                       
+
                        | # PHP and ASP-style processor instructions (<? and <%)
-                       
+
                                        [ ]{0,'.$less_than_tab.'}
                                        (?s:
                                                <([?%])                 # $2
@@ -459,7 +466,7 @@ class Markdown implements MarkdownInterface {
                                        )
                                        [ ]*
                                        (?=\n{2,}|\Z)           # followed by a blank line or end of document
-                                       
+
                        )
                        )}Sxmi',
                        array($this, '_hashHTMLBlocks_callback'),
@@ -479,9 +486,9 @@ class Markdown implements MarkdownInterface {
                $key  = $this->hashBlock($text);
                return "\n\n$key\n\n";
        }
-       
+
        /**
-        * Called whenever a tag must be hashed when a function insert an atomic 
+        * Called whenever a tag must be hashed when a function insert an atomic
         * element in the text stream. Passing $text to through this function gives
         * a unique text-token which will be reverted back when calling unhash.
         *
@@ -498,7 +505,7 @@ class Markdown implements MarkdownInterface {
                // Swap back any tag hash found in $text so we do not have to `unhash`
                // multiple times at the end.
                $text = $this->unhash($text);
-               
+
                // Then hash the block.
                static $i = 0;
                $key = "$boundary\x1A" . ++$i . $boundary;
@@ -531,10 +538,10 @@ class Markdown implements MarkdownInterface {
        /**
         * Run block gamut tranformations.
         *
-        * We need to escape raw HTML in Markdown source before doing anything 
-        * else. This need to be done for each block, and not only at the 
+        * We need to escape raw HTML in Markdown source before doing anything
+        * else. This need to be done for each block, and not only at the
         * begining in the Markdown function since hashed blocks can be part of
-        * list items and could have been indented. Indented blocks would have 
+        * list items and could have been indented. Indented blocks would have
         * been seen as a code block in a previous pass of hashHTMLBlocks.
         *
         * @param  string $text
@@ -546,7 +553,7 @@ class Markdown implements MarkdownInterface {
        }
 
        /**
-        * Run block gamut tranformations, without hashing HTML blocks. This is 
+        * Run block gamut tranformations, without hashing HTML blocks. This is
         * useful when HTML blocks are known to be already hashed, like in the first
         * whole-document pass.
         *
@@ -554,11 +561,11 @@ class Markdown implements MarkdownInterface {
         * @return string
         */
        protected function runBasicBlockGamut($text) {
-       
+
                foreach ($this->block_gamut as $method => $priority) {
                        $text = $this->$method($text);
                }
-               
+
                // Finally form paragraph and restore hashed blocks.
                $text = $this->formParagraphs($text);
 
@@ -582,7 +589,7 @@ class Markdown implements MarkdownInterface {
                                [ ]*            # Tailing spaces
                                $                       # End of line.
                        }mx',
-                       "\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n", 
+                       "\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n",
                        $text
                );
        }
@@ -629,10 +636,10 @@ class Markdown implements MarkdownInterface {
         */
        protected function doHardBreaks($text) {
                if ($this->hard_wrap) {
-                       return preg_replace_callback('/ *\n/', 
+                       return preg_replace_callback('/ *\n/',
                                array($this, '_doHardBreaks_callback'), $text);
                } else {
-                       return preg_replace_callback('/ {2,}\n/', 
+                       return preg_replace_callback('/ {2,}\n/',
                                array($this, '_doHardBreaks_callback'), $text);
                }
        }
@@ -656,7 +663,7 @@ class Markdown implements MarkdownInterface {
                        return $text;
                }
                $this->in_anchor = true;
-               
+
                // First, handle reference-style links: [link text] [id]
                $text = preg_replace_callback('{
                        (                                       # wrap whole match in $1
@@ -729,7 +736,7 @@ class Markdown implements MarkdownInterface {
                        // 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);
@@ -737,14 +744,14 @@ class Markdown implements MarkdownInterface {
                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];
                                $title = $this->encodeAttribute($title);
                                $result .=  " title=\"$title\"";
                        }
-               
+
                        $link_text = $this->runSpanGamut($link_text);
                        $result .= ">$link_text</a>";
                        $result = $this->hashPart($result);
@@ -779,7 +786,7 @@ class Markdown implements MarkdownInterface {
                        $title = $this->encodeAttribute($title);
                        $result .=  " title=\"$title\"";
                }
-               
+
                $link_text = $this->runSpanGamut($link_text);
                $result .= ">$link_text</a>";
 
@@ -807,7 +814,7 @@ class Markdown implements MarkdownInterface {
                          \]
 
                        )
-                       }xs', 
+                       }xs',
                        array($this, '_doImages_reference_callback'), $text);
 
                // Next, handle inline images:  ![alt text](url "optional title")
@@ -906,7 +913,7 @@ class Markdown implements MarkdownInterface {
                 * Setext-style headers:
                 *        Header 1
                 *        ========
-                *  
+                *
                 *        Header 2
                 *        --------
                 */
@@ -944,7 +951,7 @@ class Markdown implements MarkdownInterface {
                if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1])) {
                        return $matches[0];
                }
-               
+
                $level = $matches[2]{0} == '=' ? 1 : 2;
 
                // ID attribute generation
@@ -977,7 +984,7 @@ class Markdown implements MarkdownInterface {
         * @param  string $headerValue
         * @return string
         */
-       protected function _generateIdFromHeaderValue($headerValue) {           
+       protected function _generateIdFromHeaderValue($headerValue) {
                if (!is_callable($this->header_id_func)) {
                        return "";
                }
@@ -1035,10 +1042,10 @@ class Markdown implements MarkdownInterface {
                                  )
                                )
                        '; // mx
-                       
+
                        // We use a different prefix before nested lists than top-level lists.
                        //See extended comment in _ProcessListItems().
-               
+
                        if ($this->list_level) {
                                $text = preg_replace_callback('{
                                                ^
@@ -1132,7 +1139,7 @@ class Markdown implements MarkdownInterface {
                 * without resorting to mind-reading. Perhaps the solution is to
                 * change the syntax rules such that sub-lists must start with a
                 * starting cardinal number; e.g. "1." or "a.".
-                */             
+                */
                $this->list_level++;
 
                // Trim trailing blank lines:
@@ -1166,7 +1173,7 @@ class Markdown implements MarkdownInterface {
                $marker_space = $matches[3];
                $tailing_blank_line =& $matches[5];
 
-               if ($leading_line || $tailing_blank_line || 
+               if ($leading_line || $tailing_blank_line ||
                        preg_match('/\n{2,}/', $item))
                {
                        // Replace marker with the appropriate whitespace indentation
@@ -1273,7 +1280,7 @@ class Markdown implements MarkdownInterface {
         * @var array
         */
        protected $em_strong_prepared_relist;
-       
+
        /**
         * Prepare regular expressions for searching emphasis tokens in any
         * context.
@@ -1289,7 +1296,7 @@ class Markdown implements MarkdownInterface {
                                }
                                $token_relist[] = $em_re;
                                $token_relist[] = $strong_re;
-                               
+
                                // Construct master expression from list.
                                $token_re = '{(' . implode('|', $token_relist) . ')}';
                                $this->em_strong_prepared_relist["$em$strong"] = $token_re;
@@ -1303,24 +1310,29 @@ class Markdown implements MarkdownInterface {
         * @return string
         */
        protected function doItalicsAndBold($text) {
+               if ($this->in_emphasis_processing) {
+                       return $text; // avoid reentrency
+               }
+               $this->in_emphasis_processing = true;
+
                $token_stack = array('');
                $text_stack = array('');
                $em = '';
                $strong = '';
                $tree_char_em = false;
-               
+
                while (1) {
                        // Get prepared regular expression for seraching emphasis tokens
                        // in current context.
                        $token_re = $this->em_strong_prepared_relist["$em$strong"];
-                       
-                       // Each loop iteration search for the next emphasis token. 
+
+                       // Each loop iteration search for the next emphasis token.
                        // Each token is then passed to handleSpanToken.
                        $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
                        $text_stack[0] .= $parts[0];
                        $token =& $parts[1];
                        $text =& $parts[2];
-                       
+
                        if (empty($token)) {
                                // Reached end of text span: empty stack without emitting.
                                // any more emphasis.
@@ -1330,7 +1342,7 @@ class Markdown implements MarkdownInterface {
                                }
                                break;
                        }
-                       
+
                        $token_len = strlen($token);
                        if ($tree_char_em) {
                                // Reached closing marker while inside a three-char emphasis.
@@ -1369,7 +1381,7 @@ class Markdown implements MarkdownInterface {
                                                $$tag = ''; // $$tag stands for $em or $strong
                                        }
                                } else {
-                                       // Reached opening three-char emphasis marker. Push on token 
+                                       // Reached opening three-char emphasis marker. Push on token
                                        // stack; will be handled by the special condition above.
                                        $em = $token{0};
                                        $strong = "$em$em";
@@ -1383,6 +1395,7 @@ class Markdown implements MarkdownInterface {
                                        if (strlen($token_stack[0]) == 1) {
                                                $text_stack[1] .= array_shift($token_stack);
                                                $text_stack[0] .= array_shift($text_stack);
+                                               $em = '';
                                        }
                                        // Closing strong marker:
                                        array_shift($token_stack);
@@ -1417,6 +1430,7 @@ class Markdown implements MarkdownInterface {
                                }
                        }
                }
+               $this->in_emphasis_processing = false;
                return $text_stack[0];
        }
 
@@ -1453,9 +1467,9 @@ class Markdown implements MarkdownInterface {
                $bq = $this->runBlockGamut($bq); // recurse
 
                $bq = preg_replace('/^/m', "  ", $bq);
-               // These leading spaces cause problem with <pre> content, 
+               // These leading spaces cause problem with <pre> content,
                // 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);
 
                return "\n" . $this->hashBlock("<blockquote>\n$bq\n</blockquote>") . "\n\n";
@@ -1525,7 +1539,7 @@ class Markdown implements MarkdownInterface {
 //                                     // 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);
@@ -1582,9 +1596,9 @@ class Markdown implements MarkdownInterface {
 
                return $url;
        }
-       
+
        /**
-        * Smart processing for ampersands and angle brackets that need to 
+        * Smart processing for ampersands and angle brackets that need to
         * be encoded. Valid character entities are left alone unless the
         * no-entities mode is set.
         * @param  string $text
@@ -1596,7 +1610,7 @@ class Markdown implements MarkdownInterface {
                } else {
                        // Ampersand-encoding based entirely on Nat Irons's Amputator
                        // MT plugin: <http://bumppo.net/projects/amputator/>
-                       $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', 
+                       $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/',
                                                                '&amp;', $text);
                }
                // Encode remaining <'s
@@ -1724,7 +1738,7 @@ class Markdown implements MarkdownInterface {
         */
        protected function parseSpan($str) {
                $output = '';
-               
+
                $span_re = '{
                                (
                                        \\\\'.$this->escape_chars_re.'
@@ -1752,16 +1766,16 @@ class Markdown implements MarkdownInterface {
                                }xs';
 
                while (1) {
-                       // Each loop iteration seach for either the next tag, the next 
-                       // openning code span marker, or the next escaped character. 
+                       // Each loop iteration seach for either the next tag, the next
+                       // openning code span marker, or the next escaped character.
                        // Each token is then passed to handleSpanToken.
                        $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
-                       
+
                        // Create token from text preceding tag.
                        if ($parts[0] != "") {
                                $output .= $parts[0];
                        }
-                       
+
                        // Check if we reach the end.
                        if (isset($parts[1])) {
                                $output .= $this->handleSpanToken($parts[1], $parts[2]);
@@ -1770,7 +1784,7 @@ class Markdown implements MarkdownInterface {
                                break;
                        }
                }
-               
+
                return $output;
        }
 
@@ -1787,7 +1801,7 @@ class Markdown implements MarkdownInterface {
                                return $this->hashPart("&#". ord($token{1}). ";");
                        case "`":
                                // Search for end marker in remaining text.
-                               if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', 
+                               if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm',
                                        $str, $matches))
                                {
                                        $str = $matches[2];
@@ -1823,11 +1837,11 @@ class Markdown implements MarkdownInterface {
         * For each line we separate the line in blocks delemited by tab characters.
         * Then we reconstruct every line by adding the  appropriate number of space
         * between each blocks.
-        * 
+        *
         * @param  string $text
         * @return string
         */
-       protected function detab($text) {       
+       protected function detab($text) {
                $text = preg_replace_callback('/^.*\t.*$/m',
                        array($this, '_detab_callback'), $text);
 
@@ -1842,7 +1856,7 @@ class Markdown implements MarkdownInterface {
        protected function _detab_callback($matches) {
                $line = $matches[0];
                $strlen = $this->utf8_strlen; // strlen function for UTF-8.
-               
+
                // Split in blocks.
                $blocks = explode("\t", $line);
                // Add each blocks to the line.
@@ -1850,7 +1864,7 @@ class Markdown implements MarkdownInterface {
                unset($blocks[0]); // Do not add first block twice.
                foreach ($blocks as $block) {
                        // Calculate amount of space, insert spaces, insert block.
-                       $amount = $this->tab_width - 
+                       $amount = $this->tab_width -
                                $strlen($line, 'UTF-8') % $this->tab_width;
                        $line .= str_repeat(" ", $amount) . $block;
                }
@@ -1859,20 +1873,20 @@ class Markdown implements MarkdownInterface {
 
        /**
         * Check for the availability of the function in the `utf8_strlen` property
-        * (initially `mb_strlen`). If the function is not available, create a 
+        * (initially `mb_strlen`). If the function is not available, create a
         * function that will loosely count the number of UTF-8 characters with a
         * regular expression.
         * @return void
         */
        protected function _initDetab() {
-       
+
                if (function_exists($this->utf8_strlen)) {
                        return;
                }
 
-               $this->utf8_strlen = create_function('$text', 'return preg_match_all(
-                       "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/", 
-                       $text, $m);');
+               $this->utf8_strlen = function($text) {
+                       return preg_match_all('/[\x00-\xBF]|[\xC0-\xFF][\x80-\xBF]*/', $text, $m);
+               };
        }
 
        /**
@@ -1881,7 +1895,7 @@ class Markdown implements MarkdownInterface {
         * @return string
         */
        protected function unhash($text) {
-               return preg_replace_callback('/(.)\x1A[0-9]+\1/', 
+               return preg_replace_callback('/(.)\x1A[0-9]+\1/',
                        array($this, '_unhash_callback'), $text);
        }