Development

Changeset 6191

You must first sign up to be able to contribute.

Changeset 6191

Show
Ignore:
Timestamp:
11/27/07 23:47:01 (5 years ago)
Author:
Simone.Carletti
Message:

sfMarkdownPlugin:
- updated parser version to PHP Markdown 1.1.7
- sfMarkdownPlugin 0.1.1

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • plugins/sfMarkdownPlugin/README

    r4712 r6191  
    156156== Changelog == 
    157157 
     1582007-11-27: 0.1.1 alpha 
     159 
     160 * Updated: PHP Markdown 1.1.7 
     161 
    1581622007-07-22: 0.1.0 alpha 
    159163 
  • plugins/sfMarkdownPlugin/lib/markdown.php

    r4712 r6191  
    1313 
    1414 
    15 define( 'MARKDOWN_VERSION',       "1.0.1g" ); # Tue 3 Jul 2007 
    16 define( 'MARKDOWNEXTRA_VERSION',  "1.1.3" );  # Tue 3 Jul 2007 
     15define( 'MARKDOWN_VERSION',  "1.0.1k" ); # Wed 26 Sep 2007 
     16define( 'MARKDOWNEXTRA_VERSION',  "1.1.7" ); # Wed 26 Sep 2007 
    1717 
    1818 
     
    2222 
    2323# Change to ">" for HTML output 
    24 define( 'MARKDOWN_EMPTY_ELEMENT_SUFFIX',  " />"); 
     24@define( 'MARKDOWN_EMPTY_ELEMENT_SUFFIX',  " />"); 
    2525 
    2626# Define the width of a tab for code blocks. 
    27 define( 'MARKDOWN_TAB_WIDTH',     4 ); 
     27@define( 'MARKDOWN_TAB_WIDTH',     4 ); 
    2828 
    2929# Optional title attribute for footnote links and backlinks. 
    30 define( 'MARKDOWN_FN_LINK_TITLE',         "" ); 
    31 define( 'MARKDOWN_FN_BACKLINK_TITLE',     "" ); 
     30@define( 'MARKDOWN_FN_LINK_TITLE',         "" ); 
     31@define( 'MARKDOWN_FN_BACKLINK_TITLE',     "" ); 
    3232 
    3333# Optional class attribute for footnote links and backlinks. 
    34 define( 'MARKDOWN_FN_LINK_CLASS',         "" ); 
    35 define( 'MARKDOWN_FN_BACKLINK_CLASS',     "" ); 
     34@define( 'MARKDOWN_FN_LINK_CLASS',         "" ); 
     35@define( 'MARKDOWN_FN_BACKLINK_CLASS',     "" ); 
    3636 
    3737 
     
    4141 
    4242# Change to false to remove Markdown from posts and/or comments. 
    43 define( 'MARKDOWN_WP_POSTS',      true ); 
    44 define( 'MARKDOWN_WP_COMMENTS',   true ); 
     43@define( 'MARKDOWN_WP_POSTS',      true ); 
     44@define( 'MARKDOWN_WP_COMMENTS',   true ); 
    4545 
    4646 
     
    4848### Standard Function Interface ### 
    4949 
    50 define( 'MARKDOWN_PARSER_CLASS',  'MarkdownExtra_Parser' ); 
     50@define( 'MARKDOWN_PARSER_CLASS',  'MarkdownExtra_Parser' ); 
    5151 
    5252function Markdown($text) { 
     
    7272Plugin URI: http://www.michelf.com/projects/php-markdown/ 
    7373Description: <a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://www.michelf.com/projects/php-markdown/">More...</a> 
    74 Version: 1.1.3 
     74Version: 1.1.7 
    7575Author: Michel Fortin 
    7676Author URI: http://www.michelf.com/ 
     
    117117    add_filter('get_comment_excerpt', 'mdwp_strip_p', 7); 
    118118   
    119     global $wp_markdown_hidden
    120     $wp_markdown_hidden[1] = 
    121       '<p> </p> <pre> </pre> <ol> </ol> <ul> </ul> <li> </li>'
    122     $wp_markdown_hidden[2] = explode(' ', str_rot13( 
     119    global $mdwp_hidden_tags, $mdwp_placeholders
     120    $mdwp_hidden_tags = explode(' ', 
     121      '<p> </p> <pre> </pre> <ol> </ol> <ul> </ul> <li> </li>')
     122    $mdwp_placeholders = explode(' ', str_rot13( 
    123123      'pEj07ZbbBZ U1kqgh4w4p pre2zmeN6K QTi31t9pre ol0MP1jzJR '. 
    124124      'ML5IjmbRol ulANi1NsGY J7zRLJqPul liA8ctl16T K9nhooUHli')); 
     
    136136 
    137137  function mdwp_hide_tags($text) { 
    138     global $wp_markdown_hidden; 
    139     return str_replace(explode($wp_markdown_hidden),  
    140               explode($wp_markdown_hidden), $text); 
     138    global $mdwp_hidden_tags, $mdwp_placeholders; 
     139    return str_replace($mdwp_hidden_tags, $mdwp_placeholders, $text); 
    141140  } 
    142141  function mdwp_show_tags($text) { 
    143     global $markdown_hidden_tags; 
    144     return str_replace(array_values($markdown_hidden_tags),  
    145               array_keys($markdown_hidden_tags), $text); 
     142    global $mdwp_hidden_tags, $mdwp_placeholders; 
     143    return str_replace($mdwp_placeholders, $mdwp_hidden_tags, $text); 
    146144  } 
    147145} 
     
    212210  # Table of hash values for escaped characters: 
    213211  var $escape_chars = '\`*_{}[]()>#+-.!'; 
    214   var $escape_table = array(); 
    215   var $backslash_escape_table = array(); 
    216212 
    217213  # Change to ">" for HTML output. 
    218214  var $empty_element_suffix = MARKDOWN_EMPTY_ELEMENT_SUFFIX; 
    219215  var $tab_width = MARKDOWN_TAB_WIDTH; 
     216   
     217  # Change to `true` to disallow markup or entities. 
     218  var $no_markup = false; 
     219  var $no_entities = false; 
    220220 
    221221 
     
    233233      str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth). 
    234234      str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth); 
    235      
    236     # Create an identical table but for escaped characters. 
    237     foreach (preg_split('/(?!^|$)/', $this->escape_chars) as $char) { 
    238       $entity = "&#". ord($char). ";"; 
    239       $this->escape_table[$char] = $entity; 
    240       $this->backslash_escape_table["\\$char"] = $entity; 
    241     } 
    242235     
    243236    # Sort document, block, and span gamut in ascendent priority order. 
     
    251244  var $urls = array(); 
    252245  var $titles = array(); 
    253   var $html_blocks = array(); 
    254   var $html_hashes = array(); # Contains both blocks and span hashes. 
     246  var $html_hashes = array(); 
    255247   
    256248  # Status flag to avoid invalid nesting. 
     
    271263    $this->urls = array(); 
    272264    $this->titles = array(); 
    273     $this->html_blocks = array(); 
    274265    $this->html_hashes = array(); 
    275266 
    276267    # Standardize line endings: 
    277268    #   DOS to Unix and Mac to Unix 
    278     $text = str_replace(array("\r\n", "\r"), "\n", $text); 
     269    $text = preg_replace('{\r\n?}', "\n", $text); 
    279270 
    280271    # Make sure $text ends with a couple of newlines: 
     
    349340 
    350341  function hashHTMLBlocks($text) { 
     342    if ($this->no_markup)  return $text; 
     343 
    351344    $less_than_tab = $this->tab_width - 1; 
    352345 
     
    357350    # phrase emphasis, and spans. The list of tags we're looking for is 
    358351    # hard-coded: 
    359     $block_tags_a = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'. 
    360             'script|noscript|form|fieldset|iframe|math|ins|del'; 
     352    # 
     353    # *  List "a" is made of tags which can be both inline or block-level. 
     354    #    These will be treated block-level when the start tag is alone on  
     355    #    its line, otherwise they're not matched here and will be taken as  
     356    #    inline later. 
     357    # *  List "b" is made of tags which are always block-level; 
     358    # 
     359    $block_tags_a = 'ins|del'; 
    361360    $block_tags_b = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'. 
    362361            'script|noscript|form|fieldset|iframe|math'; 
     
    385384          <\2     # nested opening tag 
    386385          '.$attr.' # attributes 
    387           (?: 
     386          (?> 
    388387            /> 
    389388          | 
     
    398397        )*', 
    399398        $nested_tags_level); 
     399    $content2 = str_replace('\2', '\3', $content); 
    400400 
    401401    # First, look for nested blocks, e.g.: 
     
    410410    # We need to do this before the next, more liberal match, because the next 
    411411    # match will start at the first `<div>` and stop at the first `</div>`. 
    412     $text = preg_replace_callback('{ 
    413           (           # save in $1 
    414             ^         # start of line  (with /m) 
    415             <('.$block_tags_a.')# start tag = $2 
    416             '.$attr.'>\n    # attributes followed by > and \n 
     412    $text = preg_replace_callback('{(?> 
     413      (?> 
     414        (?<=\n\n)   # Starting after a blank line 
     415        |       # or 
     416        \A\n?     # the beginning of the doc 
     417      ) 
     418      (           # save in $1 
     419 
     420        # Match from `\n<tag>` to `</tag>\n`, handling nested tags  
     421        # in between. 
     422           
     423            [ ]{0,'.$less_than_tab.'} 
     424            <('.$block_tags_b.')# start tag = $2 
     425            '.$attr.'>      # attributes followed by > and \n 
    417426            '.$content.'    # content, support nesting 
    418427            </\2>       # the matching end tag 
    419428            [ ]*        # trailing spaces/tabs 
    420429            (?=\n+|\Z)  # followed by a newline or end of document 
    421           ) 
    422       }xmi', 
    423       array(&$this, '_hashHTMLBlocks_callback'), 
    424       $text); 
    425  
    426     # 
    427     # Match from `\n<tag>` to `</tag>\n`, handling nested tags in between. 
    428     # 
    429     $text = preg_replace_callback('{ 
    430           (           # save in $1 
    431             ^         # start of line  (with /m) 
    432             <('.$block_tags_b.')# start tag = $2 
    433             '.$attr.'>      # attributes followed by > 
    434             '.$content.'    # content, support nesting 
    435             </\2>       # the matching end tag 
     430 
     431      | # Special version for tags of group a. 
     432 
     433            [ ]{0,'.$less_than_tab.'} 
     434            <('.$block_tags_a.')# start tag = $3 
     435            '.$attr.'>[ ]*\n  # attributes followed by > 
     436            '.$content2.'   # content, support nesting 
     437            </\3>       # the matching end tag 
    436438            [ ]*        # trailing spaces/tabs 
    437439            (?=\n+|\Z)  # followed by a newline or end of document 
    438           ) 
    439       }xmi', 
    440       array(&$this, '_hashHTMLBlocks_callback'), 
    441       $text); 
    442  
    443     # Special case just for <hr />. It was easier to make a special case than 
    444     # to make the other regex more complicated. 
    445     $text = preg_replace_callback('{ 
    446           (?: 
    447             (?<=\n\n)   # Starting after a blank line 
    448             |       # or 
    449             \A\n?     # the beginning of the doc 
    450           ) 
    451           (           # save in $1 
     440           
     441      | # Special case just for <hr />. It was easier to make a special  
     442        # case than to make the other regex more complicated. 
     443       
    452444            [ ]{0,'.$less_than_tab.'} 
    453445            <(hr)       # start tag = $2 
     
    457449            [ ]* 
    458450            (?=\n{2,}|\Z)   # followed by a blank line or end of document 
    459           ) 
    460       }xi', 
    461       array(&$this, '_hashHTMLBlocks_callback'), 
    462       $text); 
    463  
    464     # Special case for standalone HTML comments: 
    465     $text = preg_replace_callback('{ 
    466         (?: 
    467           (?<=\n\n)   # Starting after a blank line 
    468           |       # or 
    469           \A\n?     # the beginning of the doc 
    470         ) 
    471         (           # save in $1 
     451       
     452      | # Special case for standalone HTML comments: 
     453       
    472454          [ ]{0,'.$less_than_tab.'} 
    473455          (?s: 
     
    476458          [ ]* 
    477459          (?=\n{2,}|\Z)   # followed by a blank line or end of document 
    478         ) 
    479       }x', 
    480       array(&$this, '_hashHTMLBlocks_callback'), 
    481       $text); 
    482  
    483     # PHP and ASP-style processor instructions (<? and <%) 
    484     $text = preg_replace_callback('{ 
    485         (?: 
    486           (?<=\n\n)   # Starting after a blank line 
    487           |       # or 
    488           \A\n?     # the beginning of the doc 
    489         ) 
    490         (           # save in $1 
     460       
     461      | # PHP and ASP-style processor instructions (<? and <%) 
     462       
    491463          [ ]{0,'.$less_than_tab.'} 
    492464          (?s: 
     
    497469          [ ]* 
    498470          (?=\n{2,}|\Z)   # followed by a blank line or end of document 
    499         ) 
    500       }x', 
     471           
     472      ) 
     473      )}Sxmi', 
    501474      array(&$this, '_hashHTMLBlocks_callback'), 
    502475      $text); 
     
    509482    return "\n\n$key\n\n"; 
    510483  } 
    511  
    512  
    513   function hashBlock($text) { 
    514   # 
    515   # Called whenever a tag must be hashed when a function insert a block-level  
    516   # tag in $text, it pass through this function and is automaticaly escaped,  
    517   # which remove the need to call _HashHTMLBlocks at every step. 
     484   
     485   
     486  function hashPart($text, $boundary = 'X') { 
     487  # 
     488  # Called whenever a tag must be hashed when a function insert an atomic  
     489  # element in the text stream. Passing $text to through this function gives 
     490  # a unique text-token which will be reverted back when calling unhash. 
     491  # 
     492  # The $boundary argument specify what character should be used to surround 
     493  # the token. By convension, "B" is used for block elements that needs not 
     494  # to be wrapped into paragraph tags at the end, ":" is used for elements 
     495  # that are word separators and "S" is used for general span-level elements. 
    518496  # 
    519497    # Swap back any tag hash found in $text so we do not have to `unhash` 
     
    522500     
    523501    # Then hash the block. 
    524     $key = "B\x1A". md5($text); 
     502    static $i = 0; 
     503    $key = "$boundary\x1A" . ++$i . $boundary; 
    525504    $this->html_hashes[$key] = $text; 
    526     $this->html_blocks[$key] = $text; 
    527505    return $key; # String that will replace the tag. 
    528506  } 
    529507 
    530508 
    531   function hashSpan($text, $word_separator = false) { 
    532   # 
    533   # Called whenever a tag must be hashed when a function insert a span-level  
    534   # element in $text, it pass through this function and is automaticaly  
    535   # escaped, blocking invalid nested overlap. If optional argument  
    536   # $word_separator is true, surround the hash value by spaces. 
    537   # 
    538     # Swap back any tag hash found in $text so we do not have to `unhash` 
    539     # multiple times at the end. 
    540     $text = $this->unhash($text); 
    541      
    542     # Then hash the span. 
    543     $key = "S\x1A". md5($text); 
    544     if ($word_separator) $key = ":$key:"; 
    545      
    546     $this->html_hashes[$key] = $text; 
    547     return $key; # String that will replace the span tag. 
     509  function hashBlock($text) { 
     510  # 
     511  # Shortcut function for hashPart with block-level boundaries. 
     512  # 
     513    return $this->hashPart($text, 'B'); 
    548514  } 
    549515 
     
    596562    # Do Horizontal Rules: 
    597563    return preg_replace( 
    598       array('{^[ ]{0,2}([ ]?\*[ ]?){3,}[ ]*$}mx', 
    599           '{^[ ]{0,2}([ ]? -[ ]?){3,}[ ]*$}mx', 
    600           '{^[ ]{0,2}([ ]? _[ ]?){3,}[ ]*$}mx'), 
     564      '{ 
     565        ^[ ]{0,3} # Leading space 
     566        ([-*_])   # $1: First marker 
     567        (?>     # Repeated marker group 
     568          [ ]{0,2}  # Zero, one, or two spaces. 
     569          \1      # Marker character 
     570        ){2,}   # Group repeated at least twice 
     571        [ ]*    # Tailing spaces 
     572        $     # End of line. 
     573      }mx', 
    601574      "\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n",  
    602575      $text); 
     
    609582  # tags like paragraphs, headers, and list items. 
    610583  # 
    611     "escapeSpecialCharsWithinTagAttributes"  => -20, 
    612     "doCodeSpans"              => -10, 
    613     "encodeBackslashEscapes"       =>  -5
     584    # Process character escapes, code spans, and inline HTML 
     585    # in one shot. 
     586    "parseSpan"           => -30
    614587 
    615588    # Process anchor and image tags. Images must come first, 
     
    642615  function doHardBreaks($text) { 
    643616    # Do hard breaks: 
    644     $br_tag = $this->hashSpan("<br$this->empty_element_suffix\n"); 
    645     return preg_replace('/ {2,}\n/', $br_tag, $text); 
    646   } 
    647  
    648  
    649   function escapeSpecialCharsWithinTagAttributes($text) { 
    650   # 
    651   # Within tags -- meaning between < and > -- encode [\ ` * _] so they 
    652   # don't conflict with their use in Markdown for code, italics and strong. 
    653   # We're replacing each such character with its corresponding MD5 checksum 
    654   # value; this is likely overkill, but it should prevent us from colliding 
    655   # with the escape values by accident. 
    656   # 
    657     $tokens = $this->tokenizeHTML($text); 
    658     $text = '';   # rebuild $text from the tokens 
    659  
    660     foreach ($tokens as $cur_token) { 
    661       if ($cur_token[0] == 'tag') { 
    662         $cur_token[1] = str_replace('\\', $this->escape_table['\\'], $cur_token[1]); 
    663         $cur_token[1] = str_replace('`', $this->escape_table['`'], $cur_token[1]); 
    664         $cur_token[1] = str_replace('*', $this->escape_table['*'], $cur_token[1]); 
    665         $cur_token[1] = str_replace('_', $this->escape_table['_'], $cur_token[1]); 
    666       } 
    667       $text .= $cur_token[1]; 
    668     } 
    669     return $text; 
     617    return preg_replace_callback('/ {2,}\n/',  
     618      array(&$this, '_doHardBreaks_callback'), $text); 
     619  } 
     620  function _doHardBreaks_callback($matches) { 
     621    return $this->hashPart("<br$this->empty_element_suffix\n"); 
    670622  } 
    671623 
     
    768720      $link_text = $this->runSpanGamut($link_text); 
    769721      $result .= ">$link_text</a>"; 
    770       $result = $this->hashSpan($result); 
     722      $result = $this->hashPart($result); 
    771723    } 
    772724    else { 
     
    793745    $result .= ">$link_text</a>"; 
    794746 
    795     return $this->hashSpan($result); 
     747    return $this->hashPart($result); 
    796748  } 
    797749 
     
    870822      } 
    871823      $result .= $this->empty_element_suffix; 
    872       $result = $this->hashSpan($result); 
     824      $result = $this->hashPart($result); 
    873825    } 
    874826    else { 
     
    893845    $result .= $this->empty_element_suffix; 
    894846 
    895     return $this->hashSpan($result); 
     847    return $this->hashPart($result); 
    896848  } 
    897849 
     
    905857    #   -------- 
    906858    # 
    907     $text = preg_replace_callback('{ ^(.+?)[ ]*\n=+[ ]*\n+ }mx', 
    908       array(&$this, '_doHeaders_callback_setext_h1'), $text); 
    909     $text = preg_replace_callback('{ ^(.+?)[ ]*\n-+[ ]*\n+ }mx', 
    910       array(&$this, '_doHeaders_callback_setext_h2'), $text); 
     859    $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx', 
     860      array(&$this, '_doHeaders_callback_setext'), $text); 
    911861 
    912862    # atx-style headers: 
     
    929879    return $text; 
    930880  } 
    931   function _doHeaders_callback_setext_h1($matches) { 
    932     $block = "<h1>".$this->runSpanGamut($matches[1])."</h1>"; 
    933     return "\n" . $this->hashBlock($block) . "\n\n"; 
    934   } 
    935   function _doHeaders_callback_setext_h2($matches) { 
    936     $block = "<h2>".$this->runSpanGamut($matches[1])."</h2>"; 
     881  function _doHeaders_callback_setext($matches) { 
     882    $level = $matches[2]{0} == '=' ? 1 : 2; 
     883    $block = "<h$level>".$this->runSpanGamut($matches[1])."</h$level>"; 
    937884    return "\n" . $this->hashBlock($block) . "\n\n"; 
    938885  } 
     
    10941041        (?:\n\n|\A) 
    10951042        (             # $1 = the code block -- one or more lines, starting with a space/tab 
    1096           (?: 
    1097           (?:[ ]{'.$this->tab_width.'} | \t)  # Lines must start with a tab or a tab-width of spaces 
     1043          (?> 
     1044          [ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces 
    10981045          .*\n+ 
    10991046          )+ 
     
    11081055    $codeblock = $matches[1]; 
    11091056 
    1110     $codeblock = $this->encodeCode($this->outdent($codeblock)); 
    1111 //    $codeblock = $this->detab($codeblock); 
    1112     # trim leading newlines and trailing whitespace 
    1113     $codeblock = preg_replace(array('/\A\n+/', '/\n+\z/'), '', $codeblock); 
    1114  
    1115     $result = "\n\n".$this->hashBlock("<pre><code>" . $codeblock . "\n</code></pre>")."\n\n"; 
    1116  
    1117     return $result; 
    1118   } 
    1119  
    1120  
    1121   function doCodeSpans($text) { 
    1122   # 
    1123   #   * Backtick quotes are used for <code></code> spans. 
    1124   # 
    1125   #   * You can use multiple backticks as the delimiters if you want to 
    1126   #     include literal backticks in the code span. So, this input: 
    1127   # 
    1128   #     Just type ``foo `bar` baz`` at the prompt. 
    1129   # 
    1130   #     Will translate to: 
    1131   # 
    1132   #     <p>Just type <code>foo `bar` baz</code> at the prompt.</p> 
    1133   # 
    1134   #   There's no arbitrary limit to the number of backticks you 
    1135   #   can use as delimters. If you need three consecutive backticks 
    1136   #   in your code, use four for delimiters, etc. 
    1137   # 
    1138   # * You can use spaces to get literal backticks at the edges: 
    1139   # 
    1140   #     ... type `` `bar` `` ... 
    1141   # 
    1142   #     Turns to: 
    1143   # 
    1144   #     ... type <code>`bar`</code> ... 
    1145   # 
    1146     $text = preg_replace_callback('@ 
    1147         (?<!\\\)  # Character before opening ` can\'t be a backslash 
    1148         (`+)    # $1 = Opening run of ` 
    1149         (.+?)   # $2 = The code block 
    1150         (?<!`) 
    1151         \1      # Matching closer 
    1152         (?!`) 
    1153       @xs', 
    1154       array(&$this, '_doCodeSpans_callback'), $text); 
    1155  
    1156     return $text; 
    1157   } 
    1158   function _doCodeSpans_callback($matches) { 
    1159     $c = $matches[2]; 
    1160     $c = preg_replace('/^[ ]*/', '', $c); # leading whitespace 
    1161     $c = preg_replace('/[ ]*$/', '', $c); # trailing whitespace 
    1162     $c = $this->encodeCode($c); 
    1163     return $this->hashSpan("<code>$c</code>"); 
    1164   } 
    1165  
    1166  
    1167   function encodeCode($_) { 
    1168   # 
    1169   # Encode/escape certain characters inside Markdown code runs. 
    1170   # The point is that in code, these characters are literals, 
    1171   # and lose their special Markdown meanings. 
    1172   # 
    1173     # Encode all ampersands; HTML entities are not 
    1174     # entities within a Markdown code span. 
    1175     $_ = str_replace('&', '&amp;', $_); 
    1176  
    1177     # Do the angle bracket song and dance: 
    1178     $_ = str_replace(array('<',    '>'),  
    1179              array('&lt;', '&gt;'), $_); 
    1180  
    1181     # Now, escape characters that are magic in Markdown: 
    1182 //    $_ = str_replace(array_keys($this->escape_table),  
    1183 //             array_values($this->escape_table), $_); 
    1184  
    1185     return $_; 
     1057    $codeblock = $this->outdent($codeblock); 
     1058    $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); 
     1059 
     1060    # trim leading newlines and trailing newlines 
     1061    $codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock); 
     1062 
     1063    $codeblock = "<pre><code>$codeblock\n</code></pre>"; 
     1064    return "\n\n".$this->hashBlock($codeblock)."\n\n"; 
     1065  } 
     1066 
     1067 
     1068  function makeCodeSpan($code) { 
     1069  # 
     1070  # Create a code span markup for $code. Called from handleSpanToken. 
     1071  # 
     1072    $code = htmlspecialchars(trim($code), ENT_NOQUOTES); 
     1073    return $this->hashPart("<code>$code</code>"); 
    11861074  } 
    11871075 
     
    12201108    $text = $matches[2]; 
    12211109    $text = $this->runSpanGamut($text); 
    1222     return $this->hashSpan("<em>$text</em>"); 
     1110    return $this->hashPart("<em>$text</em>"); 
    12231111  } 
    12241112  function _doItalicAndBold_strong_callback($matches) { 
    12251113    $text = $matches[2]; 
    12261114    $text = $this->runSpanGamut($text); 
    1227     return $this->hashSpan("<strong>$text</strong>"); 
     1115    return $this->hashPart("<strong>$text</strong>"); 
    12281116  } 
    12291117 
     
    12321120    $text = preg_replace_callback('/ 
    12331121        (               # Wrap whole match in $1 
    1234         ( 
     1122        (?> 
    12351123          ^[ ]*>[ ]?      # ">" at the start of a line 
    12361124          .+\n          # rest of the first line 
     
    12471135    $bq = $matches[1]; 
    12481136    # trim one level of quoting - trim whitespace-only lines 
    1249     $bq = preg_replace(array('/^[ ]*>[ ]?/m', '/^[ ]+$/m'), '', $bq); 
     1137    $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq); 
    12501138    $bq = $this->runBlockGamut($bq);    # recurse 
    12511139 
     
    12711159  # 
    12721160    # Strip leading and trailing lines: 
    1273     $text = preg_replace(array('/\A\n+/', '/\n+\z/'), '', $text); 
     1161    $text = preg_replace('/\A\n+|\n+\z/', '', $text); 
    12741162 
    12751163    $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); 
    12761164 
    12771165    # 
    1278     # Wrap <p> tags. 
     1166    # Wrap <p> tags and unhashify HTML blocks 
    12791167    # 
    12801168    foreach ($grafs as $key => $value) { 
    1281       if (!isset( $this->html_blocks[$value] )) { 
     1169      if (!preg_match('/^B\x1A[0-9]+B$/', $value)) { 
     1170        # Is a paragraph. 
    12821171        $value = $this->runSpanGamut($value); 
    12831172        $value = preg_replace('/^([ ]*)/', "<p>", $value); 
     
    12851174        $grafs[$key] = $this->unhash($value); 
    12861175      } 
    1287     } 
    1288  
    1289     # 
    1290     # Unhashify HTML blocks 
    1291     # 
    1292     foreach ($grafs as $key => $graf) { 
    1293       # Modify elements of @grafs in-place... 
    1294       if (isset($this->html_blocks[$graf])) { 
    1295         $block = $this->html_blocks[$graf]; 
     1176      else { 
     1177        # Is a block. 
     1178        # Modify elements of @grafs in-place... 
     1179        $graf = $value; 
     1180        $block = $this->html_hashes[$graf]; 
    12961181        $graf = $block; 
    12971182//        if (preg_match('{ 
     
    13401225  function encodeAmpsAndAngles($text) { 
    13411226  # Smart processing for ampersands and angle brackets that need to be encoded. 
     1227    if ($this->no_entities) { 
     1228      $text = str_replace('&', '&amp;', $text); 
     1229      $text = str_replace('<', '&lt;', $text); 
     1230      return $text; 
     1231    } 
    13421232 
    13431233    # Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin: 
     
    13501240 
    13511241    return $text; 
    1352   } 
    1353  
    1354  
    1355   function encodeBackslashEscapes($text) { 
    1356   # 
    1357   # Parameter:  String. 
    1358   # Returns:    The string, with after processing the following backslash 
    1359   #       escape sequences. 
    1360   # 
    1361     # Must process escaped backslashes first. 
    1362     return str_replace(array_keys($this->backslash_escape_table), 
    1363                array_values($this->backslash_escape_table), $text); 
    13641242  } 
    13651243 
     
    13871265    $url = $this->encodeAmpsAndAngles($matches[1]); 
    13881266    $link = "<a href=\"$url\">$url</a>"; 
    1389     return $this->hashSpan($link); 
     1267    return $this->hashPart($link); 
    13901268  } 
    13911269  function _doAutoLinks_email_callback($matches) { 
    13921270    $address = $matches[1]; 
    13931271    $link = $this->encodeEmailAddress($address); 
    1394     return $this->hashSpan($link); 
     1272    return $this->hashPart($link); 
    13951273  } 
    13961274 
     
    14371315 
    14381316 
    1439   function tokenizeHTML($str) { 
    1440   # 
    1441   #   Parameter:  String containing HTML + Markdown markup. 
    1442   #   Returns:    An array of the tokens comprising the input 
    1443   #               string. Each token is either a tag or a run of text  
    1444   #               between tags. Each element of the array is a 
    1445   #               two-element array; the first is either 'tag' or 'text'; 
    1446   #               the second is the actual value. 
    1447   #   Note:       Markdown code spans are taken into account: no tag token is  
    1448   #               generated within a code span. 
    1449   # 
    1450     $tokens = array(); 
    1451  
    1452     while ($str != "") { 
    1453       # 
    1454       # Each loop iteration seach for either the next tag or the next  
    1455       # openning code span marker. If a code span marker is found, the  
    1456       # code span is extracted in entierty and will result in an extra 
    1457       # text token. 
    1458       # 
    1459       $parts = preg_split('{ 
     1317  function parseSpan($str) { 
     1318  # 
     1319  # Take the string $str and parse it into tokens, hashing embeded HTML, 
     1320  # escaped characters and handling code spans. 
     1321  # 
     1322    $output = ''; 
     1323     
     1324    $regex = '{ 
    14601325        ( 
     1326          \\\\['.preg_quote($this->escape_chars).'] 
     1327        | 
    14611328          (?<![`\\\\]) 
    14621329          `+            # code span marker 
     1330      '.( $this->no_markup ? '' : ' 
    14631331        | 
    14641332          <!--    .*?     -->   # comment 
     
    14671335        | 
    14681336          <[/!$]?[-a-zA-Z0-9:]+ # regular tags 
    1469           (?: 
     1337          (?> 
    14701338            \s 
    14711339            (?>[^"\'>]+|"[^"]*"|\'[^\']*\')* 
    14721340          )? 
    14731341          > 
     1342      ').' 
    14741343        ) 
    1475         }xs', $str, 2, PREG_SPLIT_DELIM_CAPTURE); 
     1344        }xs'; 
     1345 
     1346    while (1) { 
     1347      # 
     1348      # Each loop iteration seach for either the next tag, the next  
     1349      # openning code span marker, or the next escaped character.  
     1350      # Each token is then passed to handleSpanToken. 
     1351      # 
     1352      $parts = preg_split($regex, $str, 2, PREG_SPLIT_DELIM_CAPTURE); 
    14761353       
    14771354      # Create token from text preceding tag. 
    14781355      if ($parts[0] != "") { 
    1479         $tokens[] = array('text', $parts[0])
     1356        $output .= $parts[0]
    14801357      } 
    14811358       
    14821359      # Check if we reach the end. 
    1483       if (count($parts) < 3) { 
     1360      if (isset($parts[1])) { 
     1361        $output .= $this->handleSpanToken($parts[1], $parts[2]); 
     1362        $str = $parts[2]; 
     1363      } 
     1364      else { 
    14841365        break; 
    14851366      } 
    1486        
    1487       # Create token from tag or code span. 
    1488       if ($parts[1]{0} == "`") { 
    1489         $tokens[] = array('text', $parts[1]); 
    1490         $str = $parts[2]; 
    1491          
    1492         # Skip the whole code span, pass as text token. 
    1493         if (preg_match('/^(.*(?<!`\\\\)'.$parts[1].'(?!`))(.*)$/sm',  
     1367    } 
     1368     
     1369    return $output; 
     1370  } 
     1371   
     1372   
     1373  function handleSpanToken($token, &$str) { 
     1374  # 
     1375  # Handle $token provided by parseSpan by determining its nature and  
     1376  # returning the corresponding value that should replace it. 
     1377  # 
     1378    switch ($token{0}) { 
     1379      case "\\": 
     1380        return $this->hashPart("&#". ord($token{1}). ";"); 
     1381      case "`": 
     1382        # Search for end marker in remaining text. 
     1383        if (preg_match('/^(.*?[^`])'.$token.'(?!`)(.*)$/sm',  
    14941384          $str, $matches)) 
    14951385        { 
    1496           $tokens[] = array('text', $matches[1]); 
    14971386          $str = $matches[2]; 
     1387          $codespan = $this->makeCodeSpan($matches[1]); 
     1388          return $this->hashPart($codespan); 
    14981389        } 
    1499       } else { 
    1500         $tokens[] = array('tag', $parts[1]); 
    1501         $str = $parts[2]; 
    1502       } 
    1503     } 
    1504      
    1505     return $tokens; 
     1390        return $token; // return as text since no ending marker found. 
     1391      default: 
     1392        return $this->hashPart($token); 
     1393    } 
    15061394  } 
    15071395 
     
    15111399  # Remove one level of line-leading tabs or spaces 
    15121400  # 
    1513     return preg_replace("/^(\\t|[ ]{1,$this->tab_width})/m", "", $text); 
     1401    return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text); 
    15141402  } 
    15151403 
     
    15271415    # appropriate number of space between each blocks. 
    15281416     
     1417    $text = preg_replace_callback('/^.*\t.*$/m', 
     1418      array(&$this, '_detab_callback'), $text); 
     1419 
     1420    return $text; 
     1421  } 
     1422  function _detab_callback($matches) { 
     1423    $line = $matches[0]; 
    15291424    $strlen = $this->utf8_strlen; # strlen function for UTF-8. 
    1530     $lines = explode("\n", $text); 
    1531     $text = ""; 
    1532      
    1533     foreach ($lines as $line) { 
    1534       # Split in blocks. 
    1535       $blocks = explode("\t", $line); 
    1536       # Add each blocks to the line. 
    1537       $line = $blocks[0]; 
    1538       unset($blocks[0]); # Do not add first block twice. 
    1539       foreach ($blocks as $block) { 
    1540         # Calculate amount of space, insert spaces, insert block. 
    1541         $amount = $this->tab_width -  
    1542           $strlen($line, 'UTF-8') % $this->tab_width; 
    1543         $line .= str_repeat(" ", $amount) . $block; 
    1544       } 
    1545       $text .= "$line\n"; 
    1546     } 
    1547     return $text; 
     1425     
     1426    # Split in blocks. 
     1427    $blocks = explode("\t", $line); 
     1428    # Add each blocks to the line. 
     1429    $line = $blocks[0]; 
     1430    unset($blocks[0]); # Do not add first block twice. 
     1431    foreach ($blocks as $block) { 
     1432      # Calculate amount of space, insert spaces, insert block. 
     1433      $amount = $this->tab_width -  
     1434        $strlen($line, 'UTF-8') % $this->tab_width; 
     1435      $line .= str_repeat(" ", $amount) . $block; 
     1436    } 
     1437    return $line; 
    15481438  } 
    15491439  function _initDetab() { 
     
    15651455  # Swap back in all the tags hashed by _HashHTMLBlocks. 
    15661456  # 
    1567     return str_replace(array_keys($this->html_hashes),  
    1568                array_values($this->html_hashes), $text); 
     1457    return preg_replace_callback('/(.)\x1A[0-9]+\1/',  
     1458      array(&$this, '_unhash_callback'), $text); 
     1459  } 
     1460  function _unhash_callback($matches) { 
     1461    return $this->html_hashes[$matches[0]]; 
    15691462  } 
    15701463 
     
    16231516  var $abbr_desciptions = array(); 
    16241517  var $abbr_matches = array(); 
    1625   var $html_cleans = array(); 
    16261518   
    16271519  # Status flag to avoid invalid nesting. 
     
    16421534    $this->abbr_desciptions = array(); 
    16431535    $this->abbr_matches = array(); 
    1644     $this->html_cleans = array(); 
    16451536 
    16461537    return parent::transform($text); 
     
    17771668      # after each newline to prevent triggering any block element. 
    17781669      if ($span) { 
    1779         $void = $this->hashSpan("", true)
    1780         $newline = $this->hashSpan("", true) . "\n"; 
     1670        $void = $this->hashPart("", ':')
     1671        $newline = "$void\n"; 
    17811672        $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void; 
    17821673      } 
     
    17971688      # 
    17981689      if (# Find current paragraph 
    1799         preg_match('/(?>^\n?|\n\n)((?>.\n?)+?)$/', $parsed, $matches) && 
     1690        preg_match('/(?>^\n?|\n\n)((?>.+\n?)*?)$/', $parsed, $matches) && 
    18001691        ( 
    18011692        # Then match in it either a code block... 
     
    20481939  # blocking invalid nested overlap. 
    20491940  # 
    2050     # Swap back any tag hash found in $text so we do not have to `unhash` 
    2051     # multiple times at the end. 
    2052     $text = $this->unhash($text); 
    2053      
    2054     # Then hash the tag. 
    2055     $key = "C\x1A". md5($text); 
    2056     $this->html_cleans[$key] = $text; 
    2057     $this->html_hashes[$key] = $text; 
    2058     return $key; # String that will replace the clean tag. 
     1941    return $this->hashPart($text, 'C'); 
    20591942  } 
    20601943 
     
    20721955    # 
    20731956    $text = preg_replace_callback( 
    2074       '{ (^.+?) (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? [ ]*\n=+[ ]*\n+ }mx', 
    2075       array(&$this, '_doHeaders_callback_setext_h1'), $text); 
    2076     $text = preg_replace_callback( 
    2077       '{ (^.+?) (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? [ ]*\n-+[ ]*\n+ }mx', 
    2078       array(&$this, '_doHeaders_callback_setext_h2'), $text); 
     1957      '{ 
     1958        (^.+?)                # $1: Header text 
     1959        (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})?  # $2: Id attribute 
     1960        [ ]*\n(=+|-+)[ ]*\n+        # $3: Header footer 
     1961      }mx', 
     1962      array(&$this, '_doHeaders_callback_setext'), $text); 
    20791963 
    20801964    # atx-style headers: 
     
    21031987    return " id=\"$attr\""; 
    21041988  } 
    2105   function _doHeaders_callback_setext_h1($matches) { 
     1989  function _doHeaders_callback_setext($matches) { 
     1990    $level = $matches[3]{0} == '=' ? 1 : 2; 
    21061991    $attr  = $this->_doHeaders_attr($id =& $matches[2]); 
    2107     $block = "<h1$attr>".$this->runSpanGamut($matches[1])."</h1>"; 
    2108     return "\n" . $this->hashBlock($block) . "\n\n"; 
    2109   } 
    2110   function _doHeaders_callback_setext_h2($matches) { 
    2111     $attr  = $this->_doHeaders_attr($id =& $matches[2]); 
    2112     $block = "<h2$attr>".$this->runSpanGamut($matches[1])."</h2>"; 
     1992    $block = "<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>"; 
    21131993    return "\n" . $this->hashBlock($block) . "\n\n"; 
    21141994  } 
     
    21452025         
    21462026        (             # $3: Cells 
    2147           (?: 
     2027          (?> 
    21482028            [ ]*        # Allowed whitespace. 
    21492029            [|] .* \n     # Row content. 
     
    21722052         
    21732053        (             # $3: Cells 
    2174           (?: 
     2054          (?> 
    21752055            .* [|] .* \n    # Row content 
    21762056          )* 
     
    22112091    } 
    22122092     
    2213     # Creating code spans before splitting the row is an easy way to  
    2214     # handle a code span containg pipes
    2215     $head = $this->doCodeSpans($head); 
     2093    # Parsing span elements, including code spans, character escapes,  
     2094    # and inline HTML tags, so that pipes inside those gets ignored
     2095    $head = $this->parseSpan($head); 
    22162096    $headers  = preg_split('/ *[|] */', $head); 
    22172097    $col_count  = count($headers); 
     
    22312111    $text .= "<tbody>\n"; 
    22322112    foreach ($rows as $row) { 
    2233       # Creating code spans before splitting the row is an easy way to  
    2234       # handle a code span containg pipes
    2235       $row = $this->doCodeSpans($row); 
     2113      # Parsing span elements, including code spans, character escapes,  
     2114      # and inline HTML tags, so that pipes inside those gets ignored
     2115      $row = $this->parseSpan($row); 
    22362116       
    22372117      # Split row by cell. 
     
    22582138 
    22592139    # Re-usable pattern to match any entire dl list: 
    2260     $whole_list = ' 
     2140    $whole_list = '(?> 
    22612141      (               # $1 = whole list 
    22622142        (               # $2 
     
    22832163        ) 
    22842164      ) 
    2285     '; // mx 
     2165    )'; // mx 
    22862166 
    22872167    $text = preg_replace_callback('{ 
     
    24372317  # 
    24382318    # Strip leading and trailing lines: 
    2439     $text = preg_replace(array('/\A\n+/', '/\n+\z/'), '', $text); 
     2319    $text = preg_replace('/\A\n+|\n+\z/', '', $text); 
    24402320     
    24412321    $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); 
     
    24492329      # Check if this should be enclosed in a paragraph. 
    24502330      # Clean tag hashes & block tag hashes are left alone. 
    2451       $clean_key = $value; 
    2452       $block_key = substr($value, 0, 34); 
    2453        
    2454       $is_p = (!isset($this->html_blocks[$block_key]) &&  
    2455            !isset($this->html_cleans[$clean_key])); 
     2331      $is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value); 
    24562332       
    24572333      if ($is_p) { 
     
    26592535      $desc = $this->abbr_desciptions[$abbr]; 
    26602536      if (empty($desc)) { 
    2661         return $this->hashSpan("<abbr>$abbr</abbr>"); 
     2537        return $this->hashPart("<abbr>$abbr</abbr>"); 
    26622538      } else { 
    2663         $desc = $this->escapeSpecialCharsWithinTagAttributes($desc); 
    2664         return $this->hashSpan("<abbr title=\"$desc\">$abbr</abbr>"); 
     2539        $desc = htmlspecialchars($desc, ENT_NOQUOTES); 
     2540        return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>"); 
    26652541      } 
    26662542    } else { 
     
    27122588 
    27132589Version History 
    2714 --------------- 
    2715  
    2716 See Readme file for details. 
    2717  
    2718 Extra 1.1.3 (3 Jul 2007): 
    2719  
    2720 Extra 1.1.2 (7 Feb 2007) 
    2721  
    2722 Extra 1.1.1 (28 Dec 2006) 
    2723  
    2724 Extra 1.1 (1 Dec 2006) 
    2725  
    2726 Extra 1.0.1 (9 Dec 2005) 
    2727  
    2728 Extra 1.0 (5 Sep 2005) 
     2590---------------  
     2591 
     2592See the readme file for detailed release notes for this version. 
    27292593 
    27302594 
  • plugins/sfMarkdownPlugin/package.xml

    r4712 r6191  
    1111        <active>yes</active> 
    1212    </lead> 
    13     <date>2007-07-22</date> 
    14     <time>20:12:00</time> 
     13    <date>2007-11-27</date> 
     14    <time>23:48:00</time> 
    1515    <version> 
    16         <release>0.1.0</release> 
    17         <api>0.1.0</api> 
     16        <release>0.1.1</release> 
     17        <api>0.1.1</api> 
    1818    </version> 
    1919    <stability>