Changeset 2128
- Timestamp:
- 01/24/05 06:30:16 (4 years ago)
- Files:
-
- trunk/wp-content/plugins/markdown.php (modified) (52 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/wp-content/plugins/markdown.php
r1593 r2128 7 7 # <http://daringfireball.net/projects/markdown/> 8 8 # 9 # Copyright (c) 2004 Michel Fortin - Translation to PHP9 # Copyright (c) 2004 Michel Fortin - PHP Port 10 10 # <http://www.michelf.com/projects/php-markdown/> 11 11 # 12 13 # This version has been modified for inclusion in WordPress14 # For the original please see Michel's site15 12 16 13 … … 18 15 $md_empty_element_suffix, $md_tab_width, 19 16 $md_nested_brackets_depth, $md_nested_brackets, 20 $md_escape_table, $md_backslash_escape_table ;21 22 23 $MarkdownPHPVersion = '1.0 '; # Sat 21 Aug200424 $MarkdownSyntaxVersion = '1.0 '; # Fri 20 Aug200417 $md_escape_table, $md_backslash_escape_table, 18 $md_list_level; 19 20 $MarkdownPHPVersion = '1.0.1'; # Fri 17 Dec 2004 21 $MarkdownSyntaxVersion = '1.0.1'; # Sun 12 Dec 2004 25 22 26 23 … … 35 32 /* 36 33 Plugin Name: Markdown 37 Plugin URI: http:// codex.wordpress.org/Plugin:Markdown34 Plugin URI: http://www.michelf.com/projects/php-markdown/ 38 35 Description: <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> 39 Version: 1.0 36 Version: 1.0.1 40 37 Author: Michel Fortin 41 38 Author URI: http://www.michelf.com/ … … 52 49 } 53 50 51 52 # -- bBlog Plugin Info -------------------------------------------------------- 53 function identify_modifier_markdown() { 54 global $MarkdownPHPVersion; 55 return array( 56 'name' => 'markdown', 57 'type' => 'modifier', 58 'nicename' => 'Markdown', 59 'description' => 'A text-to-HTML conversion tool for web writers', 60 'authors' => 'Michel Fortin and John Gruber', 61 'licence' => 'GPL', 62 'version' => $MarkdownPHPVersion, 63 'help' => '<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>' 64 ); 65 } 66 67 # -- Smarty Modifier Interface ------------------------------------------------ 54 68 function smarty_modifier_markdown($text) { 55 69 return Markdown($text); 56 70 } 57 71 72 # -- Textile Compatibility Mode ----------------------------------------------- 73 # Rename this file to "classTextile.php" and it can replace Textile anywhere. 74 if (strcasecmp(substr(__FILE__, -16), "classTextile.php") == 0) { 75 # Try to include PHP SmartyPants. Should be in the same directory. 76 @include_once 'smartypants.php'; 77 # Fake Textile class. It calls Markdown instead. 78 class Textile { 79 function TextileThis($text, $lite='', $encode='', $noimage='', $strict='') { 80 if ($lite == '' && $encode == '') $text = Markdown($text); 81 if (function_exists('SmartyPants')) $text = SmartyPants($text); 82 return $text; 83 } 84 } 85 } 86 87 88 89 # 90 # Globals: 91 # 92 93 # Regex to match balanced [brackets]. 94 # Needed to insert a maximum bracked depth while converting to PHP. 58 95 $md_nested_brackets_depth = 6; 59 96 $md_nested_brackets = … … 61 98 str_repeat('\])*', $md_nested_brackets_depth); 62 99 100 # Table of hash values for escaped characters: 63 101 $md_escape_table = array( 64 102 "\\" => md5("\\"), … … 72 110 "(" => md5("("), 73 111 ")" => md5(")"), 112 ">" => md5(">"), 74 113 "#" => md5("#"), 114 "+" => md5("+"), 115 "-" => md5("-"), 75 116 "." => md5("."), 76 117 "!" => md5("!") … … 83 124 84 125 function Markdown($text) { 126 # 127 # Main function. The order in which other subs are called here is 128 # essential. Link and image substitutions need to happen before 129 # _EscapeSpecialChars(), so that any *'s or _'s in the <a> 130 # and <img> tags get encoded. 131 # 132 # Clear the global hashes. If we don't clear these, you get conflicts 133 # from other articles when generating a page which contains more than 134 # one article (e.g. an index page that shows the N most recent 135 # articles): 85 136 global $md_urls, $md_titles, $md_html_blocks; 86 137 $md_urls = array(); … … 88 139 $md_html_blocks = array(); 89 140 141 # Standardize line endings: 142 # DOS to Unix and Mac to Unix 90 143 $text = str_replace(array("\r\n", "\r"), "\n", $text); 91 144 145 # Make sure $text ends with a couple of newlines: 92 146 $text .= "\n\n"; 93 147 148 # Convert all tabs to spaces. 94 149 $text = _Detab($text); 95 150 151 # Strip any lines consisting only of spaces and tabs. 152 # This makes subsequent regexen easier to write, because we can 153 # match consecutive blank lines with /\n+/ instead of something 154 # contorted like /[ \t]*\n+/ . 96 155 $text = preg_replace('/^[ \t]+$/m', '', $text); 97 156 157 # Turn block-level HTML blocks into hash entries 98 158 $text = _HashHTMLBlocks($text); 99 159 160 # Strip link definitions, store in hashes. 100 161 $text = _StripLinkDefinitions($text); 101 162 102 $text = _EscapeSpecialChars($text);103 104 163 $text = _RunBlockGamut($text); 105 164 … … 111 170 112 171 function _StripLinkDefinitions($text) { 172 # 173 # Strips link definitions from text, stores the URLs and titles in 174 # hash references. 175 # 176 global $md_tab_width; 177 $less_than_tab = $md_tab_width - 1; 178 179 # Link defs are in the form: ^[id]: url "optional title" 113 180 $text = preg_replace_callback('{ 114 ^[ \t]*\[(.+)\]: # id = $1181 ^[ ]{0,'.$less_than_tab.'}\[(.+)\]: # id = $1 115 182 [ \t]* 116 183 \n? # maybe *one* newline … … 121 188 [ \t]* 122 189 (?: 123 # Todo: Titles are delimited by "quotes" or (parens).190 (?<=\s) # lookbehind for whitespace 124 191 ["(] 125 192 (.+?) # title = $3 … … 138 205 $md_urls[$link_id] = _EncodeAmpsAndAngles($matches[2]); 139 206 if (isset($matches[3])) 140 $md_titles[$link_id] = htmlentities($matches[3]);207 $md_titles[$link_id] = str_replace('"', '"', $matches[3]); 141 208 return ''; # String that will replace the block 142 209 } … … 144 211 145 212 function _HashHTMLBlocks($text) { 213 global $md_tab_width; 214 $less_than_tab = $md_tab_width - 1; 215 216 # Hashify HTML blocks: 217 # We only want to do this for block-level HTML tags, such as headers, 218 # lists, and tables. That's because we still want to wrap <p>s around 219 # "paragraphs" that are wrapped in non-block-level tags, such as anchors, 220 # phrase emphasis, and spans. The list of tags we're looking for is 221 # hard-coded: 146 222 $block_tags_a = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|'. 147 223 'script|noscript|form|fieldset|iframe|math|ins|del'; … … 149 225 'script|noscript|form|fieldset|iframe|math'; 150 226 227 # First, look for nested blocks, e.g.: 228 # <div> 229 # <div> 230 # tags for inner block must be indented. 231 # </div> 232 # </div> 233 # 234 # The outermost tags must start at the left margin for this to match, and 235 # the inner nested divs must be indented. 236 # We need to do this before the next, more liberal match, because the next 237 # match will start at the first `<div>` and stop at the first `</div>`. 151 238 $text = preg_replace_callback("{ 152 239 ( # save in $1 … … 163 250 $text); 164 251 252 # 253 # Now match more liberally, simply from `\n<tag>` to `</tag>\n` 254 # 165 255 $text = preg_replace_callback("{ 166 256 ( # save in $1 … … 177 267 $text); 178 268 269 # Special case just for <hr />. It was easier to make a special case than 270 # to make the other regex more complicated. 179 271 $text = preg_replace_callback('{ 180 272 (?: … … 184 276 ) 185 277 ( # save in $1 186 [ \t]*278 [ ]{0,'.$less_than_tab.'} 187 279 <(hr) # start tag = $2 188 280 \b # word break 189 281 ([^<>])*? # 190 282 /?> # the matching end tag 283 [ \t]* 191 284 (?=\n{2,}|\Z) # followed by a blank line or end of document 192 285 ) … … 194 287 '_HashHTMLBlocks_callback', 195 288 $text); 289 290 # Special case for standalone HTML comments: 291 $text = preg_replace_callback('{ 292 (?: 293 (?<=\n\n) # Starting after a blank line 294 | # or 295 \A\n? # the beginning of the doc 296 ) 297 ( # save in $1 298 [ ]{0,'.$less_than_tab.'} 299 (?s: 300 <! 301 (--.*?--\s*)+ 302 > 303 ) 304 [ \t]* 305 (?=\n{2,}|\Z) # followed by a blank line or end of document 306 ) 307 }x', 308 '_HashHTMLBlocks_callback', 309 $text); 196 310 197 311 return $text; … … 207 321 208 322 function _RunBlockGamut($text) { 323 # 324 # These are all the transformations that form block-level 325 # tags like paragraphs, headers, and list items. 326 # 209 327 global $md_empty_element_suffix; 210 328 … … 213 331 # Do Horizontal Rules: 214 332 $text = preg_replace( 215 array(' /^( ?\* ?){3,}$/m',216 ' /^( ?- ?){3,}$/m',217 ' /^( ?_ ?){3,}$/m'),333 array('{^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$}mx', 334 '{^[ ]{0,2}([ ]? -[ ]?){3,}[ \t]*$}mx', 335 '{^[ ]{0,2}([ ]? _[ ]?){3,}[ \t]*$}mx'), 218 336 "\n<hr$md_empty_element_suffix\n", 219 337 $text); … … 225 343 $text = _DoBlockQuotes($text); 226 344 227 # Make links out of things like `<http://example.com/>` 228 $text = _DoAutoLinks($text); 229 345 # We already ran _HashHTMLBlocks() before, in Markdown(), but that 346 # was to escape raw HTML in the original Markdown source. This time, 347 # we're escaping the markup we've just created, so that we don't wrap 348 # <p> tags around block-level tags. 230 349 $text = _HashHTMLBlocks($text); 231 350 … … 237 356 238 357 function _RunSpanGamut($text) { 358 # 359 # These are all the transformations that occur *within* block-level 360 # tags like paragraphs, headers, and list items. 361 # 239 362 global $md_empty_element_suffix; 363 240 364 $text = _DoCodeSpans($text); 241 365 242 # Fix unencoded ampersands and <'s: 243 $text = _EncodeAmpsAndAngles($text); 366 $text = _EscapeSpecialChars($text); 244 367 245 368 # Process anchor and image tags. Images must come first, … … 248 371 $text = _DoAnchors($text); 249 372 373 # Make links out of things like `<http://example.com/>` 374 # Must come after _DoAnchors(), because you can use < and > 375 # delimiters in inline links like [this](<url>). 376 $text = _DoAutoLinks($text); 377 378 # Fix unencoded ampersands and <'s: 379 $text = _EncodeAmpsAndAngles($text); 250 380 251 381 $text = _DoItalicsAndBold($text); 252 382 383 # Do hard breaks: 253 384 $text = preg_replace('/ {2,}\n/', "<br$md_empty_element_suffix\n", $text); 254 385 … … 262 393 263 394 $text = ''; # rebuild $text from the tokens 395 # $in_pre = 0; # Keep track of when we're inside <pre> or <code> tags. 396 # $tags_to_skip = "!<(/?)(?:pre|code|kbd|script|math)[\s>]!"; 397 264 398 foreach ($tokens as $cur_token) { 265 399 if ($cur_token[0] == 'tag') { 400 # Within tags, encode * and _ so they don't conflict 401 # with their use in Markdown for italics and strong. 402 # We're replacing each such character with its 403 # corresponding MD5 checksum value; this is likely 404 # overkill, but it should prevent us from colliding 405 # with the escape values by accident. 266 406 $cur_token[1] = str_replace(array('*', '_'), 267 407 array($md_escape_table['*'], $md_escape_table['_']), … … 279 419 280 420 function _DoAnchors($text) { 421 # 422 # Turn Markdown link shortcuts into XHTML <a> tags. 423 # 281 424 global $md_nested_brackets; 282 425 # … … 299 442 '_DoAnchors_reference_callback', $text); 300 443 444 # 445 # Next, inline-style links: [link text](url "optional title") 446 # 301 447 $text = preg_replace_callback("{ 302 448 ( # wrap whole match in $1 … … 306 452 \\( # literal paren 307 453 [ \\t]* 308 <?(. +?)>? # href = $3454 <?(.*?)>? # href = $3 309 455 [ \\t]* 310 456 ( # $4 … … 353 499 function _DoAnchors_inline_callback($matches) { 354 500 global $md_escape_table; 355 $whole_match = $matches[1];356 $link_text = $matches[2];357 $url = $matches[3];358 $title =$matches[6];501 $whole_match = $matches[1]; 502 $link_text = $matches[2]; 503 $url = $matches[3]; 504 $title =& $matches[6]; 359 505 360 506 # We've got to encode these to avoid conflicting with italics/bold. … … 364 510 $result = "<a href=\"$url\""; 365 511 if (isset($title)) { 366 $title = str_replace('"', '" ', $title);512 $title = str_replace('"', '"', $title); 367 513 $title = str_replace(array('*', '_'), 368 514 array($md_escape_table['*'], $md_escape_table['_']), … … 378 524 379 525 function _DoImages($text) { 526 # 527 # Turn Markdown image shortcuts into <img> tags. 528 # 529 # 530 # First, handle reference-style labeled images: ![alt text][id] 531 # 380 532 $text = preg_replace_callback('{ 381 533 ( # wrap whole match in $1 … … 457 609 function _DoImages_inline_callback($matches) { 458 610 global $md_empty_element_suffix, $md_escape_table; 459 $whole_match = $matches[1];460 $alt_text = $matches[2];461 $url = $matches[3];462 $title = '';611 $whole_match = $matches[1]; 612 $alt_text = $matches[2]; 613 $url = $matches[3]; 614 $title = ''; 463 615 if (isset($matches[6])) { 464 $title = $matches[6];616 $title = $matches[6]; 465 617 } 466 618 … … 485 637 486 638 function _DoHeaders($text) { 639 # Setext-style headers: 640 # Header 1 641 # ======== 642 # 643 # Header 2 644 # -------- 645 # 487 646 $text = preg_replace( 488 array( "/(.+)[ \t]*\n=+[ \t]*\n+/e",489 "/(.+)[ \t]*\n-+[ \t]*\n+/e"),647 array('{ ^(.+)[ \t]*\n=+[ \t]*\n+ }emx', 648 '{ ^(.+)[ \t]*\n-+[ \t]*\n+ }emx'), 490 649 array("'<h1>'._RunSpanGamut(_UnslashQuotes('\\1')).'</h1>\n\n'", 491 650 "'<h2>'._RunSpanGamut(_UnslashQuotes('\\1')).'</h2>\n\n'"), 492 651 $text); 493 652 653 # atx-style headers: 654 # # Header 1 655 # ## Header 2 656 # ## Header 2 with closing hashes ## 657 # ... 658 # ###### Header 6 659 # 494 660 $text = preg_replace("{ 495 661 ^(\\#{1,6}) # $1 = string of #'s … … 511 677 # Form HTML ordered (numbered) and unordered (bulleted) lists. 512 678 # 513 global $md_tab_width ;679 global $md_tab_width, $md_list_level; 514 680 $less_than_tab = $md_tab_width - 1; 515 681 … … 519 685 $marker_any = "(?:$marker_ul|$marker_ol)"; 520 686 521 $text = preg_replace_callback("{ 522 ( # $1 523 ( # $2 524 ^[ ]{0,$less_than_tab} 525 ($marker_any) # $3 - first list item marker 526 [ \\t]+ 687 # Re-usable pattern to match any entirel ul or ol list: 688 $whole_list = ' 689 ( # $1 = whole list 690 ( # $2 691 [ ]{0,'.$less_than_tab.'} 692 ('.$marker_any.') # $3 = first list item marker 693 [ \t]+ 694 ) 695 (?s:.+?) 696 ( # $4 697 \z 698 | 699 \n{2,} 700 (?=\S) 701 (?! # Negative lookahead for another list item marker 702 [ \t]* 703 '.$marker_any.'[ \t]+ 527 704 ) 528 (?s:.+?) 529 ( # $4 530 \\z 531 | 532 \\n{2,} 533 (?=\\S) 534 (?! # Negative lookahead for another list item marker 535 [ \\t]* 536 {$marker_any}[ \\t]+ 537 ) 538 ) 539 ) 540 }xm", 541 '_DoLists_callback', $text); 705 ) 706 ) 707 '; // mx 708 709 # We use a different prefix before nested lists than top-level lists. 710 # See extended comment in _ProcessListItems(). 711 712 if ($md_list_level) { 713 $text = preg_replace_callback('{ 714 ^ 715 '.$whole_list.' 716 }mx', 717 '_DoLists_callback', $text); 718 } 719 else { 720 $text = preg_replace_callback('{ 721 (?:(?<=\n\n)|\A\n?) 722 '.$whole_list.' 723 }mx', 724 '_DoLists_callback', $text); 725 } 542 726 543 727 return $text; … … 550 734 551 735 $list = $matches[1]; 552 $list_type = preg_match( '/[*+-]/', $matches[3]) ? "ul" : "ol";736 $list_type = preg_match("/$marker_ul/", $matches[3]) ? "ul" : "ol"; 553 737 # Turn double returns into triple returns, so that we can make a 554 738 # paragraph for the last item in a list, if necessary: 555 739 $list = preg_replace("/\n{2,}/", "\n\n\n", $list); 556 740 $result = _ProcessListItems($list, $marker_any); 557 $result = "<$list_type>\n" . $result . "</$list_type>\n \n";741 $result = "<$list_type>\n" . $result . "</$list_type>\n"; 558 742 return $result; 559 743 } … … 561 745 562 746 function _ProcessListItems($list_str, $marker_any) { 747 # 748 # Process the contents of a single ordered or unordered list, splitting it 749 # into individual list items. 750 # 751 global $md_list_level; 752 753 # The $md_list_level global keeps track of when we're inside a list. 754 # Each time we enter a list, we increment it; when we leave a list, 755 # we decrement. If it's zero, we're not in a list anymore. 756 # 757 # We do this because when we're not inside a list, we want to treat 758 # something like this: 759 # 760 # I recommend upgrading to version 761 # 8. Oops, now this line is treated 762 # as a sub-list. 763 # 764 # As a single paragraph, despite the fact that the second line starts 765 # with a digit-period-space sequence. 766 # 767 # Whereas when we're inside a list (or sub-list), that line will be 768 # treated as the start of a sub-list. What a kludge, huh? This is 769 # an aspect of Markdown's syntax that's hard to parse perfectly 770 # without resorting to mind-reading. Perhaps the solution is to 771 # change the syntax rules such that sub-lists must start with a 772 # starting cardinal number; e.g. "1." or "a.". 773 774 $md_list_level++; 775 563 776 # trim trailing blank lines: 564 777 $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); … … 574 787 '_ProcessListItems_callback', $list_str); 575 788 789 $md_list_level--; 576 790 return $list_str; 577 791 } 578 792 function _ProcessListItems_callback($matches) { 579 793 $item = $matches[4]; 580 $leading_line = $matches[1];581 $leading_space = $matches[2];794 $leading_line =& $matches[1]; 795 $leading_space =& $matches[2]; 582 796 583 797 if ($leading_line || preg_match('/\n{2,}/', $item)) { 584 798 $item = _RunBlockGamut(_Outdent($item)); 585 #$item =~ s/\n+/\n/g;586 799 } 587 800 else { … … 597 810 598 811 function _DoCodeBlocks($text) { 812 # 813 # Process Markdown `<pre><code>` blocks. 814 # 599 815 global $md_tab_width; 600 816 $text = preg_replace_callback("{ … … 616 832 617 833 $codeblock = _EncodeCode(_Outdent($codeblock)); 618 $codeblock = _Detab($codeblock);834 // $codeblock = _Detab($codeblock); 619 835 # trim leading newlines and trailing whitespace 620 836 $codeblock = preg_replace(array('/\A\n+/', '/\s+\z/'), '', $codeblock); … … 627 843 628 844 function _DoCodeSpans($text) { 845 # 846 # * Backtick quotes are used for <code></code> spans. 847 # 848 # * You can use multiple backticks as the delimiters if you want to 849 # include literal backticks in the code span. So, this input: 850 # 851 # Just type ``foo `bar` baz`` at the prompt. 852 # 853 # Will translate to: 854 # 855 # <p>Just type <code>foo `bar` baz</code> at the prompt.</p> 856 # 857 # There's no arbitrary limit to the number of backticks you 858 # can use as delimters. If you need three consecutive backticks 859 # in your code, use four for delimiters, etc. 860 # 861 # * You can use spaces to get literal backticks at the edges: 862 # 863 # ... type `` `bar` `` ... 864 # 865 # Turns to: 866 # 867 # ... type <code>`bar`</code> ... 868 # 629 869 $text = preg_replace_callback("@ 630 870 (`+) # $1 = Opening run of ` … … 648 888 649 889 function _EncodeCode($_) { 890 # 891 # Encode/escape certain characters inside Markdown code runs. 892 # The point is that in code, these characters are literals, 893 # and lose their special Markdown meanings. 894 # 650 895 global $md_escape_table; 651 896 897 # Encode all ampersands; HTML entities are not 898 # entities within a Markdown code span. 652 899 $_ = str_replace('&', '&', $_); 653 900 901 # Do the angle bracket song and dance: 654 902 $_ = str_replace(array('<', '>'), 655 903 array('<', '>'), $_); 656 904 905 # Now, escape characters that are magic in Markdown: 657 906 $_ = str_replace(array_keys($md_escape_table), 658 907 array_values($md_escape_table), $_); … … 664 913 function _DoItalicsAndBold($text) { 665 914 # <strong> must go first: 666 $text = preg_replace('{ (\*\*|__) (?=\S) (.+? ) (?<=\S) \1 }sx',915 $text = preg_replace('{ (\*\*|__) (?=\S) (.+?[*_]*) (?<=\S) \1 }sx', 667 916 '<strong>\2</strong>', $text); 668 917 # Then <em>: … … 710 959 711 960 function _FormParagraphs($text) { 961 # 962 # Params: 963 # $text - string to process with html <p> tags 964 # 712 965 global $md_html_blocks; 713 966 … … 716 969 717 970 $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); 718 $count = count($grafs); 719 971 972 # 973 # Wrap <p> tags. 974 # 720 975 foreach ($grafs as $key => $value) { 721 976 if (!isset( $md_html_blocks[$value] )) { … … 727 982 } 728 983 984 # 985 # Unhashify HTML blocks 986 # 729 987 foreach ($grafs as $key => $value) { 730 988 if (isset( $md_html_blocks[$value] )) { … … 738 996 739 997 function _EncodeAmpsAndAngles($text) { 998 # Smart processing for ampersands and angle brackets that need to be encoded. 999 1000 # Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin: 1001 # http://bumppo.net/projects/amputator/ 740 1002 $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', 741 1003 '&', $text);; … … 749 1011 750 1012 function _EncodeBackslashEscapes($text) { 1013 # 1014 # Parameter: String. 1015 # Returns: The string, with after processing the following backslash 1016 # escape sequences. 1017 # 751 1018 global $md_escape_table, $md_backslash_escape_table; 752 1019 # Must process escaped backslashes first. … … 763 1030 $text = preg_replace('{ 764 1031 < 1032 (?:mailto:)? 765 1033 ( 766 1034 [-.\w]+ … … 778 1046 779 1047 function _EncodeEmailAddress($addr) { 1048 # 1049 # Input: an email address, e.g. "foo@example.com" 1050 # 1051 # Output: the email address as a mailto link, with each character 1052 # of the address encoded as either a decimal or hex entity, in 1053 # the hopes of foiling most address harvesting spam bots. E.g.: 1054 # 1055 # <a href="mailto:foo@e 1056 # xample.com">foo 1057 # @example.com</a> 1058 # 1059 # Based by a filter by Matthew Wickline, posted to the BBEdit-Talk 1060 # mailing list: <http://tinyurl.com/yu7ue> 1061 # 780 1062 $addr = "mailto:" . $addr; 781 1063 $length = strlen($addr); … … 803 1085 804 1086 function _UnescapeSpecialChars($text) { 1087 # 1088 # Swap back in all the special characters we've hidden. 1089 # 805 1090 global $md_escape_table; 806 1091 return str_replace(array_values($md_escape_table), … … 809 1094 810 1095 811 if (!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)); 830 } 831 832 return $tokens; 833 } 834 } 1096 # _TokenizeHTML is shared between PHP Markdown and PHP SmartyPants. 1097 # We only define it if it is not already defined. 1098 if (!function_exists('_TokenizeHTML')) : 1099 function _TokenizeHTML($str) { 1100 # 1101 # Parameter: String containing HTML markup. 1102 # Returns: An array of the tokens comprising the input 1103 # string. Each token is either a tag (possibly with nested, 1104 # tags contained therein, such as <a href="<MTFoo>">, or a 1105 # run of text between tags. Each element of the array is a 1106 # two-element array; the first is either 'tag' or 'text'; 1107 # the second is the actual value. 1108 # 1109 # 1110 # Regular expression derived from the _tokenize() subroutine in 1111 # Brad Choate's MTRegex plugin. 1112 # <http://www.bradchoate.com/past/mtregex.php> 1113 # 1114 $index = 0; 1115 $tokens = array(); 1116 1117 $match = '(?s:<!(?:--.*?--\s*)+>)|'. # comment 1118 '(?s:<\?.*?\?>)|'. # processing instruction 1119 '(?:</?[\w:$]+\b(?>[^"\'>]+|"[^"]*"|\'[^\']*\')*>)'; # regular tags 1120 1121 $parts = preg_split("{($match)}", $str, -1, PREG_SPLIT_DELIM_CAPTURE); 1122 1123 foreach ($parts as $part) { 1124 if (++$index % 2 && $part != '') 1125 array_push($tokens, array('text', $part)); 1126 else 1127 array_push($tokens, array('tag', $part)); 1128 } 1129 1130 return $tokens; 1131 } 1132 endif; 835 1133 836 1134 837 1135 function _Outdent($text) { 1136 # 1137 # Remove one level of line-leading tabs or spaces 1138 # 838 1139 global $md_tab_width; 839 1140 return preg_replace("/^(\\t|[ ]{1,$md_tab_width})/m", "", $text); … … 842 1143 843 1144 function _Detab($text) { 1145 # 1146 # Replace tabs with the appropriate amount of space. 1147 # 844 1148 global $md_tab_width; 845 $text = preg_replace( 846 "/(.*?)\t/e", 847 "'\\1'.str_repeat(' ', $md_tab_width - strlen('\\1') % $md_tab_width)", 848 $text); 1149 1150 # For each line we separate the line in blocks delemited by 1151 # tab characters. Then we reconstruct the line adding the appropriate 1152 # number of space charcters. 1153 1154 $lines = explode("\n", $text); 1155 $text = ""; 1156 1157 foreach ($lines as $line) { 1158 # Split in blocks. 1159 $blocks = explode("\t", $line); 1160 # Add each blocks to the line. 1161 $line = $blocks[0]; 1162 unset($blocks[0]); # Do not add first block twice. 1163 foreach ($blocks as $block) { 1164 # Calculate amount of space, insert spaces, insert block. 1165 $amount = $md_tab_width - strlen($line) % $md_tab_width; 1166 $line .= str_repeat(" ", $amount) . $block; 1167 } 1168 $text .= "$line\n"; 1169 } 849 1170 return $text; 850 1171 } … … 852 1173 853 1174 function _UnslashQuotes($text) { 1175 # 1176 # This function is useful to remove automaticaly slashed double quotes 1177 # when using preg_replace and evaluating an expression. 1178 # Parameter: String. 1179 # Returns: The string with any slash-double-quote (\") sequence replaced 1180 # by a single double quote. 1181 # 854 1182 return str_replace('\"', '"', $text); 855 1183 } 856 1184 1185 1186 /* 1187 1188 PHP Markdown 1189 ============ 1190 1191 Description 1192 ----------- 1193 1194 This is a PHP translation of the original Markdown formatter written in 1195 Perl by John Gruber. 1196 1197 Markdown is a text-to-HTML filter; it translates an easy-to-read / 1198 easy-to-write structured text format into HTML. Markdown's text format 1199 is most similar to that of plain text email, and supports features such 1200 as headers, *emphasis*, code blocks, blockquotes, and links. 1201 1202 Markdown's syntax is designed not as a generic markup language, but 1203 specifically to serve as a front-end to (X)HTML. You can use span-level 1204 HTML tags anywhere in a Markdown document, and you can use block level 1205 HTML tags (like <div> and <table> as well). 1206 1207 For more information about Markdown's syntax, see: 1208 1209 <http://daringfireball.net/projects/markdown/> 1210 1211 1212 Bugs 1213 ---- 1214 1215 To file bug reports please send email to: 1216 1217 <michel.fortin@michelf.com> 1218 1219 Please include with your report: (1) the example input; (2) the output you 1220 expected; (3) the output Markdown actually produced. 1221 1222 1223 Version History 1224 --------------- 1225 1226 See the readme file for detailed release notes for this version. 1227 1228 1.0.1 - 17 Dec 2004 1229 1230 1.0 - 21 Aug 2004 1231 1232 1233 Author & Contributors 1234 --------------------- 1235 1236 Original Perl version by John Gruber 1237 <http://daringfireball.net/> 1238 1239 PHP port and other contributions by Michel Fortin 1240 <http://www.michelf.com/> 1241 1242 1243 Copyright and License 1244 --------------------- 1245 1246 Copyright (c) 2004 Michel Fortin 1247 <http://www.michelf.com/> 1248 All rights reserved. 1249 1250 Copyright (c) 2003-2004 John Gruber 1251 <http://daringfireball.net/> 1252 All rights reserved. 1253 1254 Redistribution and use in source and binary forms, with or without 1255 modification, are permitted provided that the following conditions are 1256 met: 1257 1258 * Redistributions of source code must retain the above copyright notice, 1259 this list of conditions and the following disclaimer. 1260 1261 * Redistributions in binary form must reproduce the above copyright 1262 notice, this list of conditions and the following disclaimer in the 1263 documentation and/or other materials provided with the distribution. 1264 1265 * Neither the name "Markdown" nor the names of its contributors may 1266 be used to endorse or promote products derived from this software 1267 without specific prior written permission. 1268 1269 This software is provided by the copyright holders and contributors "as 1270 is" and any express or implied warranties, including, but not limited 1271 to, the implied warranties of merchantability and fitness for a 1272 particular purpose are disclaimed. In no event shall the copyright owner 1273 or contributors be liable for any direct, indirect, incidental, special, 1274 exemplary, or consequential damages (including, but not limited to, 1275 procurement of substitute goods or services; loss of use, data, or 1276 profits; or business interruption) however caused and on any theory of 1277 liability, whether in contract, strict liability, or tort (including 1278 negligence or otherwise) arising in any way out of the use of this 1279 software, even if advised of the possibility of such damage. 1280 1281 */ 857 1282 ?>
