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// sets the markup for bold (=strong), italic (=emphasis), underline, 302// etc. 303class Doku_Parser_Mode_formatting extends Doku_Parser_Mode { 304 var $type; 305 306 var $formatting = array ( 307 'strong' => array ( 308 'entry'=>'\*\*(?=.*\*\*)', 309 'exit'=>'\*\*', 310 'sort'=>70 311 ), 312 313 'emphasis'=> array ( 314 'entry'=>'//(?=[^\x00]*[^:])', //hack for bugs #384 #763 #1468 315 'exit'=>'//', 316 'sort'=>80 317 ), 318 319 'underline'=> array ( 320 'entry'=>'__(?=.*__)', 321 'exit'=>'__', 322 'sort'=>90 323 ), 324 325 'monospace'=> array ( 326 'entry'=>'\x27\x27(?=.*\x27\x27)', 327 'exit'=>'\x27\x27', 328 'sort'=>100 329 ), 330 331 'subscript'=> array ( 332 'entry'=>'<sub>(?=.*</sub>)', 333 'exit'=>'</sub>', 334 'sort'=>110 335 ), 336 337 'superscript'=> array ( 338 'entry'=>'<sup>(?=.*</sup>)', 339 'exit'=>'</sup>', 340 'sort'=>120 341 ), 342 343 'deleted'=> array ( 344 'entry'=>'<del>(?=.*</del>)', 345 'exit'=>'</del>', 346 'sort'=>130 347 ), 348 ); 349 350 function Doku_Parser_Mode_formatting($type) { 351 global $PARSER_MODES; 352 353 if ( !array_key_exists($type, $this->formatting) ) { 354 trigger_error('Invalid formatting type '.$type, E_USER_WARNING); 355 } 356 357 $this->type = $type; 358 359 // formatting may contain other formatting but not it self 360 $modes = $PARSER_MODES['formatting']; 361 $key = array_search($type, $modes); 362 if ( is_int($key) ) { 363 unset($modes[$key]); 364 } 365 366 $this->allowedModes = array_merge ( 367 $modes, 368 $PARSER_MODES['substition'], 369 $PARSER_MODES['disabled'] 370 ); 371 } 372 373 function connectTo($mode) { 374 375 // Can't nest formatting in itself 376 if ( $mode == $this->type ) { 377 return; 378 } 379 380 $this->Lexer->addEntryPattern( 381 $this->formatting[$this->type]['entry'], 382 $mode, 383 $this->type 384 ); 385 } 386 387 function postConnect() { 388 389 $this->Lexer->addExitPattern( 390 $this->formatting[$this->type]['exit'], 391 $this->type 392 ); 393 394 } 395 396 function getSort() { 397 return $this->formatting[$this->type]['sort']; 398 } 399} 400 401//------------------------------------------------------------------- 402class Doku_Parser_Mode_listblock extends Doku_Parser_Mode { 403 404 function Doku_Parser_Mode_listblock() { 405 global $PARSER_MODES; 406 407 $this->allowedModes = array_merge ( 408 $PARSER_MODES['formatting'], 409 $PARSER_MODES['substition'], 410 $PARSER_MODES['disabled'], 411 $PARSER_MODES['protected'] #XXX new 412 ); 413 414 // $this->allowedModes[] = 'footnote'; 415 } 416 417 function connectTo($mode) { 418 $this->Lexer->addEntryPattern('[ \t]*\n {2,}[\-\*]',$mode,'listblock'); 419 $this->Lexer->addEntryPattern('[ \t]*\n\t{1,}[\-\*]',$mode,'listblock'); 420 421 $this->Lexer->addPattern('\n {2,}[\-\*]','listblock'); 422 $this->Lexer->addPattern('\n\t{1,}[\-\*]','listblock'); 423 424 } 425 426 function postConnect() { 427 $this->Lexer->addExitPattern('\n','listblock'); 428 } 429 430 function getSort() { 431 return 10; 432 } 433} 434 435//------------------------------------------------------------------- 436class Doku_Parser_Mode_table extends Doku_Parser_Mode { 437 438 function Doku_Parser_Mode_table() { 439 global $PARSER_MODES; 440 441 $this->allowedModes = array_merge ( 442 $PARSER_MODES['formatting'], 443 $PARSER_MODES['substition'], 444 $PARSER_MODES['disabled'], 445 $PARSER_MODES['protected'] 446 ); 447 } 448 449 function connectTo($mode) { 450 $this->Lexer->addEntryPattern('\n\^',$mode,'table'); 451 $this->Lexer->addEntryPattern('\n\|',$mode,'table'); 452 } 453 454 function postConnect() { 455 $this->Lexer->addPattern('\n\^','table'); 456 $this->Lexer->addPattern('\n\|','table'); 457 $this->Lexer->addPattern('[\t ]*:::[\t ]*(?=[\|\^])','table'); 458 $this->Lexer->addPattern('[\t ]+','table'); 459 $this->Lexer->addPattern('\^','table'); 460 $this->Lexer->addPattern('\|','table'); 461 $this->Lexer->addExitPattern('\n','table'); 462 } 463 464 function getSort() { 465 return 60; 466 } 467} 468 469//------------------------------------------------------------------- 470class Doku_Parser_Mode_unformatted extends Doku_Parser_Mode { 471 472 function connectTo($mode) { 473 $this->Lexer->addEntryPattern('<nowiki>(?=.*</nowiki>)',$mode,'unformatted'); 474 $this->Lexer->addEntryPattern('%%(?=.*%%)',$mode,'unformattedalt'); 475 } 476 477 function postConnect() { 478 $this->Lexer->addExitPattern('</nowiki>','unformatted'); 479 $this->Lexer->addExitPattern('%%','unformattedalt'); 480 $this->Lexer->mapHandler('unformattedalt','unformatted'); 481 } 482 483 function getSort() { 484 return 170; 485 } 486} 487 488//------------------------------------------------------------------- 489class Doku_Parser_Mode_php extends Doku_Parser_Mode { 490 491 function connectTo($mode) { 492 $this->Lexer->addEntryPattern('<php>(?=.*</php>)',$mode,'php'); 493 $this->Lexer->addEntryPattern('<PHP>(?=.*</PHP>)',$mode,'phpblock'); 494 } 495 496 function postConnect() { 497 $this->Lexer->addExitPattern('</php>','php'); 498 $this->Lexer->addExitPattern('</PHP>','phpblock'); 499 } 500 501 function getSort() { 502 return 180; 503 } 504} 505 506//------------------------------------------------------------------- 507class Doku_Parser_Mode_html extends Doku_Parser_Mode { 508 509 function connectTo($mode) { 510 $this->Lexer->addEntryPattern('<html>(?=.*</html>)',$mode,'html'); 511 $this->Lexer->addEntryPattern('<HTML>(?=.*</HTML>)',$mode,'htmlblock'); 512 } 513 514 function postConnect() { 515 $this->Lexer->addExitPattern('</html>','html'); 516 $this->Lexer->addExitPattern('</HTML>','htmlblock'); 517 } 518 519 function getSort() { 520 return 190; 521 } 522} 523 524//------------------------------------------------------------------- 525class Doku_Parser_Mode_preformatted extends Doku_Parser_Mode { 526 527 function connectTo($mode) { 528 // Has hard coded awareness of lists... 529 $this->Lexer->addEntryPattern('\n (?![\*\-])',$mode,'preformatted'); 530 $this->Lexer->addEntryPattern('\n\t(?![\*\-])',$mode,'preformatted'); 531 532 // How to effect a sub pattern with the Lexer! 533 $this->Lexer->addPattern('\n ','preformatted'); 534 $this->Lexer->addPattern('\n\t','preformatted'); 535 536 } 537 538 function postConnect() { 539 $this->Lexer->addExitPattern('\n','preformatted'); 540 } 541 542 function getSort() { 543 return 20; 544 } 545} 546 547//------------------------------------------------------------------- 548class Doku_Parser_Mode_code extends Doku_Parser_Mode { 549 550 function connectTo($mode) { 551 $this->Lexer->addEntryPattern('<code(?=.*</code>)',$mode,'code'); 552 } 553 554 function postConnect() { 555 $this->Lexer->addExitPattern('</code>','code'); 556 } 557 558 function getSort() { 559 return 200; 560 } 561} 562 563//------------------------------------------------------------------- 564class Doku_Parser_Mode_file extends Doku_Parser_Mode { 565 566 function connectTo($mode) { 567 $this->Lexer->addEntryPattern('<file(?=.*</file>)',$mode,'file'); 568 } 569 570 function postConnect() { 571 $this->Lexer->addExitPattern('</file>','file'); 572 } 573 574 function getSort() { 575 return 210; 576 } 577} 578 579//------------------------------------------------------------------- 580class Doku_Parser_Mode_quote extends Doku_Parser_Mode { 581 582 function Doku_Parser_Mode_quote() { 583 global $PARSER_MODES; 584 585 $this->allowedModes = array_merge ( 586 $PARSER_MODES['formatting'], 587 $PARSER_MODES['substition'], 588 $PARSER_MODES['disabled'], 589 $PARSER_MODES['protected'] #XXX new 590 ); 591 #$this->allowedModes[] = 'footnote'; 592 #$this->allowedModes[] = 'preformatted'; 593 #$this->allowedModes[] = 'unformatted'; 594 } 595 596 function connectTo($mode) { 597 $this->Lexer->addEntryPattern('\n>{1,}',$mode,'quote'); 598 } 599 600 function postConnect() { 601 $this->Lexer->addPattern('\n>{1,}','quote'); 602 $this->Lexer->addExitPattern('\n','quote'); 603 } 604 605 function getSort() { 606 return 220; 607 } 608} 609 610//------------------------------------------------------------------- 611class Doku_Parser_Mode_acronym extends Doku_Parser_Mode { 612 // A list 613 var $acronyms = array(); 614 var $pattern = ''; 615 616 function Doku_Parser_Mode_acronym($acronyms) { 617 usort($acronyms,array($this,'_compare')); 618 $this->acronyms = $acronyms; 619 } 620 621 function preConnect() { 622 if(!count($this->acronyms)) return; 623 624 $bound = '[\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]'; 625 $acronyms = array_map('Doku_Lexer_Escape',$this->acronyms); 626 $this->pattern = '(?<=^|'.$bound.')(?:'.join('|',$acronyms).')(?='.$bound.')'; 627 } 628 629 function connectTo($mode) { 630 if(!count($this->acronyms)) return; 631 632 if ( strlen($this->pattern) > 0 ) { 633 $this->Lexer->addSpecialPattern($this->pattern,$mode,'acronym'); 634 } 635 } 636 637 function getSort() { 638 return 240; 639 } 640 641 /** 642 * sort callback to order by string length descending 643 */ 644 function _compare($a,$b) { 645 $a_len = strlen($a); 646 $b_len = strlen($b); 647 if ($a_len > $b_len) { 648 return -1; 649 } else if ($a_len < $b_len) { 650 return 1; 651 } 652 653 return 0; 654 } 655} 656 657//------------------------------------------------------------------- 658class Doku_Parser_Mode_smiley extends Doku_Parser_Mode { 659 // A list 660 var $smileys = array(); 661 var $pattern = ''; 662 663 function Doku_Parser_Mode_smiley($smileys) { 664 $this->smileys = $smileys; 665 } 666 667 function preConnect() { 668 if(!count($this->smileys) || $this->pattern != '') return; 669 670 $sep = ''; 671 foreach ( $this->smileys as $smiley ) { 672 $this->pattern .= $sep.'(?<=\W|^)'.Doku_Lexer_Escape($smiley).'(?=\W|$)'; 673 $sep = '|'; 674 } 675 } 676 677 function connectTo($mode) { 678 if(!count($this->smileys)) return; 679 680 if ( strlen($this->pattern) > 0 ) { 681 $this->Lexer->addSpecialPattern($this->pattern,$mode,'smiley'); 682 } 683 } 684 685 function getSort() { 686 return 230; 687 } 688} 689 690//------------------------------------------------------------------- 691class Doku_Parser_Mode_wordblock extends Doku_Parser_Mode { 692 // A list 693 var $badwords = array(); 694 var $pattern = ''; 695 696 function Doku_Parser_Mode_wordblock($badwords) { 697 $this->badwords = $badwords; 698 } 699 700 function preConnect() { 701 702 if ( count($this->badwords) == 0 || $this->pattern != '') { 703 return; 704 } 705 706 $sep = ''; 707 foreach ( $this->badwords as $badword ) { 708 $this->pattern .= $sep.'(?<=\b)(?i)'.Doku_Lexer_Escape($badword).'(?-i)(?=\b)'; 709 $sep = '|'; 710 } 711 712 } 713 714 function connectTo($mode) { 715 if ( strlen($this->pattern) > 0 ) { 716 $this->Lexer->addSpecialPattern($this->pattern,$mode,'wordblock'); 717 } 718 } 719 720 function getSort() { 721 return 250; 722 } 723} 724 725//------------------------------------------------------------------- 726class Doku_Parser_Mode_entity extends Doku_Parser_Mode { 727 // A list 728 var $entities = array(); 729 var $pattern = ''; 730 731 function Doku_Parser_Mode_entity($entities) { 732 $this->entities = $entities; 733 } 734 735 function preConnect() { 736 if(!count($this->entities) || $this->pattern != '') return; 737 738 $sep = ''; 739 foreach ( $this->entities as $entity ) { 740 $this->pattern .= $sep.Doku_Lexer_Escape($entity); 741 $sep = '|'; 742 } 743 } 744 745 function connectTo($mode) { 746 if(!count($this->entities)) return; 747 748 if ( strlen($this->pattern) > 0 ) { 749 $this->Lexer->addSpecialPattern($this->pattern,$mode,'entity'); 750 } 751 } 752 753 function getSort() { 754 return 260; 755 } 756} 757 758//------------------------------------------------------------------- 759// Implements the 640x480 replacement 760class Doku_Parser_Mode_multiplyentity extends Doku_Parser_Mode { 761 762 function connectTo($mode) { 763 764 $this->Lexer->addSpecialPattern( 765 '(?<=\b)(?:[1-9]|\d{2,})[xX]\d+(?=\b)',$mode,'multiplyentity' 766 ); 767 768 } 769 770 function getSort() { 771 return 270; 772 } 773} 774 775//------------------------------------------------------------------- 776class Doku_Parser_Mode_quotes extends Doku_Parser_Mode { 777 778 function connectTo($mode) { 779 global $conf; 780 781 $ws = '\s/\#~:+=&%@\-\x28\x29\]\[{}><"\''; // whitespace 782 $punc = ';,\.?!'; 783 784 if($conf['typography'] == 2){ 785 $this->Lexer->addSpecialPattern( 786 "(?<=^|[$ws])'(?=[^$ws$punc])",$mode,'singlequoteopening' 787 ); 788 $this->Lexer->addSpecialPattern( 789 "(?<=^|[^$ws]|[$punc])'(?=$|[$ws$punc])",$mode,'singlequoteclosing' 790 ); 791 $this->Lexer->addSpecialPattern( 792 "(?<=^|[^$ws$punc])'(?=$|[^$ws$punc])",$mode,'apostrophe' 793 ); 794 } 795 796 $this->Lexer->addSpecialPattern( 797 "(?<=^|[$ws])\"(?=[^$ws$punc])",$mode,'doublequoteopening' 798 ); 799 $this->Lexer->addSpecialPattern( 800 "\"",$mode,'doublequoteclosing' 801 ); 802 803 804 } 805 806 function getSort() { 807 return 280; 808 } 809} 810 811//------------------------------------------------------------------- 812class Doku_Parser_Mode_camelcaselink extends Doku_Parser_Mode { 813 814 function connectTo($mode) { 815 $this->Lexer->addSpecialPattern( 816 '\b[A-Z]+[a-z]+[A-Z][A-Za-z]*\b',$mode,'camelcaselink' 817 ); 818 } 819 820 function getSort() { 821 return 290; 822 } 823} 824 825//------------------------------------------------------------------- 826class Doku_Parser_Mode_internallink extends Doku_Parser_Mode { 827 828 function connectTo($mode) { 829 // Word boundaries? 830 $this->Lexer->addSpecialPattern("\[\[.+?\]\]",$mode,'internallink'); 831 } 832 833 function getSort() { 834 return 300; 835 } 836} 837 838//------------------------------------------------------------------- 839class Doku_Parser_Mode_media extends Doku_Parser_Mode { 840 841 function connectTo($mode) { 842 // Word boundaries? 843 $this->Lexer->addSpecialPattern("\{\{[^\}]+\}\}",$mode,'media'); 844 } 845 846 function getSort() { 847 return 320; 848 } 849} 850 851//------------------------------------------------------------------- 852class Doku_Parser_Mode_rss extends Doku_Parser_Mode { 853 854 function connectTo($mode) { 855 $this->Lexer->addSpecialPattern("\{\{rss>[^\}]+\}\}",$mode,'rss'); 856 } 857 858 function getSort() { 859 return 310; 860 } 861} 862 863//------------------------------------------------------------------- 864class Doku_Parser_Mode_externallink extends Doku_Parser_Mode { 865 var $schemes = array(); 866 var $patterns = array(); 867 868 function preConnect() { 869 if(count($this->patterns)) return; 870 871 $ltrs = '\w'; 872 $gunk = '/\#~:.?+=&%@!\-'; 873 $punc = '.:?\-;,'; 874 $host = $ltrs.$punc; 875 $any = $ltrs.$gunk.$punc; 876 877 $this->schemes = getSchemes(); 878 foreach ( $this->schemes as $scheme ) { 879 $this->patterns[] = '\b(?i)'.$scheme.'(?-i)://['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; 880 } 881 882 $this->patterns[] = '\b(?i)www?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; 883 $this->patterns[] = '\b(?i)ftp?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; 884 } 885 886 function connectTo($mode) { 887 888 foreach ( $this->patterns as $pattern ) { 889 $this->Lexer->addSpecialPattern($pattern,$mode,'externallink'); 890 } 891 } 892 893 function getSort() { 894 return 330; 895 } 896} 897 898//------------------------------------------------------------------- 899class Doku_Parser_Mode_filelink extends Doku_Parser_Mode { 900 901 var $pattern; 902 903 function preConnect() { 904 905 $ltrs = '\w'; 906 $gunk = '/\#~:.?+=&%@!\-'; 907 $punc = '.:?\-;,'; 908 $host = $ltrs.$punc; 909 $any = $ltrs.$gunk.$punc; 910 911 $this->pattern = '\b(?i)file(?-i)://['.$any.']+?['. 912 $punc.']*[^'.$any.']'; 913 } 914 915 function connectTo($mode) { 916 $this->Lexer->addSpecialPattern( 917 $this->pattern,$mode,'filelink'); 918 } 919 920 function getSort() { 921 return 360; 922 } 923} 924 925//------------------------------------------------------------------- 926class Doku_Parser_Mode_windowssharelink extends Doku_Parser_Mode { 927 928 var $pattern; 929 930 function preConnect() { 931 $this->pattern = "\\\\\\\\\w+?(?:\\\\[\w$]+)+"; 932 } 933 934 function connectTo($mode) { 935 $this->Lexer->addSpecialPattern( 936 $this->pattern,$mode,'windowssharelink'); 937 } 938 939 function getSort() { 940 return 350; 941 } 942} 943 944//------------------------------------------------------------------- 945class Doku_Parser_Mode_emaillink extends Doku_Parser_Mode { 946 947 function connectTo($mode) { 948 // pattern below is defined in inc/mail.php 949 $this->Lexer->addSpecialPattern('<'.PREG_PATTERN_VALID_EMAIL.'>',$mode,'emaillink'); 950 } 951 952 function getSort() { 953 return 340; 954 } 955} 956 957 958//Setup VIM: ex: et ts=4 enc=utf-8 : 959