1<?php 2if(!defined('DOKU_INC')) die('meh.'); 3require_once DOKU_INC . 'inc/parser/lexer.php'; 4require_once DOKU_INC . 'inc/parser/handler.php'; 5 6 7/** 8 * Define various types of modes used by the parser - they are used to 9 * populate the list of modes another mode accepts 10 */ 11global $PARSER_MODES; 12$PARSER_MODES = array( 13 // containers are complex modes that can contain many other modes 14 // hr breaks the principle but they shouldn't be used in tables / lists 15 // so they are put here 16 'container' => array('listblock','table','quote','hr'), 17 18 // some mode are allowed inside the base mode only 19 'baseonly' => array('header'), 20 21 // modes for styling text -- footnote behaves similar to styling 22 'formatting' => array('strong', 'emphasis', 'underline', 'monospace', 23 'subscript', 'superscript', 'deleted', 'footnote'), 24 25 // modes where the token is simply replaced - they can not contain any 26 // other modes 27 'substition' => array('acronym','smiley','wordblock','entity', 28 'camelcaselink', 'internallink','media', 29 'externallink','linebreak','emaillink', 30 'windowssharelink','filelink','notoc', 31 'nocache','multiplyentity','quotes','rss'), 32 33 // modes which have a start and end token but inside which 34 // no other modes should be applied 35 'protected' => array('preformatted','code','file','php','html','htmlblock','phpblock'), 36 37 // inside this mode no wiki markup should be applied but lineendings 38 // and whitespace isn't preserved 39 'disabled' => array('unformatted'), 40 41 // used to mark paragraph boundaries 42 'paragraphs' => array('eol') 43); 44 45//------------------------------------------------------------------- 46 47/** 48* Sets up the Lexer with modes and points it to the Handler 49* For an intro to the Lexer see: wiki:parser 50*/ 51class Doku_Parser { 52 53 var $Handler; 54 55 var $Lexer; 56 57 var $modes = array(); 58 59 var $connected = false; 60 61 function addBaseMode(& $BaseMode) { 62 $this->modes['base'] = & $BaseMode; 63 if ( !$this->Lexer ) { 64 $this->Lexer = new Doku_Lexer($this->Handler,'base', true); 65 } 66 $this->modes['base']->Lexer = & $this->Lexer; 67 } 68 69 /** 70 * PHP preserves order of associative elements 71 * Mode sequence is important 72 */ 73 function addMode($name, & $Mode) { 74 if ( !isset($this->modes['base']) ) { 75 $this->addBaseMode(new Doku_Parser_Mode_base()); 76 } 77 $Mode->Lexer = & $this->Lexer; 78 $this->modes[$name] = & $Mode; 79 } 80 81 function connectModes() { 82 83 if ( $this->connected ) { 84 return; 85 } 86 87 foreach ( array_keys($this->modes) as $mode ) { 88 89 // Base isn't connected to anything 90 if ( $mode == 'base' ) { 91 continue; 92 } 93 94 $this->modes[$mode]->preConnect(); 95 96 foreach ( array_keys($this->modes) as $cm ) { 97 98 if ( $this->modes[$cm]->accepts($mode) ) { 99 $this->modes[$mode]->connectTo($cm); 100 } 101 102 } 103 104 $this->modes[$mode]->postConnect(); 105 } 106 107 $this->connected = true; 108 } 109 110 function parse($doc) { 111 if ( $this->Lexer ) { 112 $this->connectModes(); 113 // Normalize CRs and pad doc 114 $doc = "\n".str_replace("\r\n","\n",$doc)."\n"; 115 $this->Lexer->parse($doc); 116 $this->Handler->_finalize(); 117 return $this->Handler->calls; 118 } else { 119 return false; 120 } 121 } 122 123} 124 125//------------------------------------------------------------------- 126/** 127 * This class and all the subclasses below are 128 * used to reduce the effort required to register 129 * modes with the Lexer. For performance these 130 * could all be eliminated later perhaps, or 131 * the Parser could be serialized to a file once 132 * all modes are registered 133 * 134 * @author Harry Fuecks <hfuecks@gmail.com> 135*/ 136class Doku_Parser_Mode { 137 138 var $Lexer; 139 140 var $allowedModes = array(); 141 142 // returns a number used to determine in which order modes are added 143 function getSort() { 144 trigger_error('getSort() not implemented in '.get_class($this), E_USER_WARNING); 145 } 146 147 // Called before any calls to connectTo 148 function preConnect() {} 149 150 // Connects the mode 151 function connectTo($mode) {} 152 153 // Called after all calls to connectTo 154 function postConnect() {} 155 156 function accepts($mode) { 157 return in_array($mode, (array) $this->allowedModes ); 158 } 159 160} 161 162//------------------------------------------------------------------- 163class Doku_Parser_Mode_base extends Doku_Parser_Mode { 164 165 function Doku_Parser_Mode_base() { 166 global $PARSER_MODES; 167 168 $this->allowedModes = array_merge ( 169 $PARSER_MODES['container'], 170 $PARSER_MODES['baseonly'], 171 $PARSER_MODES['paragraphs'], 172 $PARSER_MODES['formatting'], 173 $PARSER_MODES['substition'], 174 $PARSER_MODES['protected'], 175 $PARSER_MODES['disabled'] 176 ); 177 } 178 179 function getSort() { 180 return 0; 181 } 182} 183 184//------------------------------------------------------------------- 185class Doku_Parser_Mode_footnote extends Doku_Parser_Mode { 186 187 function Doku_Parser_Mode_footnote() { 188 global $PARSER_MODES; 189 190 $this->allowedModes = array_merge ( 191 $PARSER_MODES['container'], 192 $PARSER_MODES['formatting'], 193 $PARSER_MODES['substition'], 194 $PARSER_MODES['protected'], 195 $PARSER_MODES['disabled'] 196 ); 197 198 unset($this->allowedModes[array_search('footnote', $this->allowedModes)]); 199 } 200 201 function connectTo($mode) { 202 $this->Lexer->addEntryPattern( 203 '\x28\x28(?=.*\x29\x29)',$mode,'footnote' 204 ); 205 } 206 207 function postConnect() { 208 $this->Lexer->addExitPattern( 209 '\x29\x29','footnote' 210 ); 211 } 212 213 function getSort() { 214 return 150; 215 } 216} 217 218//------------------------------------------------------------------- 219class Doku_Parser_Mode_header extends Doku_Parser_Mode { 220 221 function preConnect() { 222 //we're not picky about the closing ones, two are enough 223 $this->Lexer->addSpecialPattern( 224 '[ \t]*={2,}[^\n]+={2,}[ \t]*(?=\n)', 225 'base', 226 'header' 227 ); 228 } 229 230 function getSort() { 231 return 50; 232 } 233} 234 235//------------------------------------------------------------------- 236class Doku_Parser_Mode_notoc extends Doku_Parser_Mode { 237 238 function connectTo($mode) { 239 $this->Lexer->addSpecialPattern('~~NOTOC~~',$mode,'notoc'); 240 } 241 242 function getSort() { 243 return 30; 244 } 245} 246 247//------------------------------------------------------------------- 248class Doku_Parser_Mode_nocache extends Doku_Parser_Mode { 249 250 function connectTo($mode) { 251 $this->Lexer->addSpecialPattern('~~NOCACHE~~',$mode,'nocache'); 252 } 253 254 function getSort() { 255 return 40; 256 } 257} 258 259//------------------------------------------------------------------- 260class Doku_Parser_Mode_linebreak extends Doku_Parser_Mode { 261 262 function connectTo($mode) { 263 $this->Lexer->addSpecialPattern('\x5C{2}(?:[ \t]|(?=\n))',$mode,'linebreak'); 264 } 265 266 function getSort() { 267 return 140; 268 } 269} 270 271//------------------------------------------------------------------- 272class Doku_Parser_Mode_eol extends Doku_Parser_Mode { 273 274 function connectTo($mode) { 275 $badModes = array('listblock','table'); 276 if ( in_array($mode, $badModes) ) { 277 return; 278 } 279 // see FS#1652, pattern extended to swallow preceding whitespace to avoid issues with lines that only contain whitespace 280 $this->Lexer->addSpecialPattern('(?:^[ \t]*)?\n',$mode,'eol'); 281 } 282 283 function getSort() { 284 return 370; 285 } 286} 287 288//------------------------------------------------------------------- 289class Doku_Parser_Mode_hr extends Doku_Parser_Mode { 290 291 function connectTo($mode) { 292 $this->Lexer->addSpecialPattern('\n[ \t]*-{4,}[ \t]*(?=\n)',$mode,'hr'); 293 } 294 295 function getSort() { 296 return 160; 297 } 298} 299 300//------------------------------------------------------------------- 301/** 302 * This class sets the markup for bold (=strong), 303 * italic (=emphasis), underline etc. 304 */ 305class Doku_Parser_Mode_formatting extends Doku_Parser_Mode { 306 var $type; 307 308 var $formatting = array ( 309 'strong' => array ( 310 'entry'=>'\*\*(?=.*\*\*)', 311 'exit'=>'\*\*', 312 'sort'=>70 313 ), 314 315 'emphasis'=> array ( 316 'entry'=>'//(?=[^\x00]*[^:])', //hack for bugs #384 #763 #1468 317 'exit'=>'//', 318 'sort'=>80 319 ), 320 321 'underline'=> array ( 322 'entry'=>'__(?=.*__)', 323 'exit'=>'__', 324 'sort'=>90 325 ), 326 327 'monospace'=> array ( 328 'entry'=>'\x27\x27(?=.*\x27\x27)', 329 'exit'=>'\x27\x27', 330 'sort'=>100 331 ), 332 333 'subscript'=> array ( 334 'entry'=>'<sub>(?=.*</sub>)', 335 'exit'=>'</sub>', 336 'sort'=>110 337 ), 338 339 'superscript'=> array ( 340 'entry'=>'<sup>(?=.*</sup>)', 341 'exit'=>'</sup>', 342 'sort'=>120 343 ), 344 345 'deleted'=> array ( 346 'entry'=>'<del>(?=.*</del>)', 347 'exit'=>'</del>', 348 'sort'=>130 349 ), 350 ); 351 352 function Doku_Parser_Mode_formatting($type) { 353 global $PARSER_MODES; 354 355 if ( !array_key_exists($type, $this->formatting) ) { 356 trigger_error('Invalid formatting type '.$type, E_USER_WARNING); 357 } 358 359 $this->type = $type; 360 361 // formatting may contain other formatting but not it self 362 $modes = $PARSER_MODES['formatting']; 363 $key = array_search($type, $modes); 364 if ( is_int($key) ) { 365 unset($modes[$key]); 366 } 367 368 $this->allowedModes = array_merge ( 369 $modes, 370 $PARSER_MODES['substition'], 371 $PARSER_MODES['disabled'] 372 ); 373 } 374 375 function connectTo($mode) { 376 377 // Can't nest formatting in itself 378 if ( $mode == $this->type ) { 379 return; 380 } 381 382 $this->Lexer->addEntryPattern( 383 $this->formatting[$this->type]['entry'], 384 $mode, 385 $this->type 386 ); 387 } 388 389 function postConnect() { 390 391 $this->Lexer->addExitPattern( 392 $this->formatting[$this->type]['exit'], 393 $this->type 394 ); 395 396 } 397 398 function getSort() { 399 return $this->formatting[$this->type]['sort']; 400 } 401} 402 403//------------------------------------------------------------------- 404class Doku_Parser_Mode_listblock extends Doku_Parser_Mode { 405 406 function Doku_Parser_Mode_listblock() { 407 global $PARSER_MODES; 408 409 $this->allowedModes = array_merge ( 410 $PARSER_MODES['formatting'], 411 $PARSER_MODES['substition'], 412 $PARSER_MODES['disabled'], 413 $PARSER_MODES['protected'] #XXX new 414 ); 415 416 // $this->allowedModes[] = 'footnote'; 417 } 418 419 function connectTo($mode) { 420 $this->Lexer->addEntryPattern('[ \t]*\n {2,}[\-\*]',$mode,'listblock'); 421 $this->Lexer->addEntryPattern('[ \t]*\n\t{1,}[\-\*]',$mode,'listblock'); 422 423 $this->Lexer->addPattern('\n {2,}[\-\*]','listblock'); 424 $this->Lexer->addPattern('\n\t{1,}[\-\*]','listblock'); 425 426 } 427 428 function postConnect() { 429 $this->Lexer->addExitPattern('\n','listblock'); 430 } 431 432 function getSort() { 433 return 10; 434 } 435} 436 437//------------------------------------------------------------------- 438class Doku_Parser_Mode_table extends Doku_Parser_Mode { 439 440 function Doku_Parser_Mode_table() { 441 global $PARSER_MODES; 442 443 $this->allowedModes = array_merge ( 444 $PARSER_MODES['formatting'], 445 $PARSER_MODES['substition'], 446 $PARSER_MODES['disabled'], 447 $PARSER_MODES['protected'] 448 ); 449 } 450 451 function connectTo($mode) { 452 $this->Lexer->addEntryPattern('\n\^',$mode,'table'); 453 $this->Lexer->addEntryPattern('\n\|',$mode,'table'); 454 } 455 456 function postConnect() { 457 $this->Lexer->addPattern('\n\^','table'); 458 $this->Lexer->addPattern('\n\|','table'); 459 $this->Lexer->addPattern('[\t ]*:::[\t ]*(?=[\|\^])','table'); 460 $this->Lexer->addPattern('[\t ]+','table'); 461 $this->Lexer->addPattern('\^','table'); 462 $this->Lexer->addPattern('\|','table'); 463 $this->Lexer->addExitPattern('\n','table'); 464 } 465 466 function getSort() { 467 return 60; 468 } 469} 470 471//------------------------------------------------------------------- 472class Doku_Parser_Mode_unformatted extends Doku_Parser_Mode { 473 474 function connectTo($mode) { 475 $this->Lexer->addEntryPattern('<nowiki>(?=.*</nowiki>)',$mode,'unformatted'); 476 $this->Lexer->addEntryPattern('%%(?=.*%%)',$mode,'unformattedalt'); 477 } 478 479 function postConnect() { 480 $this->Lexer->addExitPattern('</nowiki>','unformatted'); 481 $this->Lexer->addExitPattern('%%','unformattedalt'); 482 $this->Lexer->mapHandler('unformattedalt','unformatted'); 483 } 484 485 function getSort() { 486 return 170; 487 } 488} 489 490//------------------------------------------------------------------- 491class Doku_Parser_Mode_php extends Doku_Parser_Mode { 492 493 function connectTo($mode) { 494 $this->Lexer->addEntryPattern('<php>(?=.*</php>)',$mode,'php'); 495 $this->Lexer->addEntryPattern('<PHP>(?=.*</PHP>)',$mode,'phpblock'); 496 } 497 498 function postConnect() { 499 $this->Lexer->addExitPattern('</php>','php'); 500 $this->Lexer->addExitPattern('</PHP>','phpblock'); 501 } 502 503 function getSort() { 504 return 180; 505 } 506} 507 508//------------------------------------------------------------------- 509class Doku_Parser_Mode_html extends Doku_Parser_Mode { 510 511 function connectTo($mode) { 512 $this->Lexer->addEntryPattern('<html>(?=.*</html>)',$mode,'html'); 513 $this->Lexer->addEntryPattern('<HTML>(?=.*</HTML>)',$mode,'htmlblock'); 514 } 515 516 function postConnect() { 517 $this->Lexer->addExitPattern('</html>','html'); 518 $this->Lexer->addExitPattern('</HTML>','htmlblock'); 519 } 520 521 function getSort() { 522 return 190; 523 } 524} 525 526//------------------------------------------------------------------- 527class Doku_Parser_Mode_preformatted extends Doku_Parser_Mode { 528 529 function connectTo($mode) { 530 // Has hard coded awareness of lists... 531 $this->Lexer->addEntryPattern('\n (?![\*\-])',$mode,'preformatted'); 532 $this->Lexer->addEntryPattern('\n\t(?![\*\-])',$mode,'preformatted'); 533 534 // How to effect a sub pattern with the Lexer! 535 $this->Lexer->addPattern('\n ','preformatted'); 536 $this->Lexer->addPattern('\n\t','preformatted'); 537 538 } 539 540 function postConnect() { 541 $this->Lexer->addExitPattern('\n','preformatted'); 542 } 543 544 function getSort() { 545 return 20; 546 } 547} 548 549//------------------------------------------------------------------- 550class Doku_Parser_Mode_code extends Doku_Parser_Mode { 551 552 function connectTo($mode) { 553 $this->Lexer->addEntryPattern('<code(?=.*</code>)',$mode,'code'); 554 } 555 556 function postConnect() { 557 $this->Lexer->addExitPattern('</code>','code'); 558 } 559 560 function getSort() { 561 return 200; 562 } 563} 564 565//------------------------------------------------------------------- 566class Doku_Parser_Mode_file extends Doku_Parser_Mode { 567 568 function connectTo($mode) { 569 $this->Lexer->addEntryPattern('<file(?=.*</file>)',$mode,'file'); 570 } 571 572 function postConnect() { 573 $this->Lexer->addExitPattern('</file>','file'); 574 } 575 576 function getSort() { 577 return 210; 578 } 579} 580 581//------------------------------------------------------------------- 582class Doku_Parser_Mode_quote extends Doku_Parser_Mode { 583 584 function Doku_Parser_Mode_quote() { 585 global $PARSER_MODES; 586 587 $this->allowedModes = array_merge ( 588 $PARSER_MODES['formatting'], 589 $PARSER_MODES['substition'], 590 $PARSER_MODES['disabled'], 591 $PARSER_MODES['protected'] #XXX new 592 ); 593 #$this->allowedModes[] = 'footnote'; 594 #$this->allowedModes[] = 'preformatted'; 595 #$this->allowedModes[] = 'unformatted'; 596 } 597 598 function connectTo($mode) { 599 $this->Lexer->addEntryPattern('\n>{1,}',$mode,'quote'); 600 } 601 602 function postConnect() { 603 $this->Lexer->addPattern('\n>{1,}','quote'); 604 $this->Lexer->addExitPattern('\n','quote'); 605 } 606 607 function getSort() { 608 return 220; 609 } 610} 611 612//------------------------------------------------------------------- 613class Doku_Parser_Mode_acronym extends Doku_Parser_Mode { 614 // A list 615 var $acronyms = array(); 616 var $pattern = ''; 617 618 function Doku_Parser_Mode_acronym($acronyms) { 619 usort($acronyms,array($this,'_compare')); 620 $this->acronyms = $acronyms; 621 } 622 623 function preConnect() { 624 if(!count($this->acronyms)) return; 625 626 $bound = '[\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]'; 627 $acronyms = array_map('Doku_Lexer_Escape',$this->acronyms); 628 $this->pattern = '(?<=^|'.$bound.')(?:'.join('|',$acronyms).')(?='.$bound.')'; 629 } 630 631 function connectTo($mode) { 632 if(!count($this->acronyms)) return; 633 634 if ( strlen($this->pattern) > 0 ) { 635 $this->Lexer->addSpecialPattern($this->pattern,$mode,'acronym'); 636 } 637 } 638 639 function getSort() { 640 return 240; 641 } 642 643 /** 644 * sort callback to order by string length descending 645 */ 646 function _compare($a,$b) { 647 $a_len = strlen($a); 648 $b_len = strlen($b); 649 if ($a_len > $b_len) { 650 return -1; 651 } else if ($a_len < $b_len) { 652 return 1; 653 } 654 655 return 0; 656 } 657} 658 659//------------------------------------------------------------------- 660class Doku_Parser_Mode_smiley extends Doku_Parser_Mode { 661 // A list 662 var $smileys = array(); 663 var $pattern = ''; 664 665 function Doku_Parser_Mode_smiley($smileys) { 666 $this->smileys = $smileys; 667 } 668 669 function preConnect() { 670 if(!count($this->smileys) || $this->pattern != '') return; 671 672 $sep = ''; 673 foreach ( $this->smileys as $smiley ) { 674 $this->pattern .= $sep.'(?<=\W|^)'.Doku_Lexer_Escape($smiley).'(?=\W|$)'; 675 $sep = '|'; 676 } 677 } 678 679 function connectTo($mode) { 680 if(!count($this->smileys)) return; 681 682 if ( strlen($this->pattern) > 0 ) { 683 $this->Lexer->addSpecialPattern($this->pattern,$mode,'smiley'); 684 } 685 } 686 687 function getSort() { 688 return 230; 689 } 690} 691 692//------------------------------------------------------------------- 693class Doku_Parser_Mode_wordblock extends Doku_Parser_Mode { 694 // A list 695 var $badwords = array(); 696 var $pattern = ''; 697 698 function Doku_Parser_Mode_wordblock($badwords) { 699 $this->badwords = $badwords; 700 } 701 702 function preConnect() { 703 704 if ( count($this->badwords) == 0 || $this->pattern != '') { 705 return; 706 } 707 708 $sep = ''; 709 foreach ( $this->badwords as $badword ) { 710 $this->pattern .= $sep.'(?<=\b)(?i)'.Doku_Lexer_Escape($badword).'(?-i)(?=\b)'; 711 $sep = '|'; 712 } 713 714 } 715 716 function connectTo($mode) { 717 if ( strlen($this->pattern) > 0 ) { 718 $this->Lexer->addSpecialPattern($this->pattern,$mode,'wordblock'); 719 } 720 } 721 722 function getSort() { 723 return 250; 724 } 725} 726 727//------------------------------------------------------------------- 728class Doku_Parser_Mode_entity extends Doku_Parser_Mode { 729 // A list 730 var $entities = array(); 731 var $pattern = ''; 732 733 function Doku_Parser_Mode_entity($entities) { 734 $this->entities = $entities; 735 } 736 737 function preConnect() { 738 if(!count($this->entities) || $this->pattern != '') return; 739 740 $sep = ''; 741 foreach ( $this->entities as $entity ) { 742 $this->pattern .= $sep.Doku_Lexer_Escape($entity); 743 $sep = '|'; 744 } 745 } 746 747 function connectTo($mode) { 748 if(!count($this->entities)) return; 749 750 if ( strlen($this->pattern) > 0 ) { 751 $this->Lexer->addSpecialPattern($this->pattern,$mode,'entity'); 752 } 753 } 754 755 function getSort() { 756 return 260; 757 } 758} 759 760//------------------------------------------------------------------- 761// Implements the 640x480 replacement 762class Doku_Parser_Mode_multiplyentity extends Doku_Parser_Mode { 763 764 function connectTo($mode) { 765 766 $this->Lexer->addSpecialPattern( 767 '(?<=\b)(?:[1-9]|\d{2,})[xX]\d+(?=\b)',$mode,'multiplyentity' 768 ); 769 770 } 771 772 function getSort() { 773 return 270; 774 } 775} 776 777//------------------------------------------------------------------- 778class Doku_Parser_Mode_quotes extends Doku_Parser_Mode { 779 780 function connectTo($mode) { 781 global $conf; 782 783 $ws = '\s/\#~:+=&%@\-\x28\x29\]\[{}><"\''; // whitespace 784 $punc = ';,\.?!'; 785 786 if($conf['typography'] == 2){ 787 $this->Lexer->addSpecialPattern( 788 "(?<=^|[$ws])'(?=[^$ws$punc])",$mode,'singlequoteopening' 789 ); 790 $this->Lexer->addSpecialPattern( 791 "(?<=^|[^$ws]|[$punc])'(?=$|[$ws$punc])",$mode,'singlequoteclosing' 792 ); 793 $this->Lexer->addSpecialPattern( 794 "(?<=^|[^$ws$punc])'(?=$|[^$ws$punc])",$mode,'apostrophe' 795 ); 796 } 797 798 $this->Lexer->addSpecialPattern( 799 "(?<=^|[$ws])\"(?=[^$ws$punc])",$mode,'doublequoteopening' 800 ); 801 $this->Lexer->addSpecialPattern( 802 "\"",$mode,'doublequoteclosing' 803 ); 804 805 806 } 807 808 function getSort() { 809 return 280; 810 } 811} 812 813//------------------------------------------------------------------- 814class Doku_Parser_Mode_camelcaselink extends Doku_Parser_Mode { 815 816 function connectTo($mode) { 817 $this->Lexer->addSpecialPattern( 818 '\b[A-Z]+[a-z]+[A-Z][A-Za-z]*\b',$mode,'camelcaselink' 819 ); 820 } 821 822 function getSort() { 823 return 290; 824 } 825} 826 827//------------------------------------------------------------------- 828class Doku_Parser_Mode_internallink extends Doku_Parser_Mode { 829 830 function connectTo($mode) { 831 // Word boundaries? 832 $this->Lexer->addSpecialPattern("\[\[.+?\]\]",$mode,'internallink'); 833 } 834 835 function getSort() { 836 return 300; 837 } 838} 839 840//------------------------------------------------------------------- 841class Doku_Parser_Mode_media extends Doku_Parser_Mode { 842 843 function connectTo($mode) { 844 // Word boundaries? 845 $this->Lexer->addSpecialPattern("\{\{[^\}]+\}\}",$mode,'media'); 846 } 847 848 function getSort() { 849 return 320; 850 } 851} 852 853//------------------------------------------------------------------- 854class Doku_Parser_Mode_rss extends Doku_Parser_Mode { 855 856 function connectTo($mode) { 857 $this->Lexer->addSpecialPattern("\{\{rss>[^\}]+\}\}",$mode,'rss'); 858 } 859 860 function getSort() { 861 return 310; 862 } 863} 864 865//------------------------------------------------------------------- 866class Doku_Parser_Mode_externallink extends Doku_Parser_Mode { 867 var $schemes = array(); 868 var $patterns = array(); 869 870 function preConnect() { 871 if(count($this->patterns)) return; 872 873 $ltrs = '\w'; 874 $gunk = '/\#~:.?+=&%@!\-'; 875 $punc = '.:?\-;,'; 876 $host = $ltrs.$punc; 877 $any = $ltrs.$gunk.$punc; 878 879 $this->schemes = getSchemes(); 880 foreach ( $this->schemes as $scheme ) { 881 $this->patterns[] = '\b(?i)'.$scheme.'(?-i)://['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; 882 } 883 884 $this->patterns[] = '\b(?i)www?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; 885 $this->patterns[] = '\b(?i)ftp?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; 886 } 887 888 function connectTo($mode) { 889 890 foreach ( $this->patterns as $pattern ) { 891 $this->Lexer->addSpecialPattern($pattern,$mode,'externallink'); 892 } 893 } 894 895 function getSort() { 896 return 330; 897 } 898} 899 900//------------------------------------------------------------------- 901class Doku_Parser_Mode_filelink extends Doku_Parser_Mode { 902 903 var $pattern; 904 905 function preConnect() { 906 907 $ltrs = '\w'; 908 $gunk = '/\#~:.?+=&%@!\-'; 909 $punc = '.:?\-;,'; 910 $host = $ltrs.$punc; 911 $any = $ltrs.$gunk.$punc; 912 913 $this->pattern = '\b(?i)file(?-i)://['.$any.']+?['. 914 $punc.']*[^'.$any.']'; 915 } 916 917 function connectTo($mode) { 918 $this->Lexer->addSpecialPattern( 919 $this->pattern,$mode,'filelink'); 920 } 921 922 function getSort() { 923 return 360; 924 } 925} 926 927//------------------------------------------------------------------- 928class Doku_Parser_Mode_windowssharelink extends Doku_Parser_Mode { 929 930 var $pattern; 931 932 function preConnect() { 933 $this->pattern = "\\\\\\\\\w+?(?:\\\\[\w$]+)+"; 934 } 935 936 function connectTo($mode) { 937 $this->Lexer->addSpecialPattern( 938 $this->pattern,$mode,'windowssharelink'); 939 } 940 941 function getSort() { 942 return 350; 943 } 944} 945 946//------------------------------------------------------------------- 947class Doku_Parser_Mode_emaillink extends Doku_Parser_Mode { 948 949 function connectTo($mode) { 950 // pattern below is defined in inc/mail.php 951 $this->Lexer->addSpecialPattern('<'.PREG_PATTERN_VALID_EMAIL.'>',$mode,'emaillink'); 952 } 953 954 function getSort() { 955 return 340; 956 } 957} 958 959 960//Setup VIM: ex: et ts=4 : 961