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