1<?php 2 3if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); 4 5require_once DOKU_INC . 'inc/parser/lexer.php'; 6require_once DOKU_INC . 'inc/parser/handler.php'; 7 8 9/** 10 * Define various types of modes used by the parser - they are used to 11 * populate the list of modes another mode accepts 12 */ 13global $PARSER_MODES; 14$PARSER_MODES = array( 15 // containers are complex modes that can contain many other modes 16 // hr breaks the principle but they shouldn't be used in tables / lists 17 // so they are put here 18 'container' => array('listblock','table','quote','hr'), 19 20 // some mode are allowed inside the base mode only 21 'baseonly' => array('header'), 22 23 // modes for styling text -- footnote behaves similar to styling 24 'formatting' => array('strong', 'emphasis', 'underline', 'monospace', 25 'subscript', 'superscript', 'deleted', 'footnote'), 26 27 // modes where the token is simply replaced - they can not contain any 28 // other modes 29 'substition' => array('acronym','smiley','wordblock','entity', 30 'camelcaselink', 'internallink','media', 31 'externallink','linebreak','emaillink', 32 'windowssharelink','filelink','notoc', 33 'nocache','multiplyentity','quotes','rss'), 34 35 // modes which have a start and end token but inside which 36 // no other modes should be applied 37 'protected' => array('preformatted','code','file','php','html'), 38 39 // inside this mode no wiki markup should be applied but lineendings 40 // and whitespace isn't preserved 41 'disabled' => array('unformatted'), 42 43 // used to mark paragraph boundaries 44 'paragraphs' => array('eol') 45); 46 47//------------------------------------------------------------------- 48 49/** 50* Sets up the Lexer with modes and points it to the Handler 51* For an intro to the Lexer see: wiki:parser 52*/ 53class Doku_Parser { 54 55 var $Handler; 56 57 var $Lexer; 58 59 var $modes = array(); 60 61 var $connected = FALSE; 62 63 function addBaseMode(& $BaseMode) { 64 $this->modes['base'] = & $BaseMode; 65 if ( !$this->Lexer ) { 66 $this->Lexer = & new Doku_Lexer($this->Handler,'base', TRUE); 67 } 68 $this->modes['base']->Lexer = & $this->Lexer; 69 } 70 71 /** 72 * PHP preserves order of associative elements 73 * Mode sequence is important 74 */ 75 function addMode($name, & $Mode) { 76 if ( !isset($this->modes['base']) ) { 77 $this->addBaseMode(new Doku_Parser_Mode_base()); 78 } 79 $Mode->Lexer = & $this->Lexer; 80 $this->modes[$name] = & $Mode; 81 } 82 83 function connectModes() { 84 85 if ( $this->connected ) { 86 return; 87 } 88 89 foreach ( array_keys($this->modes) as $mode ) { 90 91 // Base isn't connected to anything 92 if ( $mode == 'base' ) { 93 continue; 94 } 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 130 * used to reduce the effort required to register 131 * modes with the Lexer. For performance these 132 * could all be eliminated later perhaps, or 133 * the Parser could be serialized to a file once 134 * all modes are registered 135 * 136 * @author Harry Fuecks <hfuecks@gmail.com> 137*/ 138class Doku_Parser_Mode { 139 140 var $Lexer; 141 142 var $allowedModes = array(); 143 144 // returns a number used to determine in which order modes are added 145 function getSort() { 146 trigger_error('getSort() not implemented in '.get_class($this), E_USER_WARNING); 147 } 148 149 // Called before any calls to connectTo 150 function preConnect() {} 151 152 // Connects the mode 153 function connectTo($mode) {} 154 155 // Called after all calls to connectTo 156 function postConnect() {} 157 158 function accepts($mode) { 159 return in_array($mode, $this->allowedModes ); 160 } 161 162} 163 164//------------------------------------------------------------------- 165class Doku_Parser_Mode_base extends Doku_Parser_Mode { 166 167 function Doku_Parser_Mode_base() { 168 global $PARSER_MODES; 169 170 $this->allowedModes = array_merge ( 171 $PARSER_MODES['container'], 172 $PARSER_MODES['baseonly'], 173 $PARSER_MODES['paragraphs'], 174 $PARSER_MODES['formatting'], 175 $PARSER_MODES['substition'], 176 $PARSER_MODES['protected'], 177 $PARSER_MODES['disabled'] 178 ); 179 } 180 181 function getSort() { 182 return 0; 183 } 184} 185 186//------------------------------------------------------------------- 187class Doku_Parser_Mode_footnote extends Doku_Parser_Mode { 188 189 function Doku_Parser_Mode_footnote() { 190 global $PARSER_MODES; 191 192 $this->allowedModes = array_merge ( 193 $PARSER_MODES['container'], 194 $PARSER_MODES['formatting'], 195 $PARSER_MODES['substition'], 196 $PARSER_MODES['protected'], 197 $PARSER_MODES['disabled'] 198 ); 199 200 } 201 202 function connectTo($mode) { 203 $this->Lexer->addEntryPattern( 204 '\x28\x28(?=.*\x29\x29)',$mode,'footnote' 205 ); 206 } 207 208 function postConnect() { 209 $this->Lexer->addExitPattern( 210 '\x29\x29','footnote' 211 ); 212 213 } 214 215 function getSort() { 216 return 150; 217 } 218} 219 220//------------------------------------------------------------------- 221class Doku_Parser_Mode_header extends Doku_Parser_Mode { 222 223 function preConnect() { 224 //we're not picky about the closing ones, two are enough 225 226 // Header 1 is special case - match 6 or more 227 $this->Lexer->addSpecialPattern( 228 '[ \t]*={6,}[^\n]+={2,}[ \t]*(?=\n)', 229 'base', 230 'header' 231 ); 232 233 // For the rest, match exactly 234 for ( $i = 5; $i > 1; $i--) { 235 $this->Lexer->addSpecialPattern( 236 '[ \t]*={'.$i.'}[^\n]+={2,}[ \t]*(?=\n)', 237 'base', 238 'header' 239 ); 240 } 241 } 242 243 function getSort() { 244 return 50; 245 } 246} 247 248//------------------------------------------------------------------- 249class Doku_Parser_Mode_notoc extends Doku_Parser_Mode { 250 251 function connectTo($mode) { 252 $this->Lexer->addSpecialPattern('~~NOTOC~~',$mode,'notoc'); 253 } 254 255 function getSort() { 256 return 30; 257 } 258} 259 260//------------------------------------------------------------------- 261class Doku_Parser_Mode_nocache extends Doku_Parser_Mode { 262 263 function connectTo($mode) { 264 $this->Lexer->addSpecialPattern('~~NOCACHE~~',$mode,'nocache'); 265 } 266 267 function getSort() { 268 return 40; 269 } 270} 271 272//------------------------------------------------------------------- 273class Doku_Parser_Mode_linebreak extends Doku_Parser_Mode { 274 275 function connectTo($mode) { 276 $this->Lexer->addSpecialPattern('\x5C{2}(?=\s)',$mode,'linebreak'); 277 } 278 279 function getSort() { 280 return 140; 281 } 282} 283 284//------------------------------------------------------------------- 285class Doku_Parser_Mode_eol extends Doku_Parser_Mode { 286 287 function connectTo($mode) { 288 $badModes = array('listblock','table'); 289 if ( in_array($mode, $badModes) ) { 290 return; 291 } 292 $this->Lexer->addSpecialPattern('\n',$mode,'eol'); 293 } 294 295 function getSort() { 296 return 370; 297 } 298} 299 300//------------------------------------------------------------------- 301class Doku_Parser_Mode_hr extends Doku_Parser_Mode { 302 303 function connectTo($mode) { 304 $this->Lexer->addSpecialPattern('\n[ \t]*-{4,}[ \t]*(?=\n)',$mode,'hr'); 305 } 306 307 function getSort() { 308 return 160; 309 } 310} 311 312//------------------------------------------------------------------- 313class Doku_Parser_Mode_formatting extends Doku_Parser_Mode { 314 var $type; 315 316 var $formatting = array ( 317 'strong' => array ( 318 'entry'=>'\*\*(?=.*\*\*)', 319 'exit'=>'\*\*', 320 'sort'=>70 321 ), 322 323 'emphasis'=> array ( 324 'entry'=>'//(?=.*(?<!http:|ftp:)//)', //hack for bug #384 325 'exit'=>'//', 326 'sort'=>80 327 ), 328 329 'underline'=> array ( 330 'entry'=>'__(?=.*__)', 331 'exit'=>'__', 332 'sort'=>90 333 ), 334 335 'monospace'=> array ( 336 'entry'=>'\x27\x27(?=.*\x27\x27)', 337 'exit'=>'\x27\x27', 338 'sort'=>100 339 ), 340 341 'subscript'=> array ( 342 'entry'=>'<sub>(?=.*\x3C/sub\x3E)', 343 'exit'=>'</sub>', 344 'sort'=>110 345 ), 346 347 'superscript'=> array ( 348 'entry'=>'<sup>(?=.*\x3C/sup\x3E)', 349 'exit'=>'</sup>', 350 'sort'=>120 351 ), 352 353 'deleted'=> array ( 354 'entry'=>'<del>(?=.*\x3C/del\x3E)', 355 'exit'=>'</del>', 356 'sort'=>130 357 ), 358 ); 359 360 function Doku_Parser_Mode_formatting($type) { 361 global $PARSER_MODES; 362 363 if ( !array_key_exists($type, $this->formatting) ) { 364 trigger_error('Invalid formatting type '.$type, E_USER_WARNING); 365 } 366 367 $this->type = $type; 368 369 // formatting may contain other formatting but not it self 370 $modes = $PARSER_MODES['formatting']; 371 $key = array_search($type, $modes); 372 if ( is_int($key) ) { 373 unset($modes[$key]); 374 } 375 376 $this->allowedModes = array_merge ( 377 $modes, 378 $PARSER_MODES['substition'], 379 $PARSER_MODES['disabled'] 380 ); 381 } 382 383 function connectTo($mode) { 384 385 // Can't nest formatting in itself 386 if ( $mode == $this->type ) { 387 return; 388 } 389 390 $this->Lexer->addEntryPattern( 391 $this->formatting[$this->type]['entry'], 392 $mode, 393 $this->type 394 ); 395 } 396 397 function postConnect() { 398 399 $this->Lexer->addExitPattern( 400 $this->formatting[$this->type]['exit'], 401 $this->type 402 ); 403 404 } 405 406 function getSort() { 407 return $this->formatting[$this->type]['sort']; 408 } 409} 410 411//------------------------------------------------------------------- 412class Doku_Parser_Mode_listblock extends Doku_Parser_Mode { 413 414 function Doku_Parser_Mode_listblock() { 415 global $PARSER_MODES; 416 417 $this->allowedModes = array_merge ( 418 $PARSER_MODES['formatting'], 419 $PARSER_MODES['substition'], 420 $PARSER_MODES['disabled'], 421 $PARSER_MODES['protected'] #XXX new 422 ); 423 424 // $this->allowedModes[] = 'footnote'; 425 } 426 427 function connectTo($mode) { 428 $this->Lexer->addEntryPattern('\n {2,}[\-\*]',$mode,'listblock'); 429 $this->Lexer->addEntryPattern('\n\t{1,}[\-\*]',$mode,'listblock'); 430 431 $this->Lexer->addPattern('\n {2,}[\-\*]','listblock'); 432 $this->Lexer->addPattern('\n\t{1,}[\-\*]','listblock'); 433 434 } 435 436 function postConnect() { 437 $this->Lexer->addExitPattern('\n','listblock'); 438 } 439 440 function getSort() { 441 return 10; 442 } 443} 444 445//------------------------------------------------------------------- 446class Doku_Parser_Mode_table extends Doku_Parser_Mode { 447 448 function Doku_Parser_Mode_table() { 449 global $PARSER_MODES; 450 451 $this->allowedModes = array_merge ( 452 $PARSER_MODES['formatting'], 453 $PARSER_MODES['substition'], 454 $PARSER_MODES['disabled'], 455 $PARSER_MODES['protected'] 456 ); 457 } 458 459 function connectTo($mode) { 460 $this->Lexer->addEntryPattern('\n\^',$mode,'table'); 461 $this->Lexer->addEntryPattern('\n\|',$mode,'table'); 462 } 463 464 function postConnect() { 465 $this->Lexer->addPattern('\n\^','table'); 466 $this->Lexer->addPattern('\n\|','table'); 467 $this->Lexer->addPattern(' {2,}','table'); 468 $this->Lexer->addPattern('\^','table'); 469 $this->Lexer->addPattern('\|','table'); 470 $this->Lexer->addExitPattern('\n','table'); 471 } 472 473 function getSort() { 474 return 60; 475 } 476} 477 478//------------------------------------------------------------------- 479class Doku_Parser_Mode_unformatted extends Doku_Parser_Mode { 480 481 function connectTo($mode) { 482 $this->Lexer->addEntryPattern('<nowiki>(?=.*\x3C/nowiki\x3E)',$mode,'unformatted'); 483 $this->Lexer->addEntryPattern('%%(?=.*%%)',$mode,'unformattedalt'); 484 } 485 486 function postConnect() { 487 $this->Lexer->addExitPattern('</nowiki>','unformatted'); 488 $this->Lexer->addExitPattern('%%','unformattedalt'); 489 $this->Lexer->mapHandler('unformattedalt','unformatted'); 490 } 491 492 function getSort() { 493 return 170; 494 } 495} 496 497//------------------------------------------------------------------- 498class Doku_Parser_Mode_php extends Doku_Parser_Mode { 499 500 function connectTo($mode) { 501 $this->Lexer->addEntryPattern('<php>(?=.*\x3C/php\x3E)',$mode,'php'); 502 } 503 504 function postConnect() { 505 $this->Lexer->addExitPattern('</php>','php'); 506 } 507 508 function getSort() { 509 return 180; 510 } 511} 512 513//------------------------------------------------------------------- 514class Doku_Parser_Mode_html extends Doku_Parser_Mode { 515 516 function connectTo($mode) { 517 $this->Lexer->addEntryPattern('<html>(?=.*\x3C/html\x3E)',$mode,'html'); 518 } 519 520 function postConnect() { 521 $this->Lexer->addExitPattern('</html>','html'); 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(?=.*\x3C/code\x3E)',$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>(?=.*\x3C/file\x3E)',$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 $this->acronyms = $acronyms; 623 } 624 625 function preConnect() { 626 $sep = ''; 627 foreach ( $this->acronyms as $acronym ) { 628 $this->pattern .= $sep.'(?<=\b)'.Doku_Lexer_Escape($acronym).'(?=\b)'; 629 $sep = '|'; 630 } 631 } 632 633 function connectTo($mode) { 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//------------------------------------------------------------------- 645class Doku_Parser_Mode_smiley extends Doku_Parser_Mode { 646 // A list 647 var $smileys = array(); 648 var $pattern = ''; 649 650 function Doku_Parser_Mode_smiley($smileys) { 651 $this->smileys = $smileys; 652 } 653 654 function preConnect() { 655 $sep = ''; 656 foreach ( $this->smileys as $smiley ) { 657 $this->pattern .= $sep.Doku_Lexer_Escape($smiley); 658 $sep = '|'; 659 } 660 } 661 662 function connectTo($mode) { 663 if ( strlen($this->pattern) > 0 ) { 664 $this->Lexer->addSpecialPattern($this->pattern,$mode,'smiley'); 665 } 666 } 667 668 function getSort() { 669 return 230; 670 } 671} 672 673//------------------------------------------------------------------- 674class Doku_Parser_Mode_wordblock extends Doku_Parser_Mode { 675 // A list 676 var $badwords = array(); 677 var $pattern = ''; 678 679 function Doku_Parser_Mode_wordblock($badwords) { 680 $this->badwords = $badwords; 681 } 682 683 function preConnect() { 684 685 if ( count($this->badwords) == 0 ) { 686 return; 687 } 688 689 $sep = ''; 690 foreach ( $this->badwords as $badword ) { 691 $this->pattern .= $sep.'(?<=\b)(?i)'.Doku_Lexer_Escape($badword).'(?-i)(?=\b)'; 692 $sep = '|'; 693 } 694 695 } 696 697 function connectTo($mode) { 698 if ( strlen($this->pattern) > 0 ) { 699 $this->Lexer->addSpecialPattern($this->pattern,$mode,'wordblock'); 700 } 701 } 702 703 function getSort() { 704 return 250; 705 } 706} 707 708//------------------------------------------------------------------- 709/** 710* @TODO Quotes and 640x480 are not supported - just straight replacements here 711*/ 712class Doku_Parser_Mode_entity extends Doku_Parser_Mode { 713 // A list 714 var $entities = array(); 715 var $pattern = ''; 716 717 function Doku_Parser_Mode_entity($entities) { 718 $this->entities = $entities; 719 } 720 721 function preConnect() { 722 $sep = ''; 723 foreach ( $this->entities as $entity ) { 724 $this->pattern .= $sep.Doku_Lexer_Escape($entity); 725 $sep = '|'; 726 } 727 } 728 729 function connectTo($mode) { 730 if ( strlen($this->pattern) > 0 ) { 731 $this->Lexer->addSpecialPattern($this->pattern,$mode,'entity'); 732 } 733 } 734 735 function getSort() { 736 return 260; 737 } 738} 739 740//------------------------------------------------------------------- 741// Implements the 640x480 replacement 742class Doku_Parser_Mode_multiplyentity extends Doku_Parser_Mode { 743 744 function connectTo($mode) { 745 746 $this->Lexer->addSpecialPattern( 747 '(?<=\b)\d+[xX]\d+(?=\b)',$mode,'multiplyentity' 748 ); 749 750 } 751 752 function getSort() { 753 return 270; 754 } 755} 756 757//------------------------------------------------------------------- 758class Doku_Parser_Mode_quotes extends Doku_Parser_Mode { 759 760 function connectTo($mode) { 761 762 $this->Lexer->addSpecialPattern( 763 '(?<=^|\s)\'(?=\S)',$mode,'singlequoteopening' 764 ); 765 $this->Lexer->addSpecialPattern( 766 '(?<=^|\S)\'',$mode,'singlequoteclosing' 767 ); 768 $this->Lexer->addSpecialPattern( 769 '(?<=^|\s)"(?=\S)',$mode,'doublequoteopening' 770 ); 771 $this->Lexer->addSpecialPattern( 772 '(?<=^|\S)"',$mode,'doublequoteclosing' 773 ); 774 775 } 776 777 function getSort() { 778 return 280; 779 } 780} 781 782//------------------------------------------------------------------- 783class Doku_Parser_Mode_camelcaselink extends Doku_Parser_Mode { 784 785 function connectTo($mode) { 786 $this->Lexer->addSpecialPattern( 787 '\b[A-Z]+[a-z]+[A-Z][A-Za-z]*\b',$mode,'camelcaselink' 788 ); 789 } 790 791 function getSort() { 792 return 290; 793 } 794} 795 796//------------------------------------------------------------------- 797class Doku_Parser_Mode_internallink extends Doku_Parser_Mode { 798 799 function connectTo($mode) { 800 // Word boundaries? 801 $this->Lexer->addSpecialPattern("\[\[.+?\]\]",$mode,'internallink'); 802 } 803 804 function getSort() { 805 return 300; 806 } 807} 808 809//------------------------------------------------------------------- 810class Doku_Parser_Mode_media extends Doku_Parser_Mode { 811 812 function connectTo($mode) { 813 // Word boundaries? 814 $this->Lexer->addSpecialPattern("\{\{[^\}]+\}\}",$mode,'media'); 815 } 816 817 function getSort() { 818 return 320; 819 } 820} 821 822//------------------------------------------------------------------- 823class Doku_Parser_Mode_rss extends Doku_Parser_Mode { 824 825 function connectTo($mode) { 826 $this->Lexer->addSpecialPattern("\{\{rss>[^\}]+\}\}",$mode,'rss'); 827 } 828 829 function getSort() { 830 return 310; 831 } 832} 833 834//------------------------------------------------------------------- 835class Doku_Parser_Mode_externallink extends Doku_Parser_Mode { 836 var $schemes = array('http','https','telnet','gopher','wais','ftp','ed2k','irc'); 837 var $patterns = array(); 838 839 function preConnect() { 840 841 $ltrs = '\w'; 842 $gunk = '/\#~:.?+=&%@!\-'; 843 $punc = '.:?\-;,'; 844 $host = $ltrs.$punc; 845 $any = $ltrs.$gunk.$punc; 846 847 foreach ( $this->schemes as $scheme ) { 848 $this->patterns[] = '\b(?i)'.$scheme.'(?-i)://['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; 849 } 850 851 $this->patterns[] = '\b(?i)www?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; 852 $this->patterns[] = '\b(?i)ftp?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; 853 854 } 855 856 function connectTo($mode) { 857 foreach ( $this->patterns as $pattern ) { 858 $this->Lexer->addSpecialPattern($pattern,$mode,'externallink'); 859 } 860 } 861 862 function getSort() { 863 return 330; 864 } 865} 866 867//------------------------------------------------------------------- 868class Doku_Parser_Mode_filelink extends Doku_Parser_Mode { 869 870 var $pattern; 871 872 function preConnect() { 873 874 $ltrs = '\w'; 875 $gunk = '/\#~:.?+=&%@!\-'; 876 $punc = '.:?\-;,'; 877 $host = $ltrs.$punc; 878 $any = $ltrs.$gunk.$punc; 879 880 $this->pattern = '\b(?i)file(?-i)://['.$any.']+?['. 881 $punc.']*[^'.$any.']'; 882 } 883 884 function connectTo($mode) { 885 $this->Lexer->addSpecialPattern( 886 $this->pattern,$mode,'filelink'); 887 } 888 889 function getSort() { 890 return 360; 891 } 892} 893 894//------------------------------------------------------------------- 895class Doku_Parser_Mode_windowssharelink extends Doku_Parser_Mode { 896 897 var $pattern; 898 899 function preConnect() { 900 $this->pattern = "\\\\\\\\\w+?(?:\\\\[\w$]+)+"; 901 } 902 903 function connectTo($mode) { 904 $this->Lexer->addSpecialPattern( 905 $this->pattern,$mode,'windowssharelink'); 906 } 907 908 function getSort() { 909 return 350; 910 } 911} 912 913//------------------------------------------------------------------- 914class Doku_Parser_Mode_emaillink extends Doku_Parser_Mode { 915 916 function connectTo($mode) { 917 $this->Lexer->addSpecialPattern("<[\w0-9\-_.]+?@[\w\-]+\.[\w\-\.]+\.*[\w]+>",$mode,'emaillink'); 918 } 919 920 function getSort() { 921 return 340; 922 } 923} 924 925 926//Setup VIM: ex: et ts=4 enc=utf-8 : 927