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'=>'//(?=[^\x00]*[^:]//)', //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('[\t ]+','table'); 469 $this->Lexer->addPattern('\^','table'); 470 $this->Lexer->addPattern('\|','table'); 471 $this->Lexer->addExitPattern('\n','table'); 472 } 473 474 function getSort() { 475 return 60; 476 } 477} 478 479//------------------------------------------------------------------- 480class Doku_Parser_Mode_unformatted extends Doku_Parser_Mode { 481 482 function connectTo($mode) { 483 $this->Lexer->addEntryPattern('<nowiki>(?=.*\x3C/nowiki\x3E)',$mode,'unformatted'); 484 $this->Lexer->addEntryPattern('%%(?=.*%%)',$mode,'unformattedalt'); 485 } 486 487 function postConnect() { 488 $this->Lexer->addExitPattern('</nowiki>','unformatted'); 489 $this->Lexer->addExitPattern('%%','unformattedalt'); 490 $this->Lexer->mapHandler('unformattedalt','unformatted'); 491 } 492 493 function getSort() { 494 return 170; 495 } 496} 497 498//------------------------------------------------------------------- 499class Doku_Parser_Mode_php extends Doku_Parser_Mode { 500 501 function connectTo($mode) { 502 $this->Lexer->addEntryPattern('<php>(?=.*\x3C/php\x3E)',$mode,'php'); 503 } 504 505 function postConnect() { 506 $this->Lexer->addExitPattern('</php>','php'); 507 } 508 509 function getSort() { 510 return 180; 511 } 512} 513 514//------------------------------------------------------------------- 515class Doku_Parser_Mode_html extends Doku_Parser_Mode { 516 517 function connectTo($mode) { 518 $this->Lexer->addEntryPattern('<html>(?=.*\x3C/html\x3E)',$mode,'html'); 519 } 520 521 function postConnect() { 522 $this->Lexer->addExitPattern('</html>','html'); 523 } 524 525 function getSort() { 526 return 190; 527 } 528} 529 530//------------------------------------------------------------------- 531class Doku_Parser_Mode_preformatted extends Doku_Parser_Mode { 532 533 function connectTo($mode) { 534 // Has hard coded awareness of lists... 535 $this->Lexer->addEntryPattern('\n (?![\*\-])',$mode,'preformatted'); 536 $this->Lexer->addEntryPattern('\n\t(?![\*\-])',$mode,'preformatted'); 537 538 // How to effect a sub pattern with the Lexer! 539 $this->Lexer->addPattern('\n ','preformatted'); 540 $this->Lexer->addPattern('\n\t','preformatted'); 541 542 } 543 544 function postConnect() { 545 $this->Lexer->addExitPattern('\n','preformatted'); 546 } 547 548 function getSort() { 549 return 20; 550 } 551} 552 553//------------------------------------------------------------------- 554class Doku_Parser_Mode_code extends Doku_Parser_Mode { 555 556 function connectTo($mode) { 557 $this->Lexer->addEntryPattern('<code(?=.*\x3C/code\x3E)',$mode,'code'); 558 } 559 560 function postConnect() { 561 $this->Lexer->addExitPattern('</code>','code'); 562 } 563 564 function getSort() { 565 return 200; 566 } 567} 568 569//------------------------------------------------------------------- 570class Doku_Parser_Mode_file extends Doku_Parser_Mode { 571 572 function connectTo($mode) { 573 $this->Lexer->addEntryPattern('<file>(?=.*\x3C/file\x3E)',$mode,'file'); 574 } 575 576 function postConnect() { 577 $this->Lexer->addExitPattern('</file>','file'); 578 } 579 580 function getSort() { 581 return 210; 582 } 583} 584 585//------------------------------------------------------------------- 586class Doku_Parser_Mode_quote extends Doku_Parser_Mode { 587 588 function Doku_Parser_Mode_quote() { 589 global $PARSER_MODES; 590 591 $this->allowedModes = array_merge ( 592 $PARSER_MODES['formatting'], 593 $PARSER_MODES['substition'], 594 $PARSER_MODES['disabled'], 595 $PARSER_MODES['protected'] #XXX new 596 ); 597 #$this->allowedModes[] = 'footnote'; 598 #$this->allowedModes[] = 'preformatted'; 599 #$this->allowedModes[] = 'unformatted'; 600 } 601 602 function connectTo($mode) { 603 $this->Lexer->addEntryPattern('\n>{1,}',$mode,'quote'); 604 } 605 606 function postConnect() { 607 $this->Lexer->addPattern('\n>{1,}','quote'); 608 $this->Lexer->addExitPattern('\n','quote'); 609 } 610 611 function getSort() { 612 return 220; 613 } 614} 615 616//------------------------------------------------------------------- 617class Doku_Parser_Mode_acronym extends Doku_Parser_Mode { 618 // A list 619 var $acronyms = array(); 620 var $pattern = ''; 621 622 function Doku_Parser_Mode_acronym($acronyms) { 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//------------------------------------------------------------------- 648class Doku_Parser_Mode_smiley extends Doku_Parser_Mode { 649 // A list 650 var $smileys = array(); 651 var $pattern = ''; 652 653 function Doku_Parser_Mode_smiley($smileys) { 654 $this->smileys = $smileys; 655 } 656 657 function preConnect() { 658 if(!count($this->smileys)) return; 659 660 $sep = ''; 661 foreach ( $this->smileys as $smiley ) { 662 $this->pattern .= $sep.Doku_Lexer_Escape($smiley); 663 $sep = '|'; 664 } 665 } 666 667 function connectTo($mode) { 668 if(!count($this->smileys)) return; 669 670 if ( strlen($this->pattern) > 0 ) { 671 $this->Lexer->addSpecialPattern($this->pattern,$mode,'smiley'); 672 } 673 } 674 675 function getSort() { 676 return 230; 677 } 678} 679 680//------------------------------------------------------------------- 681class Doku_Parser_Mode_wordblock extends Doku_Parser_Mode { 682 // A list 683 var $badwords = array(); 684 var $pattern = ''; 685 686 function Doku_Parser_Mode_wordblock($badwords) { 687 $this->badwords = $badwords; 688 } 689 690 function preConnect() { 691 692 if ( count($this->badwords) == 0 ) { 693 return; 694 } 695 696 $sep = ''; 697 foreach ( $this->badwords as $badword ) { 698 $this->pattern .= $sep.'(?<=\b)(?i)'.Doku_Lexer_Escape($badword).'(?-i)(?=\b)'; 699 $sep = '|'; 700 } 701 702 } 703 704 function connectTo($mode) { 705 if ( strlen($this->pattern) > 0 ) { 706 $this->Lexer->addSpecialPattern($this->pattern,$mode,'wordblock'); 707 } 708 } 709 710 function getSort() { 711 return 250; 712 } 713} 714 715//------------------------------------------------------------------- 716/** 717* @TODO Quotes and 640x480 are not supported - just straight replacements here 718*/ 719class Doku_Parser_Mode_entity extends Doku_Parser_Mode { 720 // A list 721 var $entities = array(); 722 var $pattern = ''; 723 724 function Doku_Parser_Mode_entity($entities) { 725 $this->entities = $entities; 726 } 727 728 function preConnect() { 729 if(!count($this->entities)) return; 730 731 $sep = ''; 732 foreach ( $this->entities as $entity ) { 733 $this->pattern .= $sep.Doku_Lexer_Escape($entity); 734 $sep = '|'; 735 } 736 } 737 738 function connectTo($mode) { 739 if(!count($this->entities)) return; 740 741 if ( strlen($this->pattern) > 0 ) { 742 $this->Lexer->addSpecialPattern($this->pattern,$mode,'entity'); 743 } 744 } 745 746 function getSort() { 747 return 260; 748 } 749} 750 751//------------------------------------------------------------------- 752// Implements the 640x480 replacement 753class Doku_Parser_Mode_multiplyentity extends Doku_Parser_Mode { 754 755 function connectTo($mode) { 756 757 $this->Lexer->addSpecialPattern( 758 '(?<=\b)\d+[xX]\d+(?=\b)',$mode,'multiplyentity' 759 ); 760 761 } 762 763 function getSort() { 764 return 270; 765 } 766} 767 768//------------------------------------------------------------------- 769class Doku_Parser_Mode_quotes extends Doku_Parser_Mode { 770 771 function connectTo($mode) { 772 773 $this->Lexer->addSpecialPattern( 774 '(?<=^|\s)\'(?=\S)',$mode,'singlequoteopening' 775 ); 776 $this->Lexer->addSpecialPattern( 777 '(?<=^|\S)\'',$mode,'singlequoteclosing' 778 ); 779 $this->Lexer->addSpecialPattern( 780 '(?<=^|\s)"(?=\S)',$mode,'doublequoteopening' 781 ); 782 $this->Lexer->addSpecialPattern( 783 '(?<=^|\S)"',$mode,'doublequoteclosing' 784 ); 785 786 } 787 788 function getSort() { 789 return 280; 790 } 791} 792 793//------------------------------------------------------------------- 794class Doku_Parser_Mode_camelcaselink extends Doku_Parser_Mode { 795 796 function connectTo($mode) { 797 $this->Lexer->addSpecialPattern( 798 '\b[A-Z]+[a-z]+[A-Z][A-Za-z]*\b',$mode,'camelcaselink' 799 ); 800 } 801 802 function getSort() { 803 return 290; 804 } 805} 806 807//------------------------------------------------------------------- 808class Doku_Parser_Mode_internallink extends Doku_Parser_Mode { 809 810 function connectTo($mode) { 811 // Word boundaries? 812 $this->Lexer->addSpecialPattern("\[\[.+?\]\]",$mode,'internallink'); 813 } 814 815 function getSort() { 816 return 300; 817 } 818} 819 820//------------------------------------------------------------------- 821class Doku_Parser_Mode_media extends Doku_Parser_Mode { 822 823 function connectTo($mode) { 824 // Word boundaries? 825 $this->Lexer->addSpecialPattern("\{\{[^\}]+\}\}",$mode,'media'); 826 } 827 828 function getSort() { 829 return 320; 830 } 831} 832 833//------------------------------------------------------------------- 834class Doku_Parser_Mode_rss extends Doku_Parser_Mode { 835 836 function connectTo($mode) { 837 $this->Lexer->addSpecialPattern("\{\{rss>[^\}]+\}\}",$mode,'rss'); 838 } 839 840 function getSort() { 841 return 310; 842 } 843} 844 845//------------------------------------------------------------------- 846class Doku_Parser_Mode_externallink extends Doku_Parser_Mode { 847 var $schemes = array('http','https','telnet','gopher','wais','ftp','ed2k','irc','ldap'); 848 var $patterns = array(); 849 850 function preConnect() { 851 852 $ltrs = '\w'; 853 $gunk = '/\#~:.?+=&%@!\-'; 854 $punc = '.:?\-;,'; 855 $host = $ltrs.$punc; 856 $any = $ltrs.$gunk.$punc; 857 858 foreach ( $this->schemes as $scheme ) { 859 $this->patterns[] = '\b(?i)'.$scheme.'(?-i)://['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; 860 } 861 862 $this->patterns[] = '\b(?i)www?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; 863 $this->patterns[] = '\b(?i)ftp?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])'; 864 865 } 866 867 function connectTo($mode) { 868 foreach ( $this->patterns as $pattern ) { 869 $this->Lexer->addSpecialPattern($pattern,$mode,'externallink'); 870 } 871 } 872 873 function getSort() { 874 return 330; 875 } 876} 877 878//------------------------------------------------------------------- 879class Doku_Parser_Mode_filelink extends Doku_Parser_Mode { 880 881 var $pattern; 882 883 function preConnect() { 884 885 $ltrs = '\w'; 886 $gunk = '/\#~:.?+=&%@!\-'; 887 $punc = '.:?\-;,'; 888 $host = $ltrs.$punc; 889 $any = $ltrs.$gunk.$punc; 890 891 $this->pattern = '\b(?i)file(?-i)://['.$any.']+?['. 892 $punc.']*[^'.$any.']'; 893 } 894 895 function connectTo($mode) { 896 $this->Lexer->addSpecialPattern( 897 $this->pattern,$mode,'filelink'); 898 } 899 900 function getSort() { 901 return 360; 902 } 903} 904 905//------------------------------------------------------------------- 906class Doku_Parser_Mode_windowssharelink extends Doku_Parser_Mode { 907 908 var $pattern; 909 910 function preConnect() { 911 $this->pattern = "\\\\\\\\\w+?(?:\\\\[\w$]+)+"; 912 } 913 914 function connectTo($mode) { 915 $this->Lexer->addSpecialPattern( 916 $this->pattern,$mode,'windowssharelink'); 917 } 918 919 function getSort() { 920 return 350; 921 } 922} 923 924//------------------------------------------------------------------- 925class Doku_Parser_Mode_emaillink extends Doku_Parser_Mode { 926 927 function connectTo($mode) { 928 $this->Lexer->addSpecialPattern("<[\w0-9\-_.]+?@[\w\-]+\.[\w\-\.]+\.*[\w]+>",$mode,'emaillink'); 929 } 930 931 function getSort() { 932 return 340; 933 } 934} 935 936 937//Setup VIM: ex: et ts=4 enc=utf-8 : 938