xref: /dokuwiki/inc/parser/parser.php (revision 5a3e1f53b18728d500b3505f4fbd8c78848120e0)
10cecf9d5Sandi<?php
2fa8adffeSAndreas Gohrif(!defined('DOKU_INC')) die('meh.');
30cecf9d5Sandirequire_once DOKU_INC . 'inc/parser/lexer.php';
40cecf9d5Sandirequire_once DOKU_INC . 'inc/parser/handler.php';
50cecf9d5Sandi
6ee20e7d1Sandi
7ee20e7d1Sandi/**
8ee20e7d1Sandi * Define various types of modes used by the parser - they are used to
9ee20e7d1Sandi * populate the list of modes another mode accepts
10ee20e7d1Sandi */
11ee20e7d1Sandiglobal $PARSER_MODES;
12ee20e7d1Sandi$PARSER_MODES = array(
13ee20e7d1Sandi    // containers are complex modes that can contain many other modes
14ee20e7d1Sandi    // hr breaks the principle but they shouldn't be used in tables / lists
15ee20e7d1Sandi    // so they are put here
16ee20e7d1Sandi    'container'    => array('listblock','table','quote','hr'),
17ee20e7d1Sandi
18ee20e7d1Sandi    // some mode are allowed inside the base mode only
19ee20e7d1Sandi    'baseonly'     => array('header'),
20ee20e7d1Sandi
21ee20e7d1Sandi    // modes for styling text -- footnote behaves similar to styling
22ee20e7d1Sandi    'formatting'   => array('strong', 'emphasis', 'underline', 'monospace',
23ee20e7d1Sandi                            'subscript', 'superscript', 'deleted', 'footnote'),
24ee20e7d1Sandi
25ee20e7d1Sandi    // modes where the token is simply replaced - they can not contain any
26ee20e7d1Sandi    // other modes
27ee20e7d1Sandi    'substition'   => array('acronym','smiley','wordblock','entity',
28ee20e7d1Sandi                            'camelcaselink', 'internallink','media',
29ee20e7d1Sandi                            'externallink','linebreak','emaillink',
30ee20e7d1Sandi                            'windowssharelink','filelink','notoc',
31ee20e7d1Sandi                            'nocache','multiplyentity','quotes','rss'),
32ee20e7d1Sandi
33ee20e7d1Sandi    // modes which have a start and end token but inside which
34ee20e7d1Sandi    // no other modes should be applied
3507f89c3cSAnika Henke    'protected'    => array('preformatted','code','file','php','html','htmlblock','phpblock'),
36ee20e7d1Sandi
37ee20e7d1Sandi    // inside this mode no wiki markup should be applied but lineendings
38ee20e7d1Sandi    // and whitespace isn't preserved
39ee20e7d1Sandi    'disabled'     => array('unformatted'),
40ee20e7d1Sandi
41ee20e7d1Sandi    // used to mark paragraph boundaries
42ee20e7d1Sandi    'paragraphs'   => array('eol')
43ee20e7d1Sandi);
44ee20e7d1Sandi
450cecf9d5Sandi//-------------------------------------------------------------------
460cecf9d5Sandi
470cecf9d5Sandi/**
480cecf9d5Sandi * Sets up the Lexer with modes and points it to the Handler
490cecf9d5Sandi * For an intro to the Lexer see: wiki:parser
500cecf9d5Sandi */
510cecf9d5Sandiclass Doku_Parser {
520cecf9d5Sandi
530cecf9d5Sandi    var $Handler;
540cecf9d5Sandi
55e3ab6fc5SMichael Hamann    /**
56e3ab6fc5SMichael Hamann     * @var Doku_Lexer $Lexer
57e3ab6fc5SMichael Hamann     */
580cecf9d5Sandi    var $Lexer;
590cecf9d5Sandi
600cecf9d5Sandi    var $modes = array();
610cecf9d5Sandi
6244881bd0Shenning.noren    var $connected = false;
630cecf9d5Sandi
64b7c441b9SHarry Fuecks    function addBaseMode(& $BaseMode) {
65b7c441b9SHarry Fuecks        $this->modes['base'] =& $BaseMode;
660cecf9d5Sandi        if ( !$this->Lexer ) {
6767f9913dSAndreas Gohr            $this->Lexer = new Doku_Lexer($this->Handler,'base', true);
680cecf9d5Sandi        }
690cecf9d5Sandi        $this->modes['base']->Lexer =& $this->Lexer;
700cecf9d5Sandi    }
710cecf9d5Sandi
720cecf9d5Sandi    /**
730cecf9d5Sandi     * PHP preserves order of associative elements
740cecf9d5Sandi     * Mode sequence is important
750cecf9d5Sandi     */
760cecf9d5Sandi    function addMode($name, & $Mode) {
770cecf9d5Sandi        if ( !isset($this->modes['base']) ) {
78107b01d6Sandi            $this->addBaseMode(new Doku_Parser_Mode_base());
790cecf9d5Sandi        }
800cecf9d5Sandi        $Mode->Lexer = & $this->Lexer;
810cecf9d5Sandi        $this->modes[$name] =& $Mode;
820cecf9d5Sandi    }
830cecf9d5Sandi
840cecf9d5Sandi    function connectModes() {
850cecf9d5Sandi
860cecf9d5Sandi        if ( $this->connected ) {
870cecf9d5Sandi            return;
880cecf9d5Sandi        }
890cecf9d5Sandi
900cecf9d5Sandi        foreach ( array_keys($this->modes) as $mode ) {
910cecf9d5Sandi
920cecf9d5Sandi            // Base isn't connected to anything
930cecf9d5Sandi            if ( $mode == 'base' ) {
940cecf9d5Sandi                continue;
950cecf9d5Sandi            }
960cecf9d5Sandi            $this->modes[$mode]->preConnect();
970cecf9d5Sandi
980cecf9d5Sandi            foreach ( array_keys($this->modes) as $cm ) {
990cecf9d5Sandi
1000cecf9d5Sandi                if ( $this->modes[$cm]->accepts($mode) ) {
1010cecf9d5Sandi                    $this->modes[$mode]->connectTo($cm);
1020cecf9d5Sandi                }
1030cecf9d5Sandi
1040cecf9d5Sandi            }
1050cecf9d5Sandi
1060cecf9d5Sandi            $this->modes[$mode]->postConnect();
1070cecf9d5Sandi        }
1080cecf9d5Sandi
10944881bd0Shenning.noren        $this->connected = true;
1100cecf9d5Sandi    }
1110cecf9d5Sandi
1120cecf9d5Sandi    function parse($doc) {
1130cecf9d5Sandi        if ( $this->Lexer ) {
1140cecf9d5Sandi            $this->connectModes();
1150cecf9d5Sandi            // Normalize CRs and pad doc
1160cecf9d5Sandi            $doc = "\n".str_replace("\r\n","\n",$doc)."\n";
1170cecf9d5Sandi            $this->Lexer->parse($doc);
118433bef32Sandi            $this->Handler->_finalize();
1190cecf9d5Sandi            return $this->Handler->calls;
1200cecf9d5Sandi        } else {
12144881bd0Shenning.noren            return false;
1220cecf9d5Sandi        }
1230cecf9d5Sandi    }
1240cecf9d5Sandi
1250cecf9d5Sandi}
1260cecf9d5Sandi
1270cecf9d5Sandi//-------------------------------------------------------------------
128*5a3e1f53SAndreas Gohr
129*5a3e1f53SAndreas Gohr/**
130*5a3e1f53SAndreas Gohr * Class Doku_Parser_Mode_Interface
131*5a3e1f53SAndreas Gohr *
132*5a3e1f53SAndreas Gohr * Defines a mode (syntax component) in the Parser
133*5a3e1f53SAndreas Gohr */
134*5a3e1f53SAndreas Gohrinterface Doku_Parser_Mode_Interface {
135*5a3e1f53SAndreas Gohr    /**
136*5a3e1f53SAndreas Gohr     * returns a number used to determine in which order modes are added
137*5a3e1f53SAndreas Gohr     */
138*5a3e1f53SAndreas Gohr    public function getSort();
139*5a3e1f53SAndreas Gohr
140*5a3e1f53SAndreas Gohr    /**
141*5a3e1f53SAndreas Gohr     * Called before any calls to connectTo
142*5a3e1f53SAndreas Gohr     */
143*5a3e1f53SAndreas Gohr    function preConnect();
144*5a3e1f53SAndreas Gohr
145*5a3e1f53SAndreas Gohr    /**
146*5a3e1f53SAndreas Gohr     * Connects the mode
147*5a3e1f53SAndreas Gohr     *
148*5a3e1f53SAndreas Gohr     * @param string $mode
149*5a3e1f53SAndreas Gohr     */
150*5a3e1f53SAndreas Gohr    function connectTo($mode);
151*5a3e1f53SAndreas Gohr
152*5a3e1f53SAndreas Gohr    /**
153*5a3e1f53SAndreas Gohr     * Called after all calls to connectTo
154*5a3e1f53SAndreas Gohr     */
155*5a3e1f53SAndreas Gohr    function postConnect();
156*5a3e1f53SAndreas Gohr
157*5a3e1f53SAndreas Gohr    /**
158*5a3e1f53SAndreas Gohr     * Check if given mode is accepted inside this mode
159*5a3e1f53SAndreas Gohr     *
160*5a3e1f53SAndreas Gohr     * @param string $mode
161*5a3e1f53SAndreas Gohr     * @return bool
162*5a3e1f53SAndreas Gohr     */
163*5a3e1f53SAndreas Gohr    function accepts($mode);
164*5a3e1f53SAndreas Gohr}
165*5a3e1f53SAndreas Gohr
1660cecf9d5Sandi/**
16772d89f96SAndreas Gohr * This class and all the subclasses below are used to reduce the effort required to register
16872d89f96SAndreas Gohr * modes with the Lexer.
16972d89f96SAndreas Gohr *
1700b7c14c2Sandi * @author Harry Fuecks <hfuecks@gmail.com>
1710cecf9d5Sandi */
172*5a3e1f53SAndreas Gohrclass Doku_Parser_Mode implements Doku_Parser_Mode_Interface {
173e3ab6fc5SMichael Hamann    /**
174e3ab6fc5SMichael Hamann     * @var Doku_Lexer $Lexer
175e3ab6fc5SMichael Hamann     */
1760cecf9d5Sandi    var $Lexer;
1770cecf9d5Sandi    var $allowedModes = array();
1780cecf9d5Sandi
179107b01d6Sandi    function getSort() {
180107b01d6Sandi        trigger_error('getSort() not implemented in '.get_class($this), E_USER_WARNING);
181107b01d6Sandi    }
182107b01d6Sandi
1830cecf9d5Sandi    function preConnect() {}
1840cecf9d5Sandi    function connectTo($mode) {}
1850cecf9d5Sandi    function postConnect() {}
1860cecf9d5Sandi    function accepts($mode) {
1876f9bd982SAndreas Gohr        return in_array($mode, (array) $this->allowedModes );
1880cecf9d5Sandi    }
189*5a3e1f53SAndreas Gohr}
1900cecf9d5Sandi
191*5a3e1f53SAndreas Gohr/**
192*5a3e1f53SAndreas Gohr * Basically the same as Doku_Parser_Mode but extends from DokuWiki_Plugin
193*5a3e1f53SAndreas Gohr *
194*5a3e1f53SAndreas Gohr * Adds additional functions to syntax plugins
195*5a3e1f53SAndreas Gohr */
196*5a3e1f53SAndreas Gohrclass Doku_Parser_Mode_Plugin extends DokuWiki_Plugin implements Doku_Parser_Mode_Interface {
197*5a3e1f53SAndreas Gohr    /**
198*5a3e1f53SAndreas Gohr     * @var Doku_Lexer $Lexer
199*5a3e1f53SAndreas Gohr     */
200*5a3e1f53SAndreas Gohr    var $Lexer;
201*5a3e1f53SAndreas Gohr    var $allowedModes = array();
202*5a3e1f53SAndreas Gohr
203*5a3e1f53SAndreas Gohr    function getSort() {
204*5a3e1f53SAndreas Gohr        trigger_error('getSort() not implemented in '.get_class($this), E_USER_WARNING);
205*5a3e1f53SAndreas Gohr    }
206*5a3e1f53SAndreas Gohr
207*5a3e1f53SAndreas Gohr    function preConnect() {}
208*5a3e1f53SAndreas Gohr    function connectTo($mode) {}
209*5a3e1f53SAndreas Gohr    function postConnect() {}
210*5a3e1f53SAndreas Gohr    function accepts($mode) {
211*5a3e1f53SAndreas Gohr        return in_array($mode, (array) $this->allowedModes );
212*5a3e1f53SAndreas Gohr    }
2130cecf9d5Sandi}
2140cecf9d5Sandi
2150cecf9d5Sandi//-------------------------------------------------------------------
216107b01d6Sandiclass Doku_Parser_Mode_base extends Doku_Parser_Mode {
2170cecf9d5Sandi
218107b01d6Sandi    function Doku_Parser_Mode_base() {
219ee20e7d1Sandi        global $PARSER_MODES;
2200cecf9d5Sandi
2210cecf9d5Sandi        $this->allowedModes = array_merge (
222ee20e7d1Sandi                $PARSER_MODES['container'],
223ee20e7d1Sandi                $PARSER_MODES['baseonly'],
224ee20e7d1Sandi                $PARSER_MODES['paragraphs'],
225ee20e7d1Sandi                $PARSER_MODES['formatting'],
226ee20e7d1Sandi                $PARSER_MODES['substition'],
227ee20e7d1Sandi                $PARSER_MODES['protected'],
228ee20e7d1Sandi                $PARSER_MODES['disabled']
2290cecf9d5Sandi            );
2300cecf9d5Sandi    }
231107b01d6Sandi
232107b01d6Sandi    function getSort() {
233107b01d6Sandi        return 0;
234107b01d6Sandi    }
2350cecf9d5Sandi}
2360cecf9d5Sandi
2370cecf9d5Sandi//-------------------------------------------------------------------
238107b01d6Sandiclass Doku_Parser_Mode_footnote extends Doku_Parser_Mode {
2390cecf9d5Sandi
240107b01d6Sandi    function Doku_Parser_Mode_footnote() {
241ee20e7d1Sandi        global $PARSER_MODES;
2420cecf9d5Sandi
2430cecf9d5Sandi        $this->allowedModes = array_merge (
244ee20e7d1Sandi                $PARSER_MODES['container'],
245ee20e7d1Sandi                $PARSER_MODES['formatting'],
246ee20e7d1Sandi                $PARSER_MODES['substition'],
247ee20e7d1Sandi                $PARSER_MODES['protected'],
248ee20e7d1Sandi                $PARSER_MODES['disabled']
2490cecf9d5Sandi            );
2500cecf9d5Sandi
2512fe7363dSchris        unset($this->allowedModes[array_search('footnote', $this->allowedModes)]);
2520cecf9d5Sandi    }
2530cecf9d5Sandi
2540cecf9d5Sandi    function connectTo($mode) {
2550cecf9d5Sandi        $this->Lexer->addEntryPattern(
2560cecf9d5Sandi            '\x28\x28(?=.*\x29\x29)',$mode,'footnote'
2570cecf9d5Sandi            );
2580cecf9d5Sandi    }
2590cecf9d5Sandi
2600cecf9d5Sandi    function postConnect() {
2610cecf9d5Sandi        $this->Lexer->addExitPattern(
2620cecf9d5Sandi            '\x29\x29','footnote'
2630cecf9d5Sandi            );
2640cecf9d5Sandi    }
2650cecf9d5Sandi
266107b01d6Sandi    function getSort() {
267107b01d6Sandi        return 150;
268107b01d6Sandi    }
2690cecf9d5Sandi}
2700cecf9d5Sandi
2710cecf9d5Sandi//-------------------------------------------------------------------
272107b01d6Sandiclass Doku_Parser_Mode_header extends Doku_Parser_Mode {
2730cecf9d5Sandi
2749fa736b0SAndreas Gohr    function connectTo($mode) {
275506ae684Sandi        //we're not picky about the closing ones, two are enough
2760cecf9d5Sandi        $this->Lexer->addSpecialPattern(
27730fe9cd6SAndreas Gohr                            '[ \t]*={2,}[^\n]+={2,}[ \t]*(?=\n)',
2789fa736b0SAndreas Gohr                            $mode,
2790cecf9d5Sandi                            'header'
2800cecf9d5Sandi                        );
2810cecf9d5Sandi    }
2820cecf9d5Sandi
283107b01d6Sandi    function getSort() {
284107b01d6Sandi        return 50;
285107b01d6Sandi    }
2860cecf9d5Sandi}
2870cecf9d5Sandi
2880cecf9d5Sandi//-------------------------------------------------------------------
289107b01d6Sandiclass Doku_Parser_Mode_notoc extends Doku_Parser_Mode {
2900cecf9d5Sandi
2910cecf9d5Sandi    function connectTo($mode) {
2920cecf9d5Sandi        $this->Lexer->addSpecialPattern('~~NOTOC~~',$mode,'notoc');
2930cecf9d5Sandi    }
2940cecf9d5Sandi
295107b01d6Sandi    function getSort() {
296107b01d6Sandi        return 30;
297107b01d6Sandi    }
2980cecf9d5Sandi}
2990cecf9d5Sandi
3000cecf9d5Sandi//-------------------------------------------------------------------
301107b01d6Sandiclass Doku_Parser_Mode_nocache extends Doku_Parser_Mode {
3029dc2c2afSandi
3039dc2c2afSandi    function connectTo($mode) {
3049dc2c2afSandi        $this->Lexer->addSpecialPattern('~~NOCACHE~~',$mode,'nocache');
3059dc2c2afSandi    }
3069dc2c2afSandi
307107b01d6Sandi    function getSort() {
308107b01d6Sandi        return 40;
309107b01d6Sandi    }
3109dc2c2afSandi}
3119dc2c2afSandi
3129dc2c2afSandi//-------------------------------------------------------------------
313107b01d6Sandiclass Doku_Parser_Mode_linebreak extends Doku_Parser_Mode {
3140cecf9d5Sandi
3150cecf9d5Sandi    function connectTo($mode) {
31630897fecSChris Smith        $this->Lexer->addSpecialPattern('\x5C{2}(?:[ \t]|(?=\n))',$mode,'linebreak');
3170cecf9d5Sandi    }
318107b01d6Sandi
319107b01d6Sandi    function getSort() {
320107b01d6Sandi        return 140;
321107b01d6Sandi    }
3220cecf9d5Sandi}
3230cecf9d5Sandi
3240cecf9d5Sandi//-------------------------------------------------------------------
325107b01d6Sandiclass Doku_Parser_Mode_eol extends Doku_Parser_Mode {
3260cecf9d5Sandi
3270cecf9d5Sandi    function connectTo($mode) {
3280cecf9d5Sandi        $badModes = array('listblock','table');
3290cecf9d5Sandi        if ( in_array($mode, $badModes) ) {
3300cecf9d5Sandi            return;
3310cecf9d5Sandi        }
33295c19ce7SChris Smith        // see FS#1652, pattern extended to swallow preceding whitespace to avoid issues with lines that only contain whitespace
33395c19ce7SChris Smith        $this->Lexer->addSpecialPattern('(?:^[ \t]*)?\n',$mode,'eol');
3340cecf9d5Sandi    }
335107b01d6Sandi
336107b01d6Sandi    function getSort() {
337107b01d6Sandi        return 370;
338107b01d6Sandi    }
3390cecf9d5Sandi}
3400cecf9d5Sandi
3410cecf9d5Sandi//-------------------------------------------------------------------
342107b01d6Sandiclass Doku_Parser_Mode_hr extends Doku_Parser_Mode {
3430cecf9d5Sandi
3440cecf9d5Sandi    function connectTo($mode) {
3456f0c5dbfSandi        $this->Lexer->addSpecialPattern('\n[ \t]*-{4,}[ \t]*(?=\n)',$mode,'hr');
3460cecf9d5Sandi    }
3470cecf9d5Sandi
348107b01d6Sandi    function getSort() {
349107b01d6Sandi        return 160;
350107b01d6Sandi    }
3510cecf9d5Sandi}
3520cecf9d5Sandi
3530cecf9d5Sandi//-------------------------------------------------------------------
35403b54bb0SThorsten Staerk/**
35503b54bb0SThorsten Staerk * This class sets the markup for bold (=strong),
35603b54bb0SThorsten Staerk * italic (=emphasis), underline etc.
35703b54bb0SThorsten Staerk */
358107b01d6Sandiclass Doku_Parser_Mode_formatting extends Doku_Parser_Mode {
3590cecf9d5Sandi    var $type;
3600cecf9d5Sandi
3610cecf9d5Sandi    var $formatting = array (
3620cecf9d5Sandi        'strong' => array (
3630cecf9d5Sandi            'entry'=>'\*\*(?=.*\*\*)',
3640cecf9d5Sandi            'exit'=>'\*\*',
365107b01d6Sandi            'sort'=>70
3660cecf9d5Sandi            ),
3670cecf9d5Sandi
3680cecf9d5Sandi        'emphasis'=> array (
36924b0ff2aSAndreas Gohr            'entry'=>'//(?=[^\x00]*[^:])', //hack for bugs #384 #763 #1468
3700cecf9d5Sandi            'exit'=>'//',
371107b01d6Sandi            'sort'=>80
3720cecf9d5Sandi            ),
3730cecf9d5Sandi
3740cecf9d5Sandi        'underline'=> array (
3750cecf9d5Sandi            'entry'=>'__(?=.*__)',
3760cecf9d5Sandi            'exit'=>'__',
377107b01d6Sandi            'sort'=>90
3780cecf9d5Sandi            ),
3790cecf9d5Sandi
3800cecf9d5Sandi        'monospace'=> array (
3810cecf9d5Sandi            'entry'=>'\x27\x27(?=.*\x27\x27)',
3820cecf9d5Sandi            'exit'=>'\x27\x27',
383107b01d6Sandi            'sort'=>100
3840cecf9d5Sandi            ),
3850cecf9d5Sandi
3860cecf9d5Sandi        'subscript'=> array (
38787858f84Schris            'entry'=>'<sub>(?=.*</sub>)',
3880cecf9d5Sandi            'exit'=>'</sub>',
389107b01d6Sandi            'sort'=>110
3900cecf9d5Sandi            ),
3910cecf9d5Sandi
3920cecf9d5Sandi        'superscript'=> array (
39387858f84Schris            'entry'=>'<sup>(?=.*</sup>)',
3940cecf9d5Sandi            'exit'=>'</sup>',
395107b01d6Sandi            'sort'=>120
3960cecf9d5Sandi            ),
3970cecf9d5Sandi
3980cecf9d5Sandi        'deleted'=> array (
39987858f84Schris            'entry'=>'<del>(?=.*</del>)',
4000cecf9d5Sandi            'exit'=>'</del>',
401107b01d6Sandi            'sort'=>130
4020cecf9d5Sandi            ),
4030cecf9d5Sandi        );
4040cecf9d5Sandi
405107b01d6Sandi    function Doku_Parser_Mode_formatting($type) {
406ee20e7d1Sandi        global $PARSER_MODES;
4070cecf9d5Sandi
4080cecf9d5Sandi        if ( !array_key_exists($type, $this->formatting) ) {
4090cecf9d5Sandi            trigger_error('Invalid formatting type '.$type, E_USER_WARNING);
4100cecf9d5Sandi        }
4110cecf9d5Sandi
4120cecf9d5Sandi        $this->type = $type;
4130cecf9d5Sandi
414ee20e7d1Sandi        // formatting may contain other formatting but not it self
415ee20e7d1Sandi        $modes = $PARSER_MODES['formatting'];
416ee20e7d1Sandi        $key = array_search($type, $modes);
417ee20e7d1Sandi        if ( is_int($key) ) {
418ee20e7d1Sandi            unset($modes[$key]);
419ee20e7d1Sandi        }
4200cecf9d5Sandi
421ee20e7d1Sandi        $this->allowedModes = array_merge (
422ee20e7d1Sandi                $modes,
423ee20e7d1Sandi                $PARSER_MODES['substition'],
424ee20e7d1Sandi                $PARSER_MODES['disabled']
425ee20e7d1Sandi            );
4260cecf9d5Sandi    }
4270cecf9d5Sandi
4280cecf9d5Sandi    function connectTo($mode) {
4290cecf9d5Sandi
4300cecf9d5Sandi        // Can't nest formatting in itself
4310cecf9d5Sandi        if ( $mode == $this->type ) {
4320cecf9d5Sandi            return;
4330cecf9d5Sandi        }
4340cecf9d5Sandi
4350cecf9d5Sandi        $this->Lexer->addEntryPattern(
4360cecf9d5Sandi                $this->formatting[$this->type]['entry'],
4370cecf9d5Sandi                $mode,
4380cecf9d5Sandi                $this->type
4390cecf9d5Sandi            );
4400cecf9d5Sandi    }
4410cecf9d5Sandi
4420cecf9d5Sandi    function postConnect() {
4430cecf9d5Sandi
4440cecf9d5Sandi        $this->Lexer->addExitPattern(
4450cecf9d5Sandi            $this->formatting[$this->type]['exit'],
4460cecf9d5Sandi            $this->type
4470cecf9d5Sandi            );
4480cecf9d5Sandi
4490cecf9d5Sandi    }
450107b01d6Sandi
451107b01d6Sandi    function getSort() {
452107b01d6Sandi        return $this->formatting[$this->type]['sort'];
453107b01d6Sandi    }
4540cecf9d5Sandi}
4550cecf9d5Sandi
4560cecf9d5Sandi//-------------------------------------------------------------------
457107b01d6Sandiclass Doku_Parser_Mode_listblock extends Doku_Parser_Mode {
4580cecf9d5Sandi
459107b01d6Sandi    function Doku_Parser_Mode_listblock() {
460ee20e7d1Sandi        global $PARSER_MODES;
4610cecf9d5Sandi
4620cecf9d5Sandi        $this->allowedModes = array_merge (
463ee20e7d1Sandi                $PARSER_MODES['formatting'],
464ee20e7d1Sandi                $PARSER_MODES['substition'],
465ee20e7d1Sandi                $PARSER_MODES['disabled'],
466ee20e7d1Sandi                $PARSER_MODES['protected'] #XXX new
4670cecf9d5Sandi            );
468702eb898Sandi
469ee20e7d1Sandi    //    $this->allowedModes[] = 'footnote';
4700cecf9d5Sandi    }
4710cecf9d5Sandi
4720cecf9d5Sandi    function connectTo($mode) {
47313ebcbe5SChristopher Smith        $this->Lexer->addEntryPattern('[ \t]*\n {2,}[\-\*]',$mode,'listblock');
47413ebcbe5SChristopher Smith        $this->Lexer->addEntryPattern('[ \t]*\n\t{1,}[\-\*]',$mode,'listblock');
4750cecf9d5Sandi
4760cecf9d5Sandi        $this->Lexer->addPattern('\n {2,}[\-\*]','listblock');
4770cecf9d5Sandi        $this->Lexer->addPattern('\n\t{1,}[\-\*]','listblock');
4780cecf9d5Sandi
4790cecf9d5Sandi    }
4800cecf9d5Sandi
4810cecf9d5Sandi    function postConnect() {
4820cecf9d5Sandi        $this->Lexer->addExitPattern('\n','listblock');
4830cecf9d5Sandi    }
484107b01d6Sandi
485107b01d6Sandi    function getSort() {
486107b01d6Sandi        return 10;
487107b01d6Sandi    }
4880cecf9d5Sandi}
4890cecf9d5Sandi
4900cecf9d5Sandi//-------------------------------------------------------------------
491107b01d6Sandiclass Doku_Parser_Mode_table extends Doku_Parser_Mode {
4920cecf9d5Sandi
493107b01d6Sandi    function Doku_Parser_Mode_table() {
494ee20e7d1Sandi        global $PARSER_MODES;
4950cecf9d5Sandi
4960cecf9d5Sandi        $this->allowedModes = array_merge (
497ee20e7d1Sandi                $PARSER_MODES['formatting'],
498ee20e7d1Sandi                $PARSER_MODES['substition'],
499ee20e7d1Sandi                $PARSER_MODES['disabled'],
500107b01d6Sandi                $PARSER_MODES['protected']
5010cecf9d5Sandi            );
5020cecf9d5Sandi    }
5030cecf9d5Sandi
5040cecf9d5Sandi    function connectTo($mode) {
5055a41afe6SChristopher Smith        $this->Lexer->addEntryPattern('[\t ]*\n\^',$mode,'table');
5065a41afe6SChristopher Smith        $this->Lexer->addEntryPattern('[\t ]*\n\|',$mode,'table');
5070cecf9d5Sandi    }
5080cecf9d5Sandi
5090cecf9d5Sandi    function postConnect() {
5100cecf9d5Sandi        $this->Lexer->addPattern('\n\^','table');
5110cecf9d5Sandi        $this->Lexer->addPattern('\n\|','table');
51225b97867Shakan.sandell        $this->Lexer->addPattern('[\t ]*:::[\t ]*(?=[\|\^])','table');
5139ab75d9eSAndreas Gohr        $this->Lexer->addPattern('[\t ]+','table');
5140cecf9d5Sandi        $this->Lexer->addPattern('\^','table');
5150cecf9d5Sandi        $this->Lexer->addPattern('\|','table');
5160cecf9d5Sandi        $this->Lexer->addExitPattern('\n','table');
5170cecf9d5Sandi    }
518107b01d6Sandi
519107b01d6Sandi    function getSort() {
520107b01d6Sandi        return 60;
521107b01d6Sandi    }
5220cecf9d5Sandi}
5230cecf9d5Sandi
5240cecf9d5Sandi//-------------------------------------------------------------------
525107b01d6Sandiclass Doku_Parser_Mode_unformatted extends Doku_Parser_Mode {
5260cecf9d5Sandi
5270cecf9d5Sandi    function connectTo($mode) {
52887858f84Schris        $this->Lexer->addEntryPattern('<nowiki>(?=.*</nowiki>)',$mode,'unformatted');
5290cecf9d5Sandi        $this->Lexer->addEntryPattern('%%(?=.*%%)',$mode,'unformattedalt');
5300cecf9d5Sandi    }
5310cecf9d5Sandi
5320cecf9d5Sandi    function postConnect() {
5330cecf9d5Sandi        $this->Lexer->addExitPattern('</nowiki>','unformatted');
5340cecf9d5Sandi        $this->Lexer->addExitPattern('%%','unformattedalt');
5350cecf9d5Sandi        $this->Lexer->mapHandler('unformattedalt','unformatted');
5360cecf9d5Sandi    }
5370cecf9d5Sandi
538107b01d6Sandi    function getSort() {
539107b01d6Sandi        return 170;
540107b01d6Sandi    }
5410cecf9d5Sandi}
5420cecf9d5Sandi
5430cecf9d5Sandi//-------------------------------------------------------------------
544107b01d6Sandiclass Doku_Parser_Mode_php extends Doku_Parser_Mode {
5450cecf9d5Sandi
5460cecf9d5Sandi    function connectTo($mode) {
54787858f84Schris        $this->Lexer->addEntryPattern('<php>(?=.*</php>)',$mode,'php');
54807f89c3cSAnika Henke        $this->Lexer->addEntryPattern('<PHP>(?=.*</PHP>)',$mode,'phpblock');
5490cecf9d5Sandi    }
5500cecf9d5Sandi
5510cecf9d5Sandi    function postConnect() {
5520cecf9d5Sandi        $this->Lexer->addExitPattern('</php>','php');
55307f89c3cSAnika Henke        $this->Lexer->addExitPattern('</PHP>','phpblock');
5540cecf9d5Sandi    }
5550cecf9d5Sandi
556107b01d6Sandi    function getSort() {
557107b01d6Sandi        return 180;
558107b01d6Sandi    }
5590cecf9d5Sandi}
5600cecf9d5Sandi
5610cecf9d5Sandi//-------------------------------------------------------------------
562107b01d6Sandiclass Doku_Parser_Mode_html extends Doku_Parser_Mode {
5630cecf9d5Sandi
5640cecf9d5Sandi    function connectTo($mode) {
56587858f84Schris        $this->Lexer->addEntryPattern('<html>(?=.*</html>)',$mode,'html');
56607f89c3cSAnika Henke        $this->Lexer->addEntryPattern('<HTML>(?=.*</HTML>)',$mode,'htmlblock');
5670cecf9d5Sandi    }
5680cecf9d5Sandi
5690cecf9d5Sandi    function postConnect() {
5700cecf9d5Sandi        $this->Lexer->addExitPattern('</html>','html');
57107f89c3cSAnika Henke        $this->Lexer->addExitPattern('</HTML>','htmlblock');
5720cecf9d5Sandi    }
5730cecf9d5Sandi
574107b01d6Sandi    function getSort() {
575107b01d6Sandi        return 190;
576107b01d6Sandi    }
5770cecf9d5Sandi}
5780cecf9d5Sandi
5790cecf9d5Sandi//-------------------------------------------------------------------
580107b01d6Sandiclass Doku_Parser_Mode_preformatted extends Doku_Parser_Mode {
5810cecf9d5Sandi
5820cecf9d5Sandi    function connectTo($mode) {
5830cecf9d5Sandi        // Has hard coded awareness of lists...
5840cecf9d5Sandi        $this->Lexer->addEntryPattern('\n  (?![\*\-])',$mode,'preformatted');
5850cecf9d5Sandi        $this->Lexer->addEntryPattern('\n\t(?![\*\-])',$mode,'preformatted');
5860cecf9d5Sandi
5870cecf9d5Sandi        // How to effect a sub pattern with the Lexer!
5880cecf9d5Sandi        $this->Lexer->addPattern('\n  ','preformatted');
5890cecf9d5Sandi        $this->Lexer->addPattern('\n\t','preformatted');
5900cecf9d5Sandi
5910cecf9d5Sandi    }
5920cecf9d5Sandi
5930cecf9d5Sandi    function postConnect() {
5940cecf9d5Sandi        $this->Lexer->addExitPattern('\n','preformatted');
5950cecf9d5Sandi    }
5960cecf9d5Sandi
597107b01d6Sandi    function getSort() {
598107b01d6Sandi        return 20;
599107b01d6Sandi    }
6000cecf9d5Sandi}
6010cecf9d5Sandi
6020cecf9d5Sandi//-------------------------------------------------------------------
603107b01d6Sandiclass Doku_Parser_Mode_code extends Doku_Parser_Mode {
6040cecf9d5Sandi
6050cecf9d5Sandi    function connectTo($mode) {
606fc498a42SChristopher Smith        $this->Lexer->addEntryPattern('<code\b(?=.*</code>)',$mode,'code');
6070cecf9d5Sandi    }
6080cecf9d5Sandi
6090cecf9d5Sandi    function postConnect() {
6100cecf9d5Sandi        $this->Lexer->addExitPattern('</code>','code');
6110cecf9d5Sandi    }
6120cecf9d5Sandi
613107b01d6Sandi    function getSort() {
614107b01d6Sandi        return 200;
615107b01d6Sandi    }
6160cecf9d5Sandi}
6170cecf9d5Sandi
6180cecf9d5Sandi//-------------------------------------------------------------------
619107b01d6Sandiclass Doku_Parser_Mode_file extends Doku_Parser_Mode {
6200cecf9d5Sandi
6210cecf9d5Sandi    function connectTo($mode) {
622fc498a42SChristopher Smith        $this->Lexer->addEntryPattern('<file\b(?=.*</file>)',$mode,'file');
6230cecf9d5Sandi    }
6240cecf9d5Sandi
6250cecf9d5Sandi    function postConnect() {
6260cecf9d5Sandi        $this->Lexer->addExitPattern('</file>','file');
6270cecf9d5Sandi    }
6280cecf9d5Sandi
629107b01d6Sandi    function getSort() {
630107b01d6Sandi        return 210;
631107b01d6Sandi    }
6320cecf9d5Sandi}
6330cecf9d5Sandi
6340cecf9d5Sandi//-------------------------------------------------------------------
635107b01d6Sandiclass Doku_Parser_Mode_quote extends Doku_Parser_Mode {
6360cecf9d5Sandi
637107b01d6Sandi    function Doku_Parser_Mode_quote() {
638ee20e7d1Sandi        global $PARSER_MODES;
6390cecf9d5Sandi
6400cecf9d5Sandi        $this->allowedModes = array_merge (
641ee20e7d1Sandi                $PARSER_MODES['formatting'],
642ee20e7d1Sandi                $PARSER_MODES['substition'],
643ee20e7d1Sandi                $PARSER_MODES['disabled'],
644ee20e7d1Sandi                $PARSER_MODES['protected'] #XXX new
6450cecf9d5Sandi            );
646ee20e7d1Sandi            #$this->allowedModes[] = 'footnote';
647ee20e7d1Sandi            #$this->allowedModes[] = 'preformatted';
648ee20e7d1Sandi            #$this->allowedModes[] = 'unformatted';
6490cecf9d5Sandi    }
6500cecf9d5Sandi
6510cecf9d5Sandi    function connectTo($mode) {
6520cecf9d5Sandi        $this->Lexer->addEntryPattern('\n>{1,}',$mode,'quote');
6530cecf9d5Sandi    }
6540cecf9d5Sandi
6550cecf9d5Sandi    function postConnect() {
6560cecf9d5Sandi        $this->Lexer->addPattern('\n>{1,}','quote');
6570cecf9d5Sandi        $this->Lexer->addExitPattern('\n','quote');
6580cecf9d5Sandi    }
6590cecf9d5Sandi
660107b01d6Sandi    function getSort() {
661107b01d6Sandi        return 220;
662107b01d6Sandi    }
6630cecf9d5Sandi}
6640cecf9d5Sandi
6650cecf9d5Sandi//-------------------------------------------------------------------
666107b01d6Sandiclass Doku_Parser_Mode_acronym extends Doku_Parser_Mode {
6670cecf9d5Sandi    // A list
6680cecf9d5Sandi    var $acronyms = array();
6690cecf9d5Sandi    var $pattern = '';
6700cecf9d5Sandi
671107b01d6Sandi    function Doku_Parser_Mode_acronym($acronyms) {
6727cc4b757SChris Smith        usort($acronyms,array($this,'_compare'));
6730cecf9d5Sandi        $this->acronyms = $acronyms;
6740cecf9d5Sandi    }
6750cecf9d5Sandi
6760cecf9d5Sandi    function preConnect() {
677901c1c87SAndreas Gohr        if(!count($this->acronyms)) return;
678901c1c87SAndreas Gohr
6798e266198SAndreas Gohr        $bound = '[\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]';
680e6258e07SAndreas Gohr        $acronyms = array_map('Doku_Lexer_Escape',$this->acronyms);
6818e266198SAndreas Gohr        $this->pattern = '(?<=^|'.$bound.')(?:'.join('|',$acronyms).')(?='.$bound.')';
6820cecf9d5Sandi    }
6830cecf9d5Sandi
6840cecf9d5Sandi    function connectTo($mode) {
685901c1c87SAndreas Gohr        if(!count($this->acronyms)) return;
686901c1c87SAndreas Gohr
6870cecf9d5Sandi        if ( strlen($this->pattern) > 0 ) {
6880cecf9d5Sandi            $this->Lexer->addSpecialPattern($this->pattern,$mode,'acronym');
6890cecf9d5Sandi        }
6900cecf9d5Sandi    }
6910cecf9d5Sandi
692107b01d6Sandi    function getSort() {
693107b01d6Sandi        return 240;
694107b01d6Sandi    }
6957cc4b757SChris Smith
6967cc4b757SChris Smith    /**
6977cc4b757SChris Smith     * sort callback to order by string length descending
6987cc4b757SChris Smith     */
6997cc4b757SChris Smith    function _compare($a,$b) {
7007cc4b757SChris Smith        $a_len = strlen($a);
7017cc4b757SChris Smith        $b_len = strlen($b);
7027cc4b757SChris Smith        if ($a_len > $b_len) {
7037cc4b757SChris Smith            return -1;
7047cc4b757SChris Smith        } else if ($a_len < $b_len) {
7057cc4b757SChris Smith            return 1;
7067cc4b757SChris Smith        }
7077cc4b757SChris Smith
7087cc4b757SChris Smith        return 0;
7097cc4b757SChris Smith    }
7100cecf9d5Sandi}
7110cecf9d5Sandi
7120cecf9d5Sandi//-------------------------------------------------------------------
713107b01d6Sandiclass Doku_Parser_Mode_smiley extends Doku_Parser_Mode {
7140cecf9d5Sandi    // A list
7150cecf9d5Sandi    var $smileys = array();
7160cecf9d5Sandi    var $pattern = '';
7170cecf9d5Sandi
718107b01d6Sandi    function Doku_Parser_Mode_smiley($smileys) {
7190cecf9d5Sandi        $this->smileys = $smileys;
7200cecf9d5Sandi    }
7210cecf9d5Sandi
7220cecf9d5Sandi    function preConnect() {
723d4834a19SStephane Chazelas        if(!count($this->smileys) || $this->pattern != '') return;
724901c1c87SAndreas Gohr
7250cecf9d5Sandi        $sep = '';
7260cecf9d5Sandi        foreach ( $this->smileys as $smiley ) {
7271b26635bSAndreas Gohr            $this->pattern .= $sep.'(?<=\W|^)'.Doku_Lexer_Escape($smiley).'(?=\W|$)';
7280cecf9d5Sandi            $sep = '|';
7290cecf9d5Sandi        }
7300cecf9d5Sandi    }
7310cecf9d5Sandi
7320cecf9d5Sandi    function connectTo($mode) {
733901c1c87SAndreas Gohr        if(!count($this->smileys)) return;
734901c1c87SAndreas Gohr
7350cecf9d5Sandi        if ( strlen($this->pattern) > 0 ) {
7360cecf9d5Sandi            $this->Lexer->addSpecialPattern($this->pattern,$mode,'smiley');
7370cecf9d5Sandi        }
7380cecf9d5Sandi    }
7390cecf9d5Sandi
740107b01d6Sandi    function getSort() {
741107b01d6Sandi        return 230;
742107b01d6Sandi    }
7430cecf9d5Sandi}
7440cecf9d5Sandi
7450cecf9d5Sandi//-------------------------------------------------------------------
746107b01d6Sandiclass Doku_Parser_Mode_wordblock extends Doku_Parser_Mode {
7470cecf9d5Sandi    // A list
7480cecf9d5Sandi    var $badwords = array();
7490cecf9d5Sandi    var $pattern = '';
7500cecf9d5Sandi
751107b01d6Sandi    function Doku_Parser_Mode_wordblock($badwords) {
7520cecf9d5Sandi        $this->badwords = $badwords;
7530cecf9d5Sandi    }
7540cecf9d5Sandi
7550cecf9d5Sandi    function preConnect() {
7560cecf9d5Sandi
757d4834a19SStephane Chazelas        if ( count($this->badwords) == 0 || $this->pattern != '') {
7580cecf9d5Sandi            return;
7590cecf9d5Sandi        }
7600cecf9d5Sandi
7610cecf9d5Sandi        $sep = '';
7620cecf9d5Sandi        foreach ( $this->badwords as $badword ) {
7630cecf9d5Sandi            $this->pattern .= $sep.'(?<=\b)(?i)'.Doku_Lexer_Escape($badword).'(?-i)(?=\b)';
7640cecf9d5Sandi            $sep = '|';
7650cecf9d5Sandi        }
7660cecf9d5Sandi
7670cecf9d5Sandi    }
7680cecf9d5Sandi
7690cecf9d5Sandi    function connectTo($mode) {
7700cecf9d5Sandi        if ( strlen($this->pattern) > 0 ) {
7710cecf9d5Sandi            $this->Lexer->addSpecialPattern($this->pattern,$mode,'wordblock');
7720cecf9d5Sandi        }
7730cecf9d5Sandi    }
7740cecf9d5Sandi
775107b01d6Sandi    function getSort() {
776107b01d6Sandi        return 250;
777107b01d6Sandi    }
7780cecf9d5Sandi}
7790cecf9d5Sandi
7800cecf9d5Sandi//-------------------------------------------------------------------
781107b01d6Sandiclass Doku_Parser_Mode_entity extends Doku_Parser_Mode {
7820cecf9d5Sandi    // A list
7830cecf9d5Sandi    var $entities = array();
7840cecf9d5Sandi    var $pattern = '';
7850cecf9d5Sandi
786107b01d6Sandi    function Doku_Parser_Mode_entity($entities) {
7870cecf9d5Sandi        $this->entities = $entities;
7880cecf9d5Sandi    }
7890cecf9d5Sandi
7900cecf9d5Sandi    function preConnect() {
791d4834a19SStephane Chazelas        if(!count($this->entities) || $this->pattern != '') return;
792901c1c87SAndreas Gohr
7930cecf9d5Sandi        $sep = '';
7940cecf9d5Sandi        foreach ( $this->entities as $entity ) {
7950cecf9d5Sandi            $this->pattern .= $sep.Doku_Lexer_Escape($entity);
7960cecf9d5Sandi            $sep = '|';
7970cecf9d5Sandi        }
7980cecf9d5Sandi    }
7990cecf9d5Sandi
8000cecf9d5Sandi    function connectTo($mode) {
801901c1c87SAndreas Gohr        if(!count($this->entities)) return;
802901c1c87SAndreas Gohr
8030cecf9d5Sandi        if ( strlen($this->pattern) > 0 ) {
8040cecf9d5Sandi            $this->Lexer->addSpecialPattern($this->pattern,$mode,'entity');
8050cecf9d5Sandi        }
8060cecf9d5Sandi    }
8070cecf9d5Sandi
808107b01d6Sandi    function getSort() {
809107b01d6Sandi        return 260;
810107b01d6Sandi    }
8110cecf9d5Sandi}
8120cecf9d5Sandi
8130cecf9d5Sandi//-------------------------------------------------------------------
8140cecf9d5Sandi// Implements the 640x480 replacement
815107b01d6Sandiclass Doku_Parser_Mode_multiplyentity extends Doku_Parser_Mode {
8160cecf9d5Sandi
8170cecf9d5Sandi    function connectTo($mode) {
8180cecf9d5Sandi
8190cecf9d5Sandi        $this->Lexer->addSpecialPattern(
82068df1afcSChris Smith                    '(?<=\b)(?:[1-9]|\d{2,})[xX]\d+(?=\b)',$mode,'multiplyentity'
8210cecf9d5Sandi                );
8220cecf9d5Sandi
8230cecf9d5Sandi    }
8240cecf9d5Sandi
825107b01d6Sandi    function getSort() {
826107b01d6Sandi        return 270;
827107b01d6Sandi    }
8280cecf9d5Sandi}
8290cecf9d5Sandi
8300cecf9d5Sandi//-------------------------------------------------------------------
831107b01d6Sandiclass Doku_Parser_Mode_quotes extends Doku_Parser_Mode {
8320cecf9d5Sandi
8330cecf9d5Sandi    function connectTo($mode) {
8349426a41aSAndreas Gohr        global $conf;
8359426a41aSAndreas Gohr
8365fc8a925SAndreas Gohr        $ws   =  '\s/\#~:+=&%@\-\x28\x29\]\[{}><"\'';   // whitespace
8375fc8a925SAndreas Gohr        $punc =  ';,\.?!';
8380cecf9d5Sandi
8399426a41aSAndreas Gohr        if($conf['typography'] == 2){
8400cecf9d5Sandi            $this->Lexer->addSpecialPattern(
8415fc8a925SAndreas Gohr                        "(?<=^|[$ws])'(?=[^$ws$punc])",$mode,'singlequoteopening'
8420cecf9d5Sandi                    );
8430cecf9d5Sandi            $this->Lexer->addSpecialPattern(
8445fc8a925SAndreas Gohr                        "(?<=^|[^$ws]|[$punc])'(?=$|[$ws$punc])",$mode,'singlequoteclosing'
8450cecf9d5Sandi                    );
8460cecf9d5Sandi            $this->Lexer->addSpecialPattern(
8475fc8a925SAndreas Gohr                        "(?<=^|[^$ws$punc])'(?=$|[^$ws$punc])",$mode,'apostrophe'
8480cecf9d5Sandi                    );
8499426a41aSAndreas Gohr        }
8509426a41aSAndreas Gohr
8510cecf9d5Sandi        $this->Lexer->addSpecialPattern(
8525fc8a925SAndreas Gohr                    "(?<=^|[$ws])\"(?=[^$ws$punc])",$mode,'doublequoteopening'
8530cecf9d5Sandi                );
85457d757d1SAndreas Gohr        $this->Lexer->addSpecialPattern(
8555fc8a925SAndreas Gohr                    "\"",$mode,'doublequoteclosing'
85657d757d1SAndreas Gohr                );
85757d757d1SAndreas Gohr
8580cecf9d5Sandi    }
8590cecf9d5Sandi
860107b01d6Sandi    function getSort() {
861107b01d6Sandi        return 280;
862107b01d6Sandi    }
8630cecf9d5Sandi}
8640cecf9d5Sandi
8650cecf9d5Sandi//-------------------------------------------------------------------
866107b01d6Sandiclass Doku_Parser_Mode_camelcaselink extends Doku_Parser_Mode {
8670cecf9d5Sandi
8680cecf9d5Sandi    function connectTo($mode) {
8690cecf9d5Sandi        $this->Lexer->addSpecialPattern(
8700cecf9d5Sandi                '\b[A-Z]+[a-z]+[A-Z][A-Za-z]*\b',$mode,'camelcaselink'
8710cecf9d5Sandi            );
8720cecf9d5Sandi    }
8730cecf9d5Sandi
874107b01d6Sandi    function getSort() {
875107b01d6Sandi        return 290;
876107b01d6Sandi    }
8770cecf9d5Sandi}
8780cecf9d5Sandi
8790cecf9d5Sandi//-------------------------------------------------------------------
880107b01d6Sandiclass Doku_Parser_Mode_internallink extends Doku_Parser_Mode {
8810cecf9d5Sandi
8820cecf9d5Sandi    function connectTo($mode) {
8830cecf9d5Sandi        // Word boundaries?
88445a0fa15SAdrian Lang        $this->Lexer->addSpecialPattern("\[\[(?:(?:[^[\]]*?\[.*?\])|.*?)\]\]",$mode,'internallink');
8850cecf9d5Sandi    }
8860cecf9d5Sandi
887107b01d6Sandi    function getSort() {
888107b01d6Sandi        return 300;
889107b01d6Sandi    }
8900cecf9d5Sandi}
8910cecf9d5Sandi
8920cecf9d5Sandi//-------------------------------------------------------------------
893107b01d6Sandiclass Doku_Parser_Mode_media extends Doku_Parser_Mode {
8940cecf9d5Sandi
8950cecf9d5Sandi    function connectTo($mode) {
8960cecf9d5Sandi        // Word boundaries?
8970cecf9d5Sandi        $this->Lexer->addSpecialPattern("\{\{[^\}]+\}\}",$mode,'media');
8980cecf9d5Sandi    }
8990cecf9d5Sandi
900107b01d6Sandi    function getSort() {
901107b01d6Sandi        return 320;
902107b01d6Sandi    }
9030cecf9d5Sandi}
9040cecf9d5Sandi
9050cecf9d5Sandi//-------------------------------------------------------------------
906107b01d6Sandiclass Doku_Parser_Mode_rss extends Doku_Parser_Mode {
907b625487dSandi
908b625487dSandi    function connectTo($mode) {
909b625487dSandi        $this->Lexer->addSpecialPattern("\{\{rss>[^\}]+\}\}",$mode,'rss');
910b625487dSandi    }
911b625487dSandi
912107b01d6Sandi    function getSort() {
913107b01d6Sandi        return 310;
914107b01d6Sandi    }
915b625487dSandi}
916b625487dSandi
917b625487dSandi//-------------------------------------------------------------------
918107b01d6Sandiclass Doku_Parser_Mode_externallink extends Doku_Parser_Mode {
91936f2d7c1SGina Haeussge    var $schemes = array();
9200cecf9d5Sandi    var $patterns = array();
9210cecf9d5Sandi
9220cecf9d5Sandi    function preConnect() {
923d4834a19SStephane Chazelas        if(count($this->patterns)) return;
9240cecf9d5Sandi
9250cecf9d5Sandi        $ltrs = '\w';
9265d190f12SAndreas Gohr        $gunk = '/\#~:.?+=&%@!\-\[\]';
9270cecf9d5Sandi        $punc = '.:?\-;,';
9280cecf9d5Sandi        $host = $ltrs.$punc;
9290cecf9d5Sandi        $any  = $ltrs.$gunk.$punc;
9300cecf9d5Sandi
93136f2d7c1SGina Haeussge        $this->schemes = getSchemes();
9320cecf9d5Sandi        foreach ( $this->schemes as $scheme ) {
9336f0c5dbfSandi            $this->patterns[] = '\b(?i)'.$scheme.'(?-i)://['.$any.']+?(?=['.$punc.']*[^'.$any.'])';
9340cecf9d5Sandi        }
9350cecf9d5Sandi
9366f0c5dbfSandi        $this->patterns[] = '\b(?i)www?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])';
9376f0c5dbfSandi        $this->patterns[] = '\b(?i)ftp?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])';
9380cecf9d5Sandi    }
9390cecf9d5Sandi
9400cecf9d5Sandi    function connectTo($mode) {
941d4834a19SStephane Chazelas
9420cecf9d5Sandi        foreach ( $this->patterns as $pattern ) {
9430cecf9d5Sandi            $this->Lexer->addSpecialPattern($pattern,$mode,'externallink');
9440cecf9d5Sandi        }
9450cecf9d5Sandi    }
9460cecf9d5Sandi
947107b01d6Sandi    function getSort() {
948107b01d6Sandi        return 330;
949107b01d6Sandi    }
9500cecf9d5Sandi}
9510cecf9d5Sandi
9520cecf9d5Sandi//-------------------------------------------------------------------
953107b01d6Sandiclass Doku_Parser_Mode_filelink extends Doku_Parser_Mode {
9540cecf9d5Sandi
9550cecf9d5Sandi    var $pattern;
9560cecf9d5Sandi
9570cecf9d5Sandi    function preConnect() {
9580cecf9d5Sandi
9590cecf9d5Sandi        $ltrs = '\w';
9600cecf9d5Sandi        $gunk = '/\#~:.?+=&%@!\-';
9610cecf9d5Sandi        $punc = '.:?\-;,';
9620cecf9d5Sandi        $host = $ltrs.$punc;
9630cecf9d5Sandi        $any  = $ltrs.$gunk.$punc;
9640cecf9d5Sandi
9650cecf9d5Sandi        $this->pattern = '\b(?i)file(?-i)://['.$any.']+?['.
9660cecf9d5Sandi            $punc.']*[^'.$any.']';
9670cecf9d5Sandi    }
9680cecf9d5Sandi
9690cecf9d5Sandi    function connectTo($mode) {
9700cecf9d5Sandi        $this->Lexer->addSpecialPattern(
9710cecf9d5Sandi            $this->pattern,$mode,'filelink');
9720cecf9d5Sandi    }
9730cecf9d5Sandi
974107b01d6Sandi    function getSort() {
975107b01d6Sandi        return 360;
976107b01d6Sandi    }
9770cecf9d5Sandi}
9780cecf9d5Sandi
9790cecf9d5Sandi//-------------------------------------------------------------------
980107b01d6Sandiclass Doku_Parser_Mode_windowssharelink extends Doku_Parser_Mode {
9810cecf9d5Sandi
9820cecf9d5Sandi    var $pattern;
9830cecf9d5Sandi
9840cecf9d5Sandi    function preConnect() {
985bfdeb23fSlupo49        $this->pattern = "\\\\\\\\\w+?(?:\\\\[\w-$]+)+";
9860cecf9d5Sandi    }
9870cecf9d5Sandi
9880cecf9d5Sandi    function connectTo($mode) {
9890cecf9d5Sandi        $this->Lexer->addSpecialPattern(
9900cecf9d5Sandi            $this->pattern,$mode,'windowssharelink');
9910cecf9d5Sandi    }
9920cecf9d5Sandi
993107b01d6Sandi    function getSort() {
994107b01d6Sandi        return 350;
995107b01d6Sandi    }
9960cecf9d5Sandi}
9970cecf9d5Sandi
9980cecf9d5Sandi//-------------------------------------------------------------------
999107b01d6Sandiclass Doku_Parser_Mode_emaillink extends Doku_Parser_Mode {
10000cecf9d5Sandi
10010cecf9d5Sandi    function connectTo($mode) {
10020a1d30bfSchris        // pattern below is defined in inc/mail.php
10030a1d30bfSchris        $this->Lexer->addSpecialPattern('<'.PREG_PATTERN_VALID_EMAIL.'>',$mode,'emaillink');
10040cecf9d5Sandi    }
10050cecf9d5Sandi
1006107b01d6Sandi    function getSort() {
1007107b01d6Sandi        return 340;
1008107b01d6Sandi    }
10090cecf9d5Sandi}
10100cecf9d5Sandi
1011340756e4Sandi
1012e3776c06SMichael Hamann//Setup VIM: ex: et ts=4 :
1013