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