Make WordPress Core

Changeset 1593


Ignore:
Timestamp:
09/04/2004 08:48:57 PM (22 years ago)
Author:
saxmatt
Message:

Bump to Markdown 1.0

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-content/plugins/markdown.php

    r1104 r1593  
    11<?php
     2
     3#
     4# Markdown  -  A text-to-HTML conversion tool for web writers
     5#
     6# Copyright (c) 2004 John Gruber 
     7# <http://daringfireball.net/projects/markdown/>
     8#
     9# Copyright (c) 2004 Michel Fortin - Translation to PHP 
     10# <http://www.michelf.com/projects/php-markdown/>
     11#
     12
     13# This version has been modified for inclusion in WordPress
     14# For the original please see Michel's site
     15
     16
     17global  $MarkdownPHPVersion, $MarkdownSyntaxVersion,
     18                $md_empty_element_suffix, $md_tab_width,
     19                $md_nested_brackets_depth, $md_nested_brackets,
     20                $md_escape_table, $md_backslash_escape_table;
     21
     22
     23$MarkdownPHPVersion    = '1.0'; # Sat 21 Aug 2004
     24$MarkdownSyntaxVersion = '1.0'; # Fri 20 Aug 2004
     25
     26
     27#
     28# Global default settings:
     29#
     30$md_empty_element_suffix = " />";     # Change to ">" for HTML output
     31$md_tab_width = 4;
     32
     33
     34# -- WordPress Plugin Interface -----------------------------------------------
    235/*
    3 Plugin Name: MarkDown
    4 Plugin URI: http://daringfireball.net/projects/markdown/
    5 Description: Markdown is a text-to-HTML conversion tool for web writers. <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, then convert it to structurally valid XHTML. This plugin <strong>enables Markdown for your posts and comments</strong>. Written by <a href="http://daringfireball.net/">John Gruber</a> in Perl, translated to PHP by <a href="http://www.michelf.com/">Michel Fortin</a>, and made a WP plugin by <a href="http://photomatt.net/">Matt</a>. If you use this you should disable Textile 1 and 2 because the syntax conflicts.
    6 Version: 1.0b4
    7 Author: John Gruber
    8 Author URI: http://daringfireball.net/
    9 */
    10 
    11 
    12 /*
    13 Note to code readers: I've stripped most of the comments from the source, see the original at http://www.michelf.com/php-markdown/?code to get the unaltered version. --Matt
     36Plugin Name: Markdown
     37Plugin URI: http://codex.wordpress.org/Plugin:Markdown
     38Description: <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>
     39Version: 1.0
     40Author: Michel Fortin
     41Author URI: http://www.michelf.com/
    1442*/
    15 
    16 $MarkdownPHPVersion    = '1.0b4.1'; # Sun 4 Apr 2004
    17 $MarkdownSyntaxVersion = '1.0b4'; # Thu 25 Mar 2004
    18 $g_empty_element_suffix = " />";     # Change to ">" for HTML output
    19 $g_tab_width = 4;
    20 $g_nested_brackets_depth = 6;
    21 $g_nested_brackets =
    22         str_repeat('(?>[^\[\]]+|\[', $g_nested_brackets_depth).
    23         str_repeat('\])*', $g_nested_brackets_depth);
    24 $g_escape_table = array(
     43if (isset($wp_version)) {
     44        # Remove default WordPress auto-paragraph filter.
     45        remove_filter('the_content', 'wpautop');
     46        remove_filter('the_excerpt', 'wpautop');
     47        remove_filter('comment_text', 'wpautop');
     48        # Add Markdown filter with priority 6 (same as Textile).
     49        add_filter('the_content', 'Markdown', 6);
     50        add_filter('the_excerpt', 'Markdown', 6);
     51        add_filter('comment_text', 'Markdown', 6);
     52}
     53
     54function smarty_modifier_markdown($text) {
     55        return Markdown($text);
     56}
     57
     58$md_nested_brackets_depth = 6;
     59$md_nested_brackets =
     60        str_repeat('(?>[^\[\]]+|\[', $md_nested_brackets_depth).
     61        str_repeat('\])*', $md_nested_brackets_depth);
     62
     63$md_escape_table = array(
    2564        "\\" => md5("\\"),
    2665        "`" => md5("`"),
     
    3776        "!" => md5("!")
    3877);
    39 $g_backslash_escape_table;
    40 foreach ($g_escape_table as $key => $char)
    41         $g_backslash_escape_table["\\$key"] = $char;
    42 
    43 $g_urls;
    44 $g_titles;
    45 $g_html_blocks;
     78# Create an identical table but for escaped characters.
     79$md_backslash_escape_table;
     80foreach ($md_escape_table as $key => $char)
     81        $md_backslash_escape_table["\\$key"] = $char;
     82
    4683
    4784function Markdown($text) {
    48         global $g_urls, $g_titles, $g_html_blocks;
    49         $g_urls = array();
    50         $g_titles = array();
    51         $g_html_blocks = array();
     85        global $md_urls, $md_titles, $md_html_blocks;
     86        $md_urls = array();
     87        $md_titles = array();
     88        $md_html_blocks = array();
     89
    5290        $text = str_replace(array("\r\n", "\r"), "\n", $text);
     91
    5392        $text .= "\n\n";
     93
    5494        $text = _Detab($text);
     95
    5596        $text = preg_replace('/^[ \t]+$/m', '', $text);
     97
    5698        $text = _HashHTMLBlocks($text);
     99
    57100        $text = _StripLinkDefinitions($text);
     101
    58102        $text = _EscapeSpecialChars($text);
     103
    59104        $text = _RunBlockGamut($text);
     105
    60106        $text = _UnescapeSpecialChars($text);
     107
    61108        return $text . "\n";
    62109}
     110
    63111
    64112function _StripLinkDefinitions($text) {
     
    68116                                                  \n?                           # maybe *one* newline
    69117                                                  [ \t]*
    70                                                 (\S+)                           # url = $2
     118                                                <?(\S+?)>?                      # url = $2
    71119                                                  [ \t]*
    72120                                                  \n?                           # maybe one newline
     
    86134}
    87135function _StripLinkDefinitions_callback($matches) {
    88         global $g_urls, $g_titles;
     136        global $md_urls, $md_titles;
    89137        $link_id = strtolower($matches[1]);
    90         $g_urls[$link_id] = _EncodeAmpsAndAngles($matches[2]);
     138        $md_urls[$link_id] = _EncodeAmpsAndAngles($matches[2]);
    91139        if (isset($matches[3]))
    92                 $g_titles[$link_id] = htmlentities($matches[3]);
     140                $md_titles[$link_id] = htmlentities($matches[3]);
    93141        return ''; # String that will replace the block
    94142}
    95143
     144
    96145function _HashHTMLBlocks($text) {
    97         $block_tag_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script';
     146        $block_tags_a = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|'.
     147                                        'script|noscript|form|fieldset|iframe|math|ins|del';
     148        $block_tags_b = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|'.
     149                                        'script|noscript|form|fieldset|iframe|math';
     150
    98151        $text = preg_replace_callback("{
    99152                                (                                               # save in $1
    100153                                        ^                                       # start of line  (with /m)
    101                                         <($block_tag_re)        # start tag = $2
     154                                        <($block_tags_a)        # start tag = $2
    102155                                        \\b                                     # word break
    103156                                        (.*\\n)*?                       # any number of lines, minimally matching
     
    113166                                (                                               # save in $1
    114167                                        ^                                       # start of line  (with /m)
    115                                         <($block_tag_re)        # start tag = $2
     168                                        <($block_tags_b)        # start tag = $2
    116169                                        \\b                                     # word break
    117170                                        (.*\\n)*?                       # any number of lines, minimally matching
     
    145198}
    146199function _HashHTMLBlocks_callback($matches) {
    147         global $g_html_blocks;
     200        global $md_html_blocks;
    148201        $text = $matches[1];
    149202        $key = md5($text);
    150         $g_html_blocks[$key] = $text;
     203        $md_html_blocks[$key] = $text;
    151204        return "\n\n$key\n\n"; # String that will replace the block
    152205}
    153206
     207
    154208function _RunBlockGamut($text) {
    155         global $g_empty_element_suffix;
    156        
     209        global $md_empty_element_suffix;
     210
    157211        $text = _DoHeaders($text);
    158212
     213        # Do Horizontal Rules:
    159214        $text = preg_replace(
    160215                array('/^( ?\* ?){3,}$/m',
    161                           '/^( ?- ?){3,}$/m'),
    162                 array("\n<hr$g_empty_element_suffix\n",
    163                           "\n<hr$g_empty_element_suffix\n"),
     216                          '/^( ?- ?){3,}$/m',
     217                          '/^( ?_ ?){3,}$/m'),
     218                "\n<hr$md_empty_element_suffix\n",
    164219                $text);
    165220
     
    170225        $text = _DoBlockQuotes($text);
    171226
     227        # Make links out of things like `<http://example.com/>`
    172228        $text = _DoAutoLinks($text);
    173229
     
    181237
    182238function _RunSpanGamut($text) {
    183         global $g_empty_element_suffix;
     239        global $md_empty_element_suffix;
    184240        $text = _DoCodeSpans($text);
    185241
    186 
     242        # Fix unencoded ampersands and <'s:
    187243        $text = _EncodeAmpsAndAngles($text);
    188244
     245        # Process anchor and image tags. Images must come first,
     246        # because ![foo][f] looks like an anchor.
    189247        $text = _DoImages($text);
    190248        $text = _DoAnchors($text);
     
    192250
    193251        $text = _DoItalicsAndBold($text);
    194        
    195         # Do hard breaks:
    196         $text = preg_replace('/ {2,}\n/', "<br$g_empty_element_suffix\n", $text);
     252
     253        $text = preg_replace('/ {2,}\n/', "<br$md_empty_element_suffix\n", $text);
    197254
    198255        return $text;
     
    201258
    202259function _EscapeSpecialChars($text) {
    203         global $g_escape_table;
     260        global $md_escape_table;
    204261        $tokens = _TokenizeHTML($text);
    205262
    206263        $text = '';   # rebuild $text from the tokens
    207         $in_pre = 0;  # Keep track of when we're inside <pre> or <code> tags.
    208         $tags_to_skip = "!<(/?)(?:pre|code|kbd|script)[\s>]!";
    209 
    210264        foreach ($tokens as $cur_token) {
    211265                if ($cur_token[0] == 'tag') {
    212266                        $cur_token[1] = str_replace(array('*', '_'),
    213                                 array($g_escape_table['*'], $g_escape_table['_']),
     267                                array($md_escape_table['*'], $md_escape_table['_']),
    214268                                $cur_token[1]);
    215269                        $text .= $cur_token[1];
    216270                } else {
    217271                        $t = $cur_token[1];
    218                         if (! $in_pre) {
    219                                 $t = _EncodeBackslashEscapes($t);
    220                                 # $t =~ s{([a-z])/([a-z])}{$1&thinsp;/&thinsp;$2}ig;
    221                         }
     272                        $t = _EncodeBackslashEscapes($t);
    222273                        $text .= $t;
    223274                }
     
    228279
    229280function _DoAnchors($text) {
    230         global $g_nested_brackets;
    231 
     281        global $md_nested_brackets;
     282        #
     283        # First, handle reference-style links: [link text] [id]
     284        #
    232285        $text = preg_replace_callback("{
    233286                (                                       # wrap whole match in $1
    234287                  \\[
    235                     ($g_nested_brackets)        # link text = $2
     288                        ($md_nested_brackets)   # link text = $2
    236289                  \\]
    237290
     
    240293
    241294                  \\[
    242                     (.*?)               # id = $3
     295                        (.*?)           # id = $3
    243296                  \\]
    244297                )
    245298                }xs",
    246299                '_DoAnchors_reference_callback', $text);
    247        
     300
    248301        $text = preg_replace_callback("{
    249302                (                               # wrap whole match in $1
    250303                  \\[
    251                         ($g_nested_brackets)    # link text = $2
     304                        ($md_nested_brackets)   # link text = $2
    252305                  \\]
    253306                  \\(                   # literal paren
    254307                        [ \\t]*
    255                         (.+?)           # href = $3
     308                        <?(.+?)>?       # href = $3
    256309                        [ \\t]*
    257                         (                       # title = $4
     310                        (                       # $4
    258311                          (['\"])       # quote char = $5
    259                           .*?
     312                          (.*?)         # Title = $6
    260313                          \\5           # matching quote
    261314                        )?                      # title is optional
     
    264317                }xs",
    265318                '_DoAnchors_inline_callback', $text);
    266        
     319
    267320        return $text;
    268321}
    269322function _DoAnchors_reference_callback($matches) {
    270         global $g_urls, $g_titles;
    271         $result;
     323        global $md_urls, $md_titles, $md_escape_table;
    272324        $whole_match = $matches[1];
    273325        $link_text   = $matches[2];
     
    278330        }
    279331
    280         if (isset($g_urls[$link_id])) {
    281                 $url = $g_urls[$link_id];
    282                 $url = str_replace(array('*',     '_'),
    283                                                    array('&#42;', '&#95;'), $url);
    284                 $result = "<a href='$url'";
    285                 if ( isset( $g_title[$link_id] ) ) {
    286                         $title = $g_titles[$link_id];
     332        if (isset($md_urls[$link_id])) {
     333                $url = $md_urls[$link_id];
     334                # We've got to encode these to avoid conflicting with italics/bold.
     335                $url = str_replace(array('*', '_'),
     336                                                   array($md_escape_table['*'], $md_escape_table['_']),
     337                                                   $url);
     338                $result = "<a href=\"$url\"";
     339                if ( isset( $md_titles[$link_id] ) ) {
     340                        $title = $md_titles[$link_id];
    287341                        $title = str_replace(array('*',     '_'),
    288                                                                  array('&#42;', '&#95;'), $title);
     342                                                                 array($md_escape_table['*'],
     343                                                                           $md_escape_table['_']), $title);
    289344                        $result .=  " title=\"$title\"";
    290345                }
     
    297352}
    298353function _DoAnchors_inline_callback($matches) {
    299         $result;
     354        global $md_escape_table;
    300355        $whole_match = $matches[1];
    301356        $link_text   = $matches[2];
    302357        $url                    = $matches[3];
    303         $title          = $matches[4];
     358        $title          = $matches[6];
    304359
    305360        # We've got to encode these to avoid conflicting with italics/bold.
    306         $url = str_replace(array('*',     '_'),
    307                                            array('&#42;', '&#95;'), $url);
     361        $url = str_replace(array('*', '_'),
     362                                           array($md_escape_table['*'], $md_escape_table['_']),
     363                                           $url);
    308364        $result = "<a href=\"$url\"";
    309         if ($title) {
    310                 $title = str_replace(array('*',     '_'),
    311                                                          array('&#42;', '&#95;'), $title);
    312                 $result .=  " title=$title";
    313         }
     365        if (isset($title)) {
     366                $title = str_replace('"', '&quot', $title);
     367                $title = str_replace(array('*', '_'),
     368                                                         array($md_escape_table['*'], $md_escape_table['_']),
     369                                                         $title);
     370                $result .=  " title=\"$title\"";
     371        }
     372       
    314373        $result .= ">$link_text</a>";
    315374
     
    322381                (                               # wrap whole match in $1
    323382                  !\[
    324                     (.*?)               # alt text = $2
     383                        (.*?)           # alt text = $2
    325384                  \]
    326385
     
    329388
    330389                  \[
    331                     (.*?)               # id = $3
     390                        (.*?)           # id = $3
    332391                  \]
    333392
     
    347406                  \\(                   # literal paren
    348407                        [ \\t]*
    349                         (\\S+)          # src url = $3
     408                        <?(\S+?)>?      # src url = $3
    350409                        [ \\t]*
    351                         (                       # title = $4
     410                        (                       # $4
    352411                          (['\"])       # quote char = $5
    353                           .*?
     412                          (.*?)         # title = $6
    354413                          \\5           # matching quote
    355414                          [ \\t]*
     
    363422}
    364423function _DoImages_reference_callback($matches) {
    365         global $g_urls, $g_titles, $g_empty_element_suffix;
    366         $result;
     424        global $md_urls, $md_titles, $md_empty_element_suffix, $md_escape_table;
    367425        $whole_match = $matches[1];
    368426        $alt_text    = $matches[2];
     
    372430                $link_id = strtolower($alt_text); # for shortcut links like ![this][].
    373431        }
    374        
    375         if (isset($g_urls[$link_id])) {
    376                 $url = $g_urls[$link_id];
    377                 $url = str_replace(array('*',     '_'),
    378                                                    array('&#42;', '&#95;'), $url);
     432
     433        $alt_text = str_replace('"', '&quot;', $alt_text);
     434        if (isset($md_urls[$link_id])) {
     435                $url = $md_urls[$link_id];
     436                # We've got to encode these to avoid conflicting with italics/bold.
     437                $url = str_replace(array('*', '_'),
     438                                                   array($md_escape_table['*'], $md_escape_table['_']),
     439                                                   $url);
    379440                $result = "<img src=\"$url\" alt=\"$alt_text\"";
    380                 if (isset($g_titles[$link_id])) {
    381                         $title = $g_titles[$link_id];
    382                         $title = str_replace(array('*',     '_'),
    383                                                                  array('&#42;', '&#95;'), $title);
     441                if (isset($md_titles[$link_id])) {
     442                        $title = $md_titles[$link_id];
     443                        $title = str_replace(array('*', '_'),
     444                                                                 array($md_escape_table['*'],
     445                                                                           $md_escape_table['_']), $title);
    384446                        $result .=  " title=\"$title\"";
    385447                }
    386                 $result .= $g_empty_element_suffix;
     448                $result .= $md_empty_element_suffix;
    387449        }
    388450        else {
     451                # If there's no such link ID, leave intact:
    389452                $result = $whole_match;
    390453        }
     
    393456}
    394457function _DoImages_inline_callback($matches) {
    395         global $g_empty_element_suffix;
    396         $result;
     458        global $md_empty_element_suffix, $md_escape_table;
    397459        $whole_match = $matches[1];
    398460        $alt_text    = $matches[2];
    399461        $url                    = $matches[3];
    400         $title          = $matches[4];
    401 
    402         $url = str_replace(array('*',     '_'),
    403                                            array('&#42;', '&#95;'), $url);
     462        $title          = '';
     463        if (isset($matches[6])) {
     464                $title = $matches[6];
     465        }
     466
     467        $alt_text = str_replace('"', '&quot;', $alt_text);
     468        $title    = str_replace('"', '&quot;', $title);
     469        # We've got to encode these to avoid conflicting with italics/bold.
     470        $url = str_replace(array('*', '_'),
     471                                           array($md_escape_table['*'], $md_escape_table['_']),
     472                                           $url);
    404473        $result = "<img src=\"$url\" alt=\"$alt_text\"";
    405474        if (isset($title)) {
    406                 $title = str_replace(array('*',     '_'),
    407                                                          array('&#42;', '&#95;'), $title);
    408                 $result .=  " title=$title"; # $title already quoted
    409         }
    410         $result .= $g_empty_element_suffix;
     475                $title = str_replace(array('*', '_'),
     476                                                         array($md_escape_table['*'], $md_escape_table['_']),
     477                                                         $title);
     478                $result .=  " title=\"$title\""; # $title already quoted
     479        }
     480        $result .= $md_empty_element_suffix;
    411481
    412482        return $result;
     
    438508
    439509function _DoLists($text) {
    440         global $g_tab_width;
    441         $less_than_tab = $g_tab_width - 1;
     510#
     511# Form HTML ordered (numbered) and unordered (bulleted) lists.
     512#
     513        global $md_tab_width;
     514        $less_than_tab = $md_tab_width - 1;
     515
     516        # Re-usable patterns to match list item bullets and number markers:
     517        $marker_ul  = '[*+-]';
     518        $marker_ol  = '\d+[.]';
     519        $marker_any = "(?:$marker_ul|$marker_ol)";
    442520
    443521        $text = preg_replace_callback("{
    444                         (
    445                           (
    446                             ^[ ]{0,$less_than_tab}
    447                             (\\*|\\d+[.])
    448                             [ \\t]+
     522                        (                                                               # $1
     523                          (                                                             # $2
     524                                ^[ ]{0,$less_than_tab}
     525                            ($marker_any)                               # $3 - first list item marker
     526                                [ \\t]+
    449527                          )
    450528                          (?s:.+?)
    451                           (
    452                               \\z
    453                             |
     529                          (                                                             # $4
     530                                  \\z
     531                                |
    454532                                  \\n{2,}
    455533                                  (?=\\S)
    456                                   (?![ \\t]* (\\*|\\d+[.]) [ \\t]+)
     534                                  (?!                                           # Negative lookahead for another list item marker
     535                                        [ \\t]*
     536                                        {$marker_any}[ \\t]+
     537                                  )
    457538                          )
    458539                        )
     
    463544}
    464545function _DoLists_callback($matches) {
    465         $list_type = ($matches[3] == "*") ? "ul" : "ol";
     546        # Re-usable patterns to match list item bullets and number markers:
     547        $marker_ul  = '[*+-]';
     548        $marker_ol  = '\d+[.]';
     549        $marker_any = "(?:$marker_ul|$marker_ol)";
     550       
    466551        $list = $matches[1];
     552        $list_type = preg_match('/[*+-]/', $matches[3]) ? "ul" : "ol";
     553        # Turn double returns into triple returns, so that we can make a
     554        # paragraph for the last item in a list, if necessary:
    467555        $list = preg_replace("/\n{2,}/", "\n\n\n", $list);
    468         $result = _ProcessListItems($list);
    469         $result = "<$list_type>\n" . $result . "</$list_type>\n";
     556        $result = _ProcessListItems($list, $marker_any);
     557        $result = "<$list_type>\n" . $result . "</$list_type>\n\n";
    470558        return $result;
    471559}
    472560
    473561
    474 function _ProcessListItems($list_str) {
     562function _ProcessListItems($list_str, $marker_any) {
    475563        # trim trailing blank lines:
    476564        $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
     
    479567                (\n)?                                                   # leading line = $1
    480568                (^[ \t]*)                                               # leading whitespace = $2
    481                 (\*|\d+[.]) [ \t]+                              # list marker = $3
     569                ('.$marker_any.') [ \t]+                # list marker = $3
    482570                ((?s:.+?)                                               # list item text   = $4
    483571                (\n{1,2}))
    484                 (?= \n* (\z | \2 (\*|\d+[.]) [ \t]+))
     572                (?= \n* (\z | \2 ('.$marker_any.') [ \t]+))
    485573                }xm',
    486574                '_ProcessListItems_callback', $list_str);
     
    509597
    510598function _DoCodeBlocks($text) {
    511         global $g_tab_width;
     599        global $md_tab_width;
    512600        $text = preg_replace_callback("{
    513                         (.?)                    # $1 = preceding character
    514                         (:)                             # $2 = colon delimiter
    515                         (\\n+)                  # $3 = newlines after colon
    516                         (                   # $4 = the code block -- one or more lines, starting with a space/tab
     601                        (?:\\n\\n|\\A)
     602                        (                   # $1 = the code block -- one or more lines, starting with a space/tab
    517603                          (?:
    518                             (?:[ ]\{$g_tab_width} | \\t)  # Lines must start with a tab or a tab-width of spaces
    519                             .*\\n+
     604                                (?:[ ]\{$md_tab_width} | \\t)  # Lines must start with a tab or a tab-width of spaces
     605                                .*\\n+
    520606                          )+
    521607                        )
    522                         ((?=^[ ]{0,$g_tab_width}\\S)|\\Z)       # Lookahead for non-space at line-start, or end of doc
     608                        ((?=^[ ]{0,$md_tab_width}\\S)|\\Z)      # Lookahead for non-space at line-start, or end of doc
    523609                }xm",
    524610                '_DoCodeBlocks_callback', $text);
     
    527613}
    528614function _DoCodeBlocks_callback($matches) {
    529         $prevchar  = $matches[1];
    530         $newlines  = $matches[2];
    531         $codeblock = $matches[4];
    532 
    533         $result; # return value
    534        
    535 
    536         $prefix = "";
    537         if (!(preg_match('/\s/', $prevchar) || ($prevchar == ""))) {
    538                         $prefix = "$prevchar:";
    539         }
     615        $codeblock = $matches[1];
     616
    540617        $codeblock = _EncodeCode(_Outdent($codeblock));
    541618        $codeblock = _Detab($codeblock);
    542619        # trim leading newlines and trailing whitespace
    543620        $codeblock = preg_replace(array('/\A\n+/', '/\s+\z/'), '', $codeblock);
    544        
    545         $result = $prefix . "\n\n<pre><code>" . $codeblock . "\n</code></pre>\n\n";
     621
     622        $result = "\n\n<pre><code>" . $codeblock . "\n</code></pre>\n\n";
    546623
    547624        return $result;
     
    551628function _DoCodeSpans($text) {
    552629        $text = preg_replace_callback("@
    553                         (`+)            # Opening run of `
    554                         (.+?)           # the code block
     630                        (`+)            # $1 = Opening run of `
     631                        (.+?)           # $2 = The code block
    555632                        (?<!`)
    556633                        \\1
     
    571648
    572649function _EncodeCode($_) {
    573 
    574         global $g_escape_table;
    575 
    576         # Encode all ampersands; HTML entities are not
    577         # entities within a Markdown code span.
     650        global $md_escape_table;
     651
    578652        $_ = str_replace('&', '&amp;', $_);
    579653
    580         # Do the angle bracket song and dance:
    581654        $_ = str_replace(array('<',    '>'),
    582655                                         array('&lt;', '&gt;'), $_);
    583656
    584         # Now, escape characters that are magic in Markdown:
    585         $_ = str_replace(array_keys($g_escape_table),
    586                                          array_values($g_escape_table), $_);
     657        $_ = str_replace(array_keys($md_escape_table),
     658                                         array_values($md_escape_table), $_);
    587659
    588660        return $_;
     
    619691function _DoBlockQuotes_callback($matches) {
    620692        $bq = $matches[1];
    621         $bq = preg_replace('/^[ \t]*>[ \t]?/m', '', $bq);
     693        # trim one level of quoting - trim whitespace-only lines
     694        $bq = preg_replace(array('/^[ \t]*>[ \t]?/m', '/^[ \t]+$/m'), '', $bq);
    622695        $bq = _RunBlockGamut($bq);              # recurse
    623         $bq = preg_replace('/^/m', "\t", $bq);
    624        
     696
     697        $bq = preg_replace('/^/m', "  ", $bq);
     698        # These leading spaces screw with <pre> content, so we need to fix that:
     699        $bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx',
     700                                                                '_DoBlockQuotes_callback2', $bq);
     701
    625702        return "<blockquote>\n$bq\n</blockquote>\n\n";
    626703}
     704function _DoBlockQuotes_callback2($matches) {
     705        $pre = $matches[1];
     706        $pre = preg_replace('/^  /m', '', $pre);
     707        return $pre;
     708}
    627709
    628710
    629711function _FormParagraphs($text) {
    630         global $g_html_blocks;
     712        global $md_html_blocks;
    631713
    632714        # Strip leading and trailing lines:
    633715        $text = preg_replace(array('/\A\n+/', '/\n+\z/'), '', $text);
    634716
    635         $grafs = preg_split('/\n{2,}/', $text);
    636         $count = count($graph);
    637 
     717        $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
     718        $count = count($grafs);
    638719
    639720        foreach ($grafs as $key => $value) {
    640                 if (!isset( $g_html_blocks[$value] )) {
     721                if (!isset( $md_html_blocks[$value] )) {
    641722                        $value = _RunSpanGamut($value);
    642723                        $value = preg_replace('/^([ \t]*)/', '<p>', $value);
     
    646727        }
    647728
    648 
    649729        foreach ($grafs as $key => $value) {
    650                 if (isset( $g_html_blocks[$value] )) {
    651                         $grafs[$key] = $g_html_blocks[$value];
     730                if (isset( $md_html_blocks[$value] )) {
     731                        $grafs[$key] = $md_html_blocks[$value];
    652732                }
    653733        }
     
    658738
    659739function _EncodeAmpsAndAngles($text) {
    660         $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w{1,8});)/',
     740        $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/',
    661741                                                 '&amp;', $text);;
    662742
     
    669749
    670750function _EncodeBackslashEscapes($text) {
    671         global $g_escape_table, $g_backslash_escape_table;
     751        global $md_escape_table, $md_backslash_escape_table;
    672752        # Must process escaped backslashes first.
    673         return str_replace(array_keys($g_backslash_escape_table),
    674                                            array_values($g_backslash_escape_table), $text);
     753        return str_replace(array_keys($md_backslash_escape_table),
     754                                           array_values($md_backslash_escape_table), $text);
    675755}
    676756
     
    679759        $text = preg_replace("!<((https?|ftp):[^'\">\\s]+)>!",
    680760                                                 '<a href="\1">\1</a>', $text);
    681        
     761
    682762        # Email addresses: <address@domain.foo>
    683763        $text = preg_replace('{
     
    692772                "_EncodeEmailAddress(_UnescapeSpecialChars(_UnslashQuotes('\\1')))",
    693773                $text);
    694        
     774
    695775        return $text;
    696776}
     
    701781        $length = strlen($addr);
    702782
     783        # leave ':' alone (to spot mailto: later)
    703784        $addr = preg_replace_callback('/([^\:])/',
    704785                                                                  '_EncodeEmailAddress_callback', $addr);
    705786
    706787        $addr = "<a href=\"$addr\">$addr</a>";
     788        # strip the mailto: from the visible part
    707789        $addr = preg_replace('/">.+?:/', '">', $addr);
    708790
     
    712794        $char = $matches[1];
    713795        $r = rand(0, 100);
     796        # roughly 10% raw, 45% hex, 45% dec
     797        # '@' *must* be encoded. I insist.
    714798        if ($r > 90 && $char != '@') return $char;
    715799        if ($r < 45) return '&#x'.dechex(ord($char)).';';
     
    719803
    720804function _UnescapeSpecialChars($text) {
    721         global $g_escape_table;
    722         return str_replace(array_values($g_escape_table),
    723                                            array_keys($g_escape_table), $text);
    724 }
    725 
    726 
    727 function _TokenizeHTML($str) {
    728         $pos = 0;
    729         $len = strlen($str);
    730         $tokens = array();
    731 
    732         $depth = 6;
    733         $nested_tags = str_repeat('(?:<[a-z\/!$](?:[^<>]|',$depth)
    734                                    .str_repeat(')*>)', $depth);
    735         $match = "(?s:<!(--.*?--\s*)+>)|".  # comment
    736                          "(?s:<\?.*?\?>)|".         # processing instruction
    737                          "$nested_tags";            # nested tags
    738        
    739         preg_match_all("/($match)/", $str, $matches,
    740                                    PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
    741 
    742         foreach ($matches as $element) {
    743                 $whole_tag = $element[0][0];
    744                 $tag_start = $element[0][1];
    745                 $sec_start = $tag_start + strlen($whole_tag);
    746                 if ($pos < $tag_start) {
    747                         array_push($tokens, array('text',
    748                                            substr($str, $pos, $tag_start - $pos)));
     805        global $md_escape_table;
     806        return str_replace(array_values($md_escape_table),
     807                                           array_keys($md_escape_table), $text);
     808}
     809
     810
     811if (!function_exists('_TokenizeHTML')) {
     812        function _TokenizeHTML($str) {
     813                $index = 0;
     814                $tokens = array();
     815
     816                $depth = 6;
     817                $nested_tags = str_repeat('(?:<[a-z\/!$](?:[^<>]|',$depth)
     818                                           .str_repeat(')*>)', $depth);
     819                $match = "(?s:<!(?:--.*?--\s*)+>)|".  # comment
     820                                 "(?s:<\?.*?\?>)|".         # processing instruction
     821                                 "$nested_tags";            # nested tags
     822
     823                $parts = preg_split("/($match)/", $str, -1, PREG_SPLIT_DELIM_CAPTURE);
     824
     825                foreach ($parts as $part) {
     826                        if (++$index % 2 && $part != '')
     827                                array_push($tokens, array('text', $part));
     828                        else
     829                                array_push($tokens, array('tag', $part));
    749830                }
    750                 array_push($tokens, array('tag', $whole_tag));
    751                 $pos = $sec_start;
    752         }
    753        
    754         if ($pos < $len)
    755                 array_push($tokens, array('text',
    756                                    substr($str, $pos, $len - $pos)));
    757         return $tokens;
     831
     832                return $tokens;
     833        }
    758834}
    759835
    760836
    761837function _Outdent($text) {
    762         global $g_tab_width;
    763         return preg_replace("/^(\\t|[ ]{1,$g_tab_width})/m", "", $text);
     838        global $md_tab_width;
     839        return preg_replace("/^(\\t|[ ]{1,$md_tab_width})/m", "", $text);
    764840}
    765841
    766842
    767843function _Detab($text) {
    768         global $g_tab_width;
     844        global $md_tab_width;
    769845        $text = preg_replace(
    770846                "/(.*?)\t/e",
    771                 "'\\1'.str_repeat(' ', $g_tab_width - strlen('\\1') % $g_tab_width)",
     847                "'\\1'.str_repeat(' ', $md_tab_width - strlen('\\1') % $md_tab_width)",
    772848                $text);
    773849        return $text;
     
    779855}
    780856
    781 // And now for the filters
    782 remove_filter('the_content', 'wpautop');
    783 remove_filter('the_excerpt', 'wpautop');
    784 remove_filter('comment_text', 'wpautop');
    785 
    786 add_filter('the_content', 'Markdown');
    787 add_filter('the_excerpt', 'Markdown');
    788 remove_filter('comment_text', 'Markdown');
    789 
    790857?>
Note: See TracChangeset for help on using the changeset viewer.