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