xref: /dokuwiki/inc/parser/parser.php (revision 6f0c5dbf635314087f00cf0b7ca387effec492b8)
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/**
11* Sets up the Lexer with modes and points it to the Handler
12* For an intro to the Lexer see: wiki:parser
13*/
14class Doku_Parser {
15
16    var $Handler;
17
18    var $Lexer;
19
20    var $modes = array();
21
22    var $connected = FALSE;
23
24    function addBaseMode(& $BaseMode) {
25        $this->modes['base'] = & $BaseMode;
26        if ( !$this->Lexer ) {
27            $this->Lexer = & new Doku_Lexer($this->Handler,'base', TRUE);
28        }
29        $this->modes['base']->Lexer = & $this->Lexer;
30    }
31
32    /**
33    * PHP preserves order of associative elements
34    * Mode sequence is important
35    */
36    function addMode($name, & $Mode) {
37        if ( !isset($this->modes['base']) ) {
38            $this->addBaseMode(new Doku_Parser_Mode_Base());
39        }
40        $Mode->Lexer = & $this->Lexer;
41        $this->modes[$name] = & $Mode;
42    }
43
44    function connectModes() {
45
46        if ( $this->connected ) {
47            return;
48        }
49
50        foreach ( array_keys($this->modes) as $mode ) {
51
52            // Base isn't connected to anything
53            if ( $mode == 'base' ) {
54                continue;
55            }
56
57            $this->modes[$mode]->preConnect();
58
59            foreach ( array_keys($this->modes) as $cm ) {
60
61                if ( $this->modes[$cm]->accepts($mode) ) {
62                    $this->modes[$mode]->connectTo($cm);
63                }
64
65            }
66
67            $this->modes[$mode]->postConnect();
68        }
69
70        $this->connected = TRUE;
71    }
72
73    function parse($doc) {
74        if ( $this->Lexer ) {
75            $this->connectModes();
76            // Normalize CRs and pad doc
77            $doc = "\n".str_replace("\r\n","\n",$doc)."\n";
78            $this->Lexer->parse($doc);
79            $this->Handler->_finalize();
80            return $this->Handler->calls;
81        } else {
82            return FALSE;
83        }
84    }
85
86}
87
88//-------------------------------------------------------------------
89/**
90* This class and all the subclasses below are
91* used to reduce the effort required to register
92* modes with the Lexer. For performance these
93* could all be eliminated later perhaps, or
94* the Parser could be serialized to a file once
95* all modes are registered
96*/
97class Doku_Parser_Mode {
98
99    var $Lexer;
100
101    var $allowedModes = array();
102
103    // Called before any calls to connectTo
104    function preConnect() {}
105
106    function connectTo($mode) {}
107
108    // Called after all calls to connectTo
109    function postConnect() {}
110
111    function accepts($mode) {
112        return in_array($mode, $this->allowedModes );
113    }
114
115}
116
117//-------------------------------------------------------------------
118class Doku_Parser_Mode_Base extends Doku_Parser_Mode {
119
120    function Doku_Parser_Mode_Base() {
121
122        $this->allowedModes = array_merge (
123                Doku_Parser_BlockContainers(),
124                Doku_Parser_BaseOnly(),
125                Doku_Parser_Paragraphs(),
126                Doku_Parser_Formatting(),
127                Doku_Parser_Substition(),
128                Doku_Parser_Protected(),
129                Doku_Parser_Disabled()
130            );
131    }
132}
133
134//-------------------------------------------------------------------
135class Doku_Parser_Mode_Footnote extends Doku_Parser_Mode {
136
137    function Doku_Parser_Mode_Footnote() {
138
139        $this->allowedModes = array_merge (
140                Doku_Parser_BlockContainers(),
141                Doku_Parser_Formatting(),
142                Doku_Parser_Substition(),
143                Doku_Parser_Protected(),
144                Doku_Parser_Disabled()
145            );
146
147    }
148
149    function connectTo($mode) {
150        $this->Lexer->addEntryPattern(
151            '\x28\x28(?=.*\x29\x29)',$mode,'footnote'
152            );
153    }
154
155    function postConnect() {
156        $this->Lexer->addExitPattern(
157            '\x29\x29','footnote'
158            );
159
160    }
161
162}
163
164//-------------------------------------------------------------------
165class Doku_Parser_Mode_Header extends Doku_Parser_Mode {
166
167    function preConnect() {
168        //we're not picky about the closing ones, two are enough
169
170        // Header 1 is special case - match 6 or more
171        $this->Lexer->addSpecialPattern(
172                            '[ \t]*={6,}[^\n]+={2,}[ \t]*(?=\n)',
173                            'base',
174                            'header'
175                        );
176
177        // For the rest, match exactly
178        for ( $i = 5; $i > 1; $i--) {
179            $this->Lexer->addSpecialPattern(
180                                '[ \t]*={'.$i.'}[^\n]+={2,}[ \t]*(?=\n)',
181                                'base',
182                                'header'
183                            );
184        }
185    }
186
187}
188
189//-------------------------------------------------------------------
190class Doku_Parser_Mode_NoToc extends Doku_Parser_Mode {
191
192    function connectTo($mode) {
193        $this->Lexer->addSpecialPattern('~~NOTOC~~',$mode,'notoc');
194    }
195
196}
197
198//-------------------------------------------------------------------
199class Doku_Parser_Mode_Linebreak extends Doku_Parser_Mode {
200
201    function connectTo($mode) {
202        $this->Lexer->addSpecialPattern('\x5C{2}\s',$mode,'linebreak');
203    }
204}
205
206//-------------------------------------------------------------------
207class Doku_Parser_Mode_Eol extends Doku_Parser_Mode {
208
209    function connectTo($mode) {
210        $badModes = array('listblock','table');
211        if ( in_array($mode, $badModes) ) {
212            return;
213        }
214        $this->Lexer->addSpecialPattern('\n',$mode,'eol');
215    }
216}
217
218//-------------------------------------------------------------------
219class Doku_Parser_Mode_HR extends Doku_Parser_Mode {
220
221    function connectTo($mode) {
222        $this->Lexer->addSpecialPattern('\n[ \t]*-{4,}[ \t]*(?=\n)',$mode,'hr');
223    }
224
225}
226
227//-------------------------------------------------------------------
228class Doku_Parser_Mode_Formatting extends Doku_Parser_Mode {
229
230    var $type;
231
232    var $formatting = array (
233        'strong' => array (
234            'entry'=>'\*\*(?=.*\*\*)',
235            'exit'=>'\*\*',
236            ),
237
238        'emphasis'=> array (
239            'entry'=>'//(?=.*//)',
240            'exit'=>'//',
241            ),
242
243        'underline'=> array (
244            'entry'=>'__(?=.*__)',
245            'exit'=>'__',
246            ),
247
248        'monospace'=> array (
249            'entry'=>'\x27\x27(?=.*\x27\x27)',
250            'exit'=>'\x27\x27',
251            ),
252
253        'subscript'=> array (
254            'entry'=>'<sub>(?=.*\x3C/sub\x3E)',
255            'exit'=>'</sub>',
256            ),
257
258        'superscript'=> array (
259            'entry'=>'<sup>(?=.*\x3C/sup\x3E)',
260            'exit'=>'</sup>',
261            ),
262
263        'deleted'=> array (
264            'entry'=>'<del>(?=.*\x3C/del\x3E)',
265            'exit'=>'</del>',
266            ),
267        );
268
269    function Doku_Parser_Mode_Formatting($type) {
270
271        if ( !array_key_exists($type, $this->formatting) ) {
272            trigger_error('Invalid formatting type '.$type, E_USER_WARNING);
273        }
274
275        $this->type = $type;
276
277        $this->allowedModes = array_merge (
278                Doku_Parser_Formatting($type),
279                Doku_Parser_Substition(),
280                Doku_Parser_Disabled()
281            );
282
283    }
284
285    function connectTo($mode) {
286
287        // Can't nest formatting in itself
288        if ( $mode == $this->type ) {
289            return;
290        }
291
292        $this->Lexer->addEntryPattern(
293                $this->formatting[$this->type]['entry'],
294                $mode,
295                $this->type
296            );
297    }
298
299    function postConnect() {
300
301        $this->Lexer->addExitPattern(
302            $this->formatting[$this->type]['exit'],
303            $this->type
304            );
305
306    }
307}
308
309//-------------------------------------------------------------------
310class Doku_Parser_Mode_ListBlock extends Doku_Parser_Mode {
311
312    function Doku_Parser_Mode_ListBlock() {
313
314        $this->allowedModes = array_merge (
315                Doku_Parser_Formatting(),
316                Doku_Parser_Substition(),
317                Doku_Parser_Disabled()
318            );
319        $this->allowedModes[] = 'footnote';
320        $this->allowedModes[] = 'preformatted';
321        $this->allowedModes[] = 'unformatted';
322
323    }
324
325    function connectTo($mode) {
326        $this->Lexer->addEntryPattern('\n {2,}[\-\*]',$mode,'listblock');
327        $this->Lexer->addEntryPattern('\n\t{1,}[\-\*]',$mode,'listblock');
328
329        $this->Lexer->addPattern('\n {2,}[\-\*]','listblock');
330        $this->Lexer->addPattern('\n\t{1,}[\-\*]','listblock');
331
332    }
333
334    function postConnect() {
335        $this->Lexer->addExitPattern('\n','listblock');
336    }
337}
338
339//-------------------------------------------------------------------
340class Doku_Parser_Mode_Table extends Doku_Parser_Mode {
341
342    function Doku_Parser_Mode_Table() {
343
344        $this->allowedModes = array_merge (
345                Doku_Parser_Formatting(),
346                Doku_Parser_Substition(),
347                Doku_Parser_Disabled()
348            );
349        $this->allowedModes[] = 'footnote';
350        $this->allowedModes[] = 'preformatted';
351        $this->allowedModes[] = 'unformatted';
352    }
353
354    function connectTo($mode) {
355        $this->Lexer->addEntryPattern('\n\^',$mode,'table');
356        $this->Lexer->addEntryPattern('\n\|',$mode,'table');
357    }
358
359    function postConnect() {
360        $this->Lexer->addPattern('\n\^','table');
361        $this->Lexer->addPattern('\n\|','table');
362        $this->Lexer->addPattern(' {2,}','table');
363        $this->Lexer->addPattern('\^','table');
364        $this->Lexer->addPattern('\|','table');
365        $this->Lexer->addExitPattern('\n','table');
366    }
367}
368
369//-------------------------------------------------------------------
370class Doku_Parser_Mode_Unformatted extends Doku_Parser_Mode {
371
372    function connectTo($mode) {
373        $this->Lexer->addEntryPattern('<nowiki>(?=.*\x3C/nowiki\x3E)',$mode,'unformatted');
374        $this->Lexer->addEntryPattern('%%(?=.*%%)',$mode,'unformattedalt');
375    }
376
377    function postConnect() {
378        $this->Lexer->addExitPattern('</nowiki>','unformatted');
379        $this->Lexer->addExitPattern('%%','unformattedalt');
380        $this->Lexer->mapHandler('unformattedalt','unformatted');
381    }
382
383}
384
385//-------------------------------------------------------------------
386class Doku_Parser_Mode_PHP extends Doku_Parser_Mode {
387
388    function connectTo($mode) {
389        $this->Lexer->addEntryPattern('<php>(?=.*\x3C/php\x3E)',$mode,'php');
390    }
391
392    function postConnect() {
393        $this->Lexer->addExitPattern('</php>','php');
394    }
395
396}
397
398//-------------------------------------------------------------------
399class Doku_Parser_Mode_HTML extends Doku_Parser_Mode {
400
401    function connectTo($mode) {
402        $this->Lexer->addEntryPattern('<html>(?=.*\x3C/html\x3E)',$mode,'html');
403    }
404
405    function postConnect() {
406        $this->Lexer->addExitPattern('</html>','html');
407    }
408
409}
410
411//-------------------------------------------------------------------
412class Doku_Parser_Mode_Preformatted extends Doku_Parser_Mode {
413
414    function connectTo($mode) {
415        // Has hard coded awareness of lists...
416        $this->Lexer->addEntryPattern('\n  (?![\*\-])',$mode,'preformatted');
417        $this->Lexer->addEntryPattern('\n\t(?![\*\-])',$mode,'preformatted');
418
419        // How to effect a sub pattern with the Lexer!
420        $this->Lexer->addPattern('\n  ','preformatted');
421        $this->Lexer->addPattern('\n\t','preformatted');
422
423    }
424
425    function postConnect() {
426        $this->Lexer->addExitPattern('\n','preformatted');
427    }
428
429}
430
431//-------------------------------------------------------------------
432class Doku_Parser_Mode_Code extends Doku_Parser_Mode {
433
434    function connectTo($mode) {
435        $this->Lexer->addEntryPattern('<code(?=.*\x3C/code\x3E)',$mode,'code');
436    }
437
438    function postConnect() {
439        $this->Lexer->addExitPattern('</code>','code');
440    }
441
442}
443
444//-------------------------------------------------------------------
445class Doku_Parser_Mode_File extends Doku_Parser_Mode {
446
447    function connectTo($mode) {
448        $this->Lexer->addEntryPattern('<file>(?=.*\x3C/file\x3E)',$mode,'file');
449    }
450
451    function postConnect() {
452        $this->Lexer->addExitPattern('</file>','file');
453    }
454
455}
456
457//-------------------------------------------------------------------
458class Doku_Parser_Mode_Quote extends Doku_Parser_Mode {
459
460    function Doku_Parser_Mode_Quote() {
461
462        $this->allowedModes = array_merge (
463                Doku_Parser_Formatting(),
464                Doku_Parser_Substition(),
465                Doku_Parser_Disabled()
466            );
467            $this->allowedModes[] = 'footnote';
468            $this->allowedModes[] = 'preformatted';
469            $this->allowedModes[] = 'unformatted';
470    }
471
472    function connectTo($mode) {
473        $this->Lexer->addEntryPattern('\n>{1,}',$mode,'quote');
474    }
475
476    function postConnect() {
477        $this->Lexer->addPattern('\n>{1,}','quote');
478        $this->Lexer->addExitPattern('\n','quote');
479    }
480
481}
482
483//-------------------------------------------------------------------
484class Doku_Parser_Mode_Acronym extends Doku_Parser_Mode {
485    // A list
486    var $acronyms = array();
487    var $pattern = '';
488
489    function Doku_Parser_Mode_Acronym($acronyms) {
490        $this->acronyms = $acronyms;
491    }
492
493    function preConnect() {
494        $sep = '';
495        foreach ( $this->acronyms as $acronym ) {
496            $this->pattern .= $sep.'(?<=\b)'.Doku_Lexer_Escape($acronym).'(?=\b)';
497            $sep = '|';
498        }
499    }
500
501    function connectTo($mode) {
502        if ( strlen($this->pattern) > 0 ) {
503            $this->Lexer->addSpecialPattern($this->pattern,$mode,'acronym');
504        }
505    }
506
507}
508
509//-------------------------------------------------------------------
510class Doku_Parser_Mode_Smiley extends Doku_Parser_Mode {
511    // A list
512    var $smileys = array();
513    var $pattern = '';
514
515    function Doku_Parser_Mode_Smiley($smileys) {
516        $this->smileys = $smileys;
517    }
518
519    function preConnect() {
520        $sep = '';
521        foreach ( $this->smileys as $smiley ) {
522            $this->pattern .= $sep.Doku_Lexer_Escape($smiley);
523            $sep = '|';
524        }
525    }
526
527    function connectTo($mode) {
528        if ( strlen($this->pattern) > 0 ) {
529            $this->Lexer->addSpecialPattern($this->pattern,$mode,'smiley');
530        }
531    }
532
533}
534
535//-------------------------------------------------------------------
536class Doku_Parser_Mode_Wordblock extends Doku_Parser_Mode {
537    // A list
538    var $badwords = array();
539    var $pattern = '';
540
541    function Doku_Parser_Mode_Wordblock($badwords) {
542        $this->badwords = $badwords;
543    }
544
545    function preConnect() {
546
547        if ( count($this->badwords) == 0 ) {
548            return;
549        }
550
551        $sep = '';
552        foreach ( $this->badwords as $badword ) {
553            $this->pattern .= $sep.'(?<=\b)(?i)'.Doku_Lexer_Escape($badword).'(?-i)(?=\b)';
554            $sep = '|';
555        }
556
557    }
558
559    function connectTo($mode) {
560        if ( strlen($this->pattern) > 0 ) {
561            $this->Lexer->addSpecialPattern($this->pattern,$mode,'wordblock');
562        }
563    }
564
565}
566
567//-------------------------------------------------------------------
568/**
569* @TODO Quotes and 640x480 are not supported - just straight replacements here
570*/
571class Doku_Parser_Mode_Entity extends Doku_Parser_Mode {
572    // A list
573    var $entities = array();
574    var $pattern = '';
575
576    function Doku_Parser_Mode_Entity($entities) {
577        $this->entities = $entities;
578    }
579
580    function preConnect() {
581        $sep = '';
582        foreach ( $this->entities as $entity ) {
583            $this->pattern .= $sep.Doku_Lexer_Escape($entity);
584            $sep = '|';
585        }
586    }
587
588    function connectTo($mode) {
589        if ( strlen($this->pattern) > 0 ) {
590            $this->Lexer->addSpecialPattern($this->pattern,$mode,'entity');
591        }
592    }
593
594}
595
596//-------------------------------------------------------------------
597// Implements the 640x480 replacement
598class Doku_Parser_Mode_MultiplyEntity extends Doku_Parser_Mode {
599
600    function connectTo($mode) {
601
602        $this->Lexer->addSpecialPattern(
603                    '(?<=\b)\d+[x|X]\d+(?=\b)',$mode,'multiplyentity'
604                );
605
606    }
607
608}
609
610//-------------------------------------------------------------------
611class Doku_Parser_Mode_Quotes extends Doku_Parser_Mode {
612
613    function connectTo($mode) {
614
615        $this->Lexer->addSpecialPattern(
616                    '(?<=\s)\'(?=\S)',$mode,'singlequoteopening'
617                );
618        $this->Lexer->addSpecialPattern(
619                    '(?<=^|\S)\'',$mode,'singlequoteclosing'
620                );
621        $this->Lexer->addSpecialPattern(
622                    '(?<=^|\s)"(?=\S)',$mode,'doublequoteopening'
623                );
624        $this->Lexer->addSpecialPattern(
625                    '(?<=\S)"',$mode,'doublequoteclosing'
626                );
627
628    }
629
630}
631
632//-------------------------------------------------------------------
633class Doku_Parser_Mode_CamelCaseLink extends Doku_Parser_Mode {
634
635    function connectTo($mode) {
636        $this->Lexer->addSpecialPattern(
637                '\b[A-Z]+[a-z]+[A-Z][A-Za-z]*\b',$mode,'camelcaselink'
638            );
639    }
640
641}
642
643//-------------------------------------------------------------------
644class Doku_Parser_Mode_InternalLink extends Doku_Parser_Mode {
645
646    function connectTo($mode) {
647        // Word boundaries?
648        $this->Lexer->addSpecialPattern("\[\[[^\]]+?\]\]",$mode,'internallink');
649    }
650
651}
652
653//-------------------------------------------------------------------
654class Doku_Parser_Mode_Media extends Doku_Parser_Mode {
655
656    function connectTo($mode) {
657        // Word boundaries?
658        $this->Lexer->addSpecialPattern("\{\{[^\}]+\}\}",$mode,'media');
659    }
660
661}
662
663//-------------------------------------------------------------------
664class Doku_Parser_Mode_RSS extends Doku_Parser_Mode {
665
666    function connectTo($mode) {
667        $this->Lexer->addSpecialPattern("\{\{rss>[^\}]+\}\}",$mode,'rss');
668    }
669
670}
671
672//-------------------------------------------------------------------
673class Doku_Parser_Mode_ExternalLink extends Doku_Parser_Mode {
674    var $schemes = array('http','https','telnet','gopher','wais','ftp','ed2k','irc');
675    var $patterns = array();
676
677    function preConnect() {
678
679        $ltrs = '\w';
680        $gunk = '/\#~:.?+=&%@!\-';
681        $punc = '.:?\-;,';
682        $host = $ltrs.$punc;
683        $any  = $ltrs.$gunk.$punc;
684
685        foreach ( $this->schemes as $scheme ) {
686            $this->patterns[] = '\b(?i)'.$scheme.'(?-i)://['.$any.']+?(?=['.$punc.']*[^'.$any.'])';
687        }
688
689        $this->patterns[] = '\b(?i)www?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])';
690        $this->patterns[] = '\b(?i)ftp?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])';
691
692    }
693
694    function connectTo($mode) {
695        foreach ( $this->patterns as $pattern ) {
696            $this->Lexer->addSpecialPattern($pattern,$mode,'externallink');
697        }
698    }
699
700}
701
702//-------------------------------------------------------------------
703class Doku_Parser_Mode_FileLink extends Doku_Parser_Mode {
704
705    var $pattern;
706
707    function preConnect() {
708
709        $ltrs = '\w';
710        $gunk = '/\#~:.?+=&%@!\-';
711        $punc = '.:?\-;,';
712        $host = $ltrs.$punc;
713        $any  = $ltrs.$gunk.$punc;
714
715        $this->pattern = '\b(?i)file(?-i)://['.$any.']+?['.
716            $punc.']*[^'.$any.']';
717    }
718
719    function connectTo($mode) {
720        $this->Lexer->addSpecialPattern(
721            $this->pattern,$mode,'filelink');
722    }
723
724
725}
726
727//-------------------------------------------------------------------
728class Doku_Parser_Mode_WindowsShareLink extends Doku_Parser_Mode {
729
730    var $pattern;
731
732    function preConnect() {
733
734        $ltrs = '\w';
735        $gunk = '/\#~:.?+=&%@!\-';
736        $punc = '.:?\-;,';
737        $host = $ltrs.$punc;
738        $any  = $ltrs.$gunk.$punc;
739
740        $this->pattern = "[$gunk$punc\s]\\\\\\\\[$host]+?\\\\[$any]+?[$punc]*[^$any]";
741    }
742
743    function connectTo($mode) {
744        $this->Lexer->addSpecialPattern(
745            $this->pattern,$mode,'windowssharelink');
746    }
747
748
749}
750
751//-------------------------------------------------------------------
752class Doku_Parser_Mode_EmailLink extends Doku_Parser_Mode {
753
754    function connectTo($mode) {
755    //<([\w0-9\-_.]+?)@([\w\-]+\.([\w\-\.]+\.)*[\w]+)>
756        $this->Lexer->addSpecialPattern("<[\w0-9\-_.]+?@[\w\-]+\.[\w\-\.]+\.*[\w]+>",$mode,'emaillink');
757    }
758
759}
760
761//-------------------------------------------------------------------
762// Help fns to keep mode lists - used to make it easier to populate
763// the list of modes another mode accepts
764
765// Can contain many other modes
766// E.g. a footnote can containing formatting etc.
767function Doku_Parser_BlockContainers() {
768    $modes = array(
769        'footnote', 'listblock', 'table','quote',
770        // hr breaks the principle but HRs should not be used in tables / lists
771        // so put it here
772        'hr',
773    );
774    return $modes;
775}
776
777// Used to mark paragraph boundaries
778function Doku_Parser_Paragraphs() {
779    $modes = array(
780        'eol'
781    );
782    return $modes;
783}
784
785// Can only be used by the base mode
786function Doku_Parser_BaseOnly() {
787    $modes = array(
788        'header'
789    );
790    return $modes;
791}
792
793// "Styling" modes that format text.
794function Doku_Parser_Formatting($remove = '') {
795    $modes = array(
796        'strong', 'emphasis', 'underline', 'monospace',
797        'subscript', 'superscript', 'deleted',
798        );
799    $key = array_search($remove, $modes);
800    if ( is_int($key) ) {
801        unset($modes[$key]);
802    }
803
804    return $modes;
805}
806
807// Modes where the token is simply replaced - contain no
808// other modes
809function Doku_Parser_Substition() {
810    $modes = array(
811        'acronym','smiley','wordblock','entity','camelcaselink',
812        'internallink','media','externallink','linebreak','emaillink',
813        'windowssharelink','filelink','notoc','multiplyentity',
814        'quotes','rss'
815
816    );
817    return $modes;
818}
819
820// Modes which have a start and end token but inside which
821// no other modes should be applied
822function Doku_Parser_Protected() {
823    $modes = array(
824        'preformatted','code','file',
825        'php','html','quote',
826    );
827    return $modes;
828}
829
830// Disable wiki markup inside this mode
831function Doku_Parser_Disabled() {
832    $modes = array(
833        'unformatted'
834    );
835    return $modes;
836}
837
838
839//Setup VIM: ex: et ts=4 enc=utf-8 :
840