xref: /dokuwiki/inc/parser/parser.php (revision f50a239b3b819527445d240746b09a05fb76d103)
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
64276820f7SScrutinizer Auto-Fixer    /**
65276820f7SScrutinizer Auto-Fixer     * @param Doku_Parser_Mode_base $BaseMode
66276820f7SScrutinizer Auto-Fixer     */
6745e8987eSChristopher Smith    function addBaseMode($BaseMode) {
6845e8987eSChristopher Smith        $this->modes['base'] = $BaseMode;
690cecf9d5Sandi        if ( !$this->Lexer ) {
7067f9913dSAndreas Gohr            $this->Lexer = new Doku_Lexer($this->Handler,'base', true);
710cecf9d5Sandi        }
7245e8987eSChristopher Smith        $this->modes['base']->Lexer = $this->Lexer;
730cecf9d5Sandi    }
740cecf9d5Sandi
750cecf9d5Sandi    /**
760cecf9d5Sandi     * PHP preserves order of associative elements
770cecf9d5Sandi     * Mode sequence is important
78*f50a239bSTakamura     *
79*f50a239bSTakamura     * @param string $name
80*f50a239bSTakamura     * @param Doku_Parser_Mode_Interface $Mode
810cecf9d5Sandi     */
8245e8987eSChristopher Smith    function addMode($name, Doku_Parser_Mode_Interface $Mode) {
830cecf9d5Sandi        if ( !isset($this->modes['base']) ) {
84107b01d6Sandi            $this->addBaseMode(new Doku_Parser_Mode_base());
850cecf9d5Sandi        }
8645e8987eSChristopher Smith        $Mode->Lexer = $this->Lexer;
8745e8987eSChristopher Smith        $this->modes[$name] = $Mode;
880cecf9d5Sandi    }
890cecf9d5Sandi
900cecf9d5Sandi    function connectModes() {
910cecf9d5Sandi
920cecf9d5Sandi        if ( $this->connected ) {
930cecf9d5Sandi            return;
940cecf9d5Sandi        }
950cecf9d5Sandi
960cecf9d5Sandi        foreach ( array_keys($this->modes) as $mode ) {
970cecf9d5Sandi
980cecf9d5Sandi            // Base isn't connected to anything
990cecf9d5Sandi            if ( $mode == 'base' ) {
1000cecf9d5Sandi                continue;
1010cecf9d5Sandi            }
1020cecf9d5Sandi            $this->modes[$mode]->preConnect();
1030cecf9d5Sandi
1040cecf9d5Sandi            foreach ( array_keys($this->modes) as $cm ) {
1050cecf9d5Sandi
1060cecf9d5Sandi                if ( $this->modes[$cm]->accepts($mode) ) {
1070cecf9d5Sandi                    $this->modes[$mode]->connectTo($cm);
1080cecf9d5Sandi                }
1090cecf9d5Sandi
1100cecf9d5Sandi            }
1110cecf9d5Sandi
1120cecf9d5Sandi            $this->modes[$mode]->postConnect();
1130cecf9d5Sandi        }
1140cecf9d5Sandi
11544881bd0Shenning.noren        $this->connected = true;
1160cecf9d5Sandi    }
1170cecf9d5Sandi
1180cecf9d5Sandi    function parse($doc) {
1190cecf9d5Sandi        if ( $this->Lexer ) {
1200cecf9d5Sandi            $this->connectModes();
1210cecf9d5Sandi            // Normalize CRs and pad doc
1220cecf9d5Sandi            $doc = "\n".str_replace("\r\n","\n",$doc)."\n";
1230cecf9d5Sandi            $this->Lexer->parse($doc);
124433bef32Sandi            $this->Handler->_finalize();
1250cecf9d5Sandi            return $this->Handler->calls;
1260cecf9d5Sandi        } else {
12744881bd0Shenning.noren            return false;
1280cecf9d5Sandi        }
1290cecf9d5Sandi    }
1300cecf9d5Sandi
1310cecf9d5Sandi}
1320cecf9d5Sandi
1330cecf9d5Sandi//-------------------------------------------------------------------
1345a3e1f53SAndreas Gohr
1355a3e1f53SAndreas Gohr/**
1365a3e1f53SAndreas Gohr * Class Doku_Parser_Mode_Interface
1375a3e1f53SAndreas Gohr *
1385a3e1f53SAndreas Gohr * Defines a mode (syntax component) in the Parser
1395a3e1f53SAndreas Gohr */
1405a3e1f53SAndreas Gohrinterface Doku_Parser_Mode_Interface {
1415a3e1f53SAndreas Gohr    /**
1425a3e1f53SAndreas Gohr     * returns a number used to determine in which order modes are added
1435a3e1f53SAndreas Gohr     */
1445a3e1f53SAndreas Gohr    public function getSort();
1455a3e1f53SAndreas Gohr
1465a3e1f53SAndreas Gohr    /**
1475a3e1f53SAndreas Gohr     * Called before any calls to connectTo
148276820f7SScrutinizer Auto-Fixer     * @return void
1495a3e1f53SAndreas Gohr     */
1505a3e1f53SAndreas Gohr    function preConnect();
1515a3e1f53SAndreas Gohr
1525a3e1f53SAndreas Gohr    /**
1535a3e1f53SAndreas Gohr     * Connects the mode
1545a3e1f53SAndreas Gohr     *
1555a3e1f53SAndreas Gohr     * @param string $mode
156276820f7SScrutinizer Auto-Fixer     * @return void
1575a3e1f53SAndreas Gohr     */
1585a3e1f53SAndreas Gohr    function connectTo($mode);
1595a3e1f53SAndreas Gohr
1605a3e1f53SAndreas Gohr    /**
1615a3e1f53SAndreas Gohr     * Called after all calls to connectTo
162276820f7SScrutinizer Auto-Fixer     * @return void
1635a3e1f53SAndreas Gohr     */
1645a3e1f53SAndreas Gohr    function postConnect();
1655a3e1f53SAndreas Gohr
1665a3e1f53SAndreas Gohr    /**
1675a3e1f53SAndreas Gohr     * Check if given mode is accepted inside this mode
1685a3e1f53SAndreas Gohr     *
1695a3e1f53SAndreas Gohr     * @param string $mode
1705a3e1f53SAndreas Gohr     * @return bool
1715a3e1f53SAndreas Gohr     */
1725a3e1f53SAndreas Gohr    function accepts($mode);
1735a3e1f53SAndreas Gohr}
1745a3e1f53SAndreas Gohr
1750cecf9d5Sandi/**
17672d89f96SAndreas Gohr * This class and all the subclasses below are used to reduce the effort required to register
17772d89f96SAndreas Gohr * modes with the Lexer.
17872d89f96SAndreas Gohr *
1790b7c14c2Sandi * @author Harry Fuecks <hfuecks@gmail.com>
1800cecf9d5Sandi */
1815a3e1f53SAndreas Gohrclass Doku_Parser_Mode implements Doku_Parser_Mode_Interface {
182e3ab6fc5SMichael Hamann    /**
183e3ab6fc5SMichael Hamann     * @var Doku_Lexer $Lexer
184e3ab6fc5SMichael Hamann     */
1850cecf9d5Sandi    var $Lexer;
1860cecf9d5Sandi    var $allowedModes = array();
1870cecf9d5Sandi
188107b01d6Sandi    function getSort() {
189107b01d6Sandi        trigger_error('getSort() not implemented in '.get_class($this), E_USER_WARNING);
190107b01d6Sandi    }
191107b01d6Sandi
1920cecf9d5Sandi    function preConnect() {}
1930cecf9d5Sandi    function connectTo($mode) {}
1940cecf9d5Sandi    function postConnect() {}
1950cecf9d5Sandi    function accepts($mode) {
1966f9bd982SAndreas Gohr        return in_array($mode, (array) $this->allowedModes );
1970cecf9d5Sandi    }
1985a3e1f53SAndreas Gohr}
1990cecf9d5Sandi
2005a3e1f53SAndreas Gohr/**
2015a3e1f53SAndreas Gohr * Basically the same as Doku_Parser_Mode but extends from DokuWiki_Plugin
2025a3e1f53SAndreas Gohr *
2035a3e1f53SAndreas Gohr * Adds additional functions to syntax plugins
2045a3e1f53SAndreas Gohr */
2055a3e1f53SAndreas Gohrclass Doku_Parser_Mode_Plugin extends DokuWiki_Plugin implements Doku_Parser_Mode_Interface {
2065a3e1f53SAndreas Gohr    /**
2075a3e1f53SAndreas Gohr     * @var Doku_Lexer $Lexer
2085a3e1f53SAndreas Gohr     */
2095a3e1f53SAndreas Gohr    var $Lexer;
2105a3e1f53SAndreas Gohr    var $allowedModes = array();
2115a3e1f53SAndreas Gohr
2127ac0b9feSAndreas Gohr    /**
2137ac0b9feSAndreas Gohr     * Sort for applying this mode
2147ac0b9feSAndreas Gohr     *
2157ac0b9feSAndreas Gohr     * @return int
2167ac0b9feSAndreas Gohr     */
2175a3e1f53SAndreas Gohr    function getSort() {
2185a3e1f53SAndreas Gohr        trigger_error('getSort() not implemented in '.get_class($this), E_USER_WARNING);
2195a3e1f53SAndreas Gohr    }
2205a3e1f53SAndreas Gohr
2215a3e1f53SAndreas Gohr    function preConnect() {}
2225a3e1f53SAndreas Gohr    function connectTo($mode) {}
2235a3e1f53SAndreas Gohr    function postConnect() {}
2245a3e1f53SAndreas Gohr    function accepts($mode) {
2255a3e1f53SAndreas Gohr        return in_array($mode, (array) $this->allowedModes );
2265a3e1f53SAndreas Gohr    }
2270cecf9d5Sandi}
2280cecf9d5Sandi
2290cecf9d5Sandi//-------------------------------------------------------------------
230107b01d6Sandiclass Doku_Parser_Mode_base extends Doku_Parser_Mode {
2310cecf9d5Sandi
23226e22ab8SChristopher Smith    function __construct() {
233ee20e7d1Sandi        global $PARSER_MODES;
2340cecf9d5Sandi
2350cecf9d5Sandi        $this->allowedModes = array_merge (
236ee20e7d1Sandi                $PARSER_MODES['container'],
237ee20e7d1Sandi                $PARSER_MODES['baseonly'],
238ee20e7d1Sandi                $PARSER_MODES['paragraphs'],
239ee20e7d1Sandi                $PARSER_MODES['formatting'],
240ee20e7d1Sandi                $PARSER_MODES['substition'],
241ee20e7d1Sandi                $PARSER_MODES['protected'],
242ee20e7d1Sandi                $PARSER_MODES['disabled']
2430cecf9d5Sandi            );
2440cecf9d5Sandi    }
245107b01d6Sandi
246107b01d6Sandi    function getSort() {
247107b01d6Sandi        return 0;
248107b01d6Sandi    }
2490cecf9d5Sandi}
2500cecf9d5Sandi
2510cecf9d5Sandi//-------------------------------------------------------------------
252107b01d6Sandiclass Doku_Parser_Mode_footnote extends Doku_Parser_Mode {
2530cecf9d5Sandi
25426e22ab8SChristopher Smith    function __construct() {
255ee20e7d1Sandi        global $PARSER_MODES;
2560cecf9d5Sandi
2570cecf9d5Sandi        $this->allowedModes = array_merge (
258ee20e7d1Sandi                $PARSER_MODES['container'],
259ee20e7d1Sandi                $PARSER_MODES['formatting'],
260ee20e7d1Sandi                $PARSER_MODES['substition'],
261ee20e7d1Sandi                $PARSER_MODES['protected'],
262ee20e7d1Sandi                $PARSER_MODES['disabled']
2630cecf9d5Sandi            );
2640cecf9d5Sandi
2652fe7363dSchris        unset($this->allowedModes[array_search('footnote', $this->allowedModes)]);
2660cecf9d5Sandi    }
2670cecf9d5Sandi
2680cecf9d5Sandi    function connectTo($mode) {
2690cecf9d5Sandi        $this->Lexer->addEntryPattern(
2700cecf9d5Sandi            '\x28\x28(?=.*\x29\x29)',$mode,'footnote'
2710cecf9d5Sandi            );
2720cecf9d5Sandi    }
2730cecf9d5Sandi
2740cecf9d5Sandi    function postConnect() {
2750cecf9d5Sandi        $this->Lexer->addExitPattern(
2760cecf9d5Sandi            '\x29\x29','footnote'
2770cecf9d5Sandi            );
2780cecf9d5Sandi    }
2790cecf9d5Sandi
280107b01d6Sandi    function getSort() {
281107b01d6Sandi        return 150;
282107b01d6Sandi    }
2830cecf9d5Sandi}
2840cecf9d5Sandi
2850cecf9d5Sandi//-------------------------------------------------------------------
286107b01d6Sandiclass Doku_Parser_Mode_header extends Doku_Parser_Mode {
2870cecf9d5Sandi
2889fa736b0SAndreas Gohr    function connectTo($mode) {
289506ae684Sandi        //we're not picky about the closing ones, two are enough
2900cecf9d5Sandi        $this->Lexer->addSpecialPattern(
29130fe9cd6SAndreas Gohr                            '[ \t]*={2,}[^\n]+={2,}[ \t]*(?=\n)',
2929fa736b0SAndreas Gohr                            $mode,
2930cecf9d5Sandi                            'header'
2940cecf9d5Sandi                        );
2950cecf9d5Sandi    }
2960cecf9d5Sandi
297107b01d6Sandi    function getSort() {
298107b01d6Sandi        return 50;
299107b01d6Sandi    }
3000cecf9d5Sandi}
3010cecf9d5Sandi
3020cecf9d5Sandi//-------------------------------------------------------------------
303107b01d6Sandiclass Doku_Parser_Mode_notoc extends Doku_Parser_Mode {
3040cecf9d5Sandi
3050cecf9d5Sandi    function connectTo($mode) {
3060cecf9d5Sandi        $this->Lexer->addSpecialPattern('~~NOTOC~~',$mode,'notoc');
3070cecf9d5Sandi    }
3080cecf9d5Sandi
309107b01d6Sandi    function getSort() {
310107b01d6Sandi        return 30;
311107b01d6Sandi    }
3120cecf9d5Sandi}
3130cecf9d5Sandi
3140cecf9d5Sandi//-------------------------------------------------------------------
315107b01d6Sandiclass Doku_Parser_Mode_nocache extends Doku_Parser_Mode {
3169dc2c2afSandi
3179dc2c2afSandi    function connectTo($mode) {
3189dc2c2afSandi        $this->Lexer->addSpecialPattern('~~NOCACHE~~',$mode,'nocache');
3199dc2c2afSandi    }
3209dc2c2afSandi
321107b01d6Sandi    function getSort() {
322107b01d6Sandi        return 40;
323107b01d6Sandi    }
3249dc2c2afSandi}
3259dc2c2afSandi
3269dc2c2afSandi//-------------------------------------------------------------------
327107b01d6Sandiclass Doku_Parser_Mode_linebreak extends Doku_Parser_Mode {
3280cecf9d5Sandi
3290cecf9d5Sandi    function connectTo($mode) {
33030897fecSChris Smith        $this->Lexer->addSpecialPattern('\x5C{2}(?:[ \t]|(?=\n))',$mode,'linebreak');
3310cecf9d5Sandi    }
332107b01d6Sandi
333107b01d6Sandi    function getSort() {
334107b01d6Sandi        return 140;
335107b01d6Sandi    }
3360cecf9d5Sandi}
3370cecf9d5Sandi
3380cecf9d5Sandi//-------------------------------------------------------------------
339107b01d6Sandiclass Doku_Parser_Mode_eol extends Doku_Parser_Mode {
3400cecf9d5Sandi
3410cecf9d5Sandi    function connectTo($mode) {
3420cecf9d5Sandi        $badModes = array('listblock','table');
3430cecf9d5Sandi        if ( in_array($mode, $badModes) ) {
3440cecf9d5Sandi            return;
3450cecf9d5Sandi        }
34695c19ce7SChris Smith        // see FS#1652, pattern extended to swallow preceding whitespace to avoid issues with lines that only contain whitespace
34795c19ce7SChris Smith        $this->Lexer->addSpecialPattern('(?:^[ \t]*)?\n',$mode,'eol');
3480cecf9d5Sandi    }
349107b01d6Sandi
350107b01d6Sandi    function getSort() {
351107b01d6Sandi        return 370;
352107b01d6Sandi    }
3530cecf9d5Sandi}
3540cecf9d5Sandi
3550cecf9d5Sandi//-------------------------------------------------------------------
356107b01d6Sandiclass Doku_Parser_Mode_hr extends Doku_Parser_Mode {
3570cecf9d5Sandi
3580cecf9d5Sandi    function connectTo($mode) {
3596f0c5dbfSandi        $this->Lexer->addSpecialPattern('\n[ \t]*-{4,}[ \t]*(?=\n)',$mode,'hr');
3600cecf9d5Sandi    }
3610cecf9d5Sandi
362107b01d6Sandi    function getSort() {
363107b01d6Sandi        return 160;
364107b01d6Sandi    }
3650cecf9d5Sandi}
3660cecf9d5Sandi
3670cecf9d5Sandi//-------------------------------------------------------------------
36803b54bb0SThorsten Staerk/**
36903b54bb0SThorsten Staerk * This class sets the markup for bold (=strong),
37003b54bb0SThorsten Staerk * italic (=emphasis), underline etc.
37103b54bb0SThorsten Staerk */
372107b01d6Sandiclass Doku_Parser_Mode_formatting extends Doku_Parser_Mode {
3730cecf9d5Sandi    var $type;
3740cecf9d5Sandi
3750cecf9d5Sandi    var $formatting = array (
3760cecf9d5Sandi        'strong' => array (
3770cecf9d5Sandi            'entry'=>'\*\*(?=.*\*\*)',
3780cecf9d5Sandi            'exit'=>'\*\*',
379107b01d6Sandi            'sort'=>70
3800cecf9d5Sandi            ),
3810cecf9d5Sandi
3820cecf9d5Sandi        'emphasis'=> array (
38324b0ff2aSAndreas Gohr            'entry'=>'//(?=[^\x00]*[^:])', //hack for bugs #384 #763 #1468
3840cecf9d5Sandi            'exit'=>'//',
385107b01d6Sandi            'sort'=>80
3860cecf9d5Sandi            ),
3870cecf9d5Sandi
3880cecf9d5Sandi        'underline'=> array (
3890cecf9d5Sandi            'entry'=>'__(?=.*__)',
3900cecf9d5Sandi            'exit'=>'__',
391107b01d6Sandi            'sort'=>90
3920cecf9d5Sandi            ),
3930cecf9d5Sandi
3940cecf9d5Sandi        'monospace'=> array (
3950cecf9d5Sandi            'entry'=>'\x27\x27(?=.*\x27\x27)',
3960cecf9d5Sandi            'exit'=>'\x27\x27',
397107b01d6Sandi            'sort'=>100
3980cecf9d5Sandi            ),
3990cecf9d5Sandi
4000cecf9d5Sandi        'subscript'=> array (
40187858f84Schris            'entry'=>'<sub>(?=.*</sub>)',
4020cecf9d5Sandi            'exit'=>'</sub>',
403107b01d6Sandi            'sort'=>110
4040cecf9d5Sandi            ),
4050cecf9d5Sandi
4060cecf9d5Sandi        'superscript'=> array (
40787858f84Schris            'entry'=>'<sup>(?=.*</sup>)',
4080cecf9d5Sandi            'exit'=>'</sup>',
409107b01d6Sandi            'sort'=>120
4100cecf9d5Sandi            ),
4110cecf9d5Sandi
4120cecf9d5Sandi        'deleted'=> array (
41387858f84Schris            'entry'=>'<del>(?=.*</del>)',
4140cecf9d5Sandi            'exit'=>'</del>',
415107b01d6Sandi            'sort'=>130
4160cecf9d5Sandi            ),
4170cecf9d5Sandi        );
4180cecf9d5Sandi
419276820f7SScrutinizer Auto-Fixer    /**
420276820f7SScrutinizer Auto-Fixer     * @param string $type
421276820f7SScrutinizer Auto-Fixer     */
42226e22ab8SChristopher Smith    function __construct($type) {
423ee20e7d1Sandi        global $PARSER_MODES;
4240cecf9d5Sandi
4250cecf9d5Sandi        if ( !array_key_exists($type, $this->formatting) ) {
4260cecf9d5Sandi            trigger_error('Invalid formatting type '.$type, E_USER_WARNING);
4270cecf9d5Sandi        }
4280cecf9d5Sandi
4290cecf9d5Sandi        $this->type = $type;
4300cecf9d5Sandi
431ee20e7d1Sandi        // formatting may contain other formatting but not it self
432ee20e7d1Sandi        $modes = $PARSER_MODES['formatting'];
433ee20e7d1Sandi        $key = array_search($type, $modes);
434ee20e7d1Sandi        if ( is_int($key) ) {
435ee20e7d1Sandi            unset($modes[$key]);
436ee20e7d1Sandi        }
4370cecf9d5Sandi
438ee20e7d1Sandi        $this->allowedModes = array_merge (
439ee20e7d1Sandi                $modes,
440ee20e7d1Sandi                $PARSER_MODES['substition'],
441ee20e7d1Sandi                $PARSER_MODES['disabled']
442ee20e7d1Sandi            );
4430cecf9d5Sandi    }
4440cecf9d5Sandi
4450cecf9d5Sandi    function connectTo($mode) {
4460cecf9d5Sandi
4470cecf9d5Sandi        // Can't nest formatting in itself
4480cecf9d5Sandi        if ( $mode == $this->type ) {
4490cecf9d5Sandi            return;
4500cecf9d5Sandi        }
4510cecf9d5Sandi
4520cecf9d5Sandi        $this->Lexer->addEntryPattern(
4530cecf9d5Sandi                $this->formatting[$this->type]['entry'],
4540cecf9d5Sandi                $mode,
4550cecf9d5Sandi                $this->type
4560cecf9d5Sandi            );
4570cecf9d5Sandi    }
4580cecf9d5Sandi
4590cecf9d5Sandi    function postConnect() {
4600cecf9d5Sandi
4610cecf9d5Sandi        $this->Lexer->addExitPattern(
4620cecf9d5Sandi            $this->formatting[$this->type]['exit'],
4630cecf9d5Sandi            $this->type
4640cecf9d5Sandi            );
4650cecf9d5Sandi
4660cecf9d5Sandi    }
467107b01d6Sandi
468107b01d6Sandi    function getSort() {
469107b01d6Sandi        return $this->formatting[$this->type]['sort'];
470107b01d6Sandi    }
4710cecf9d5Sandi}
4720cecf9d5Sandi
4730cecf9d5Sandi//-------------------------------------------------------------------
474107b01d6Sandiclass Doku_Parser_Mode_listblock extends Doku_Parser_Mode {
4750cecf9d5Sandi
47626e22ab8SChristopher Smith    function __construct() {
477ee20e7d1Sandi        global $PARSER_MODES;
4780cecf9d5Sandi
4790cecf9d5Sandi        $this->allowedModes = array_merge (
480ee20e7d1Sandi                $PARSER_MODES['formatting'],
481ee20e7d1Sandi                $PARSER_MODES['substition'],
482ee20e7d1Sandi                $PARSER_MODES['disabled'],
483ee20e7d1Sandi                $PARSER_MODES['protected'] #XXX new
4840cecf9d5Sandi            );
485702eb898Sandi
486ee20e7d1Sandi    //    $this->allowedModes[] = 'footnote';
4870cecf9d5Sandi    }
4880cecf9d5Sandi
4890cecf9d5Sandi    function connectTo($mode) {
49013ebcbe5SChristopher Smith        $this->Lexer->addEntryPattern('[ \t]*\n {2,}[\-\*]',$mode,'listblock');
49113ebcbe5SChristopher Smith        $this->Lexer->addEntryPattern('[ \t]*\n\t{1,}[\-\*]',$mode,'listblock');
4920cecf9d5Sandi
4930cecf9d5Sandi        $this->Lexer->addPattern('\n {2,}[\-\*]','listblock');
4940cecf9d5Sandi        $this->Lexer->addPattern('\n\t{1,}[\-\*]','listblock');
4950cecf9d5Sandi
4960cecf9d5Sandi    }
4970cecf9d5Sandi
4980cecf9d5Sandi    function postConnect() {
4990cecf9d5Sandi        $this->Lexer->addExitPattern('\n','listblock');
5000cecf9d5Sandi    }
501107b01d6Sandi
502107b01d6Sandi    function getSort() {
503107b01d6Sandi        return 10;
504107b01d6Sandi    }
5050cecf9d5Sandi}
5060cecf9d5Sandi
5070cecf9d5Sandi//-------------------------------------------------------------------
508107b01d6Sandiclass Doku_Parser_Mode_table extends Doku_Parser_Mode {
5090cecf9d5Sandi
51026e22ab8SChristopher Smith    function __construct() {
511ee20e7d1Sandi        global $PARSER_MODES;
5120cecf9d5Sandi
5130cecf9d5Sandi        $this->allowedModes = array_merge (
514ee20e7d1Sandi                $PARSER_MODES['formatting'],
515ee20e7d1Sandi                $PARSER_MODES['substition'],
516ee20e7d1Sandi                $PARSER_MODES['disabled'],
517107b01d6Sandi                $PARSER_MODES['protected']
5180cecf9d5Sandi            );
5190cecf9d5Sandi    }
5200cecf9d5Sandi
5210cecf9d5Sandi    function connectTo($mode) {
5225a41afe6SChristopher Smith        $this->Lexer->addEntryPattern('[\t ]*\n\^',$mode,'table');
5235a41afe6SChristopher Smith        $this->Lexer->addEntryPattern('[\t ]*\n\|',$mode,'table');
5240cecf9d5Sandi    }
5250cecf9d5Sandi
5260cecf9d5Sandi    function postConnect() {
5270cecf9d5Sandi        $this->Lexer->addPattern('\n\^','table');
5280cecf9d5Sandi        $this->Lexer->addPattern('\n\|','table');
52925b97867Shakan.sandell        $this->Lexer->addPattern('[\t ]*:::[\t ]*(?=[\|\^])','table');
5309ab75d9eSAndreas Gohr        $this->Lexer->addPattern('[\t ]+','table');
5310cecf9d5Sandi        $this->Lexer->addPattern('\^','table');
5320cecf9d5Sandi        $this->Lexer->addPattern('\|','table');
5330cecf9d5Sandi        $this->Lexer->addExitPattern('\n','table');
5340cecf9d5Sandi    }
535107b01d6Sandi
536107b01d6Sandi    function getSort() {
537107b01d6Sandi        return 60;
538107b01d6Sandi    }
5390cecf9d5Sandi}
5400cecf9d5Sandi
5410cecf9d5Sandi//-------------------------------------------------------------------
542107b01d6Sandiclass Doku_Parser_Mode_unformatted extends Doku_Parser_Mode {
5430cecf9d5Sandi
5440cecf9d5Sandi    function connectTo($mode) {
54587858f84Schris        $this->Lexer->addEntryPattern('<nowiki>(?=.*</nowiki>)',$mode,'unformatted');
5460cecf9d5Sandi        $this->Lexer->addEntryPattern('%%(?=.*%%)',$mode,'unformattedalt');
5470cecf9d5Sandi    }
5480cecf9d5Sandi
5490cecf9d5Sandi    function postConnect() {
5500cecf9d5Sandi        $this->Lexer->addExitPattern('</nowiki>','unformatted');
5510cecf9d5Sandi        $this->Lexer->addExitPattern('%%','unformattedalt');
5520cecf9d5Sandi        $this->Lexer->mapHandler('unformattedalt','unformatted');
5530cecf9d5Sandi    }
5540cecf9d5Sandi
555107b01d6Sandi    function getSort() {
556107b01d6Sandi        return 170;
557107b01d6Sandi    }
5580cecf9d5Sandi}
5590cecf9d5Sandi
5600cecf9d5Sandi//-------------------------------------------------------------------
561107b01d6Sandiclass Doku_Parser_Mode_php extends Doku_Parser_Mode {
5620cecf9d5Sandi
5630cecf9d5Sandi    function connectTo($mode) {
56487858f84Schris        $this->Lexer->addEntryPattern('<php>(?=.*</php>)',$mode,'php');
56507f89c3cSAnika Henke        $this->Lexer->addEntryPattern('<PHP>(?=.*</PHP>)',$mode,'phpblock');
5660cecf9d5Sandi    }
5670cecf9d5Sandi
5680cecf9d5Sandi    function postConnect() {
5690cecf9d5Sandi        $this->Lexer->addExitPattern('</php>','php');
57007f89c3cSAnika Henke        $this->Lexer->addExitPattern('</PHP>','phpblock');
5710cecf9d5Sandi    }
5720cecf9d5Sandi
573107b01d6Sandi    function getSort() {
574107b01d6Sandi        return 180;
575107b01d6Sandi    }
5760cecf9d5Sandi}
5770cecf9d5Sandi
5780cecf9d5Sandi//-------------------------------------------------------------------
579107b01d6Sandiclass Doku_Parser_Mode_html extends Doku_Parser_Mode {
5800cecf9d5Sandi
5810cecf9d5Sandi    function connectTo($mode) {
58287858f84Schris        $this->Lexer->addEntryPattern('<html>(?=.*</html>)',$mode,'html');
58307f89c3cSAnika Henke        $this->Lexer->addEntryPattern('<HTML>(?=.*</HTML>)',$mode,'htmlblock');
5840cecf9d5Sandi    }
5850cecf9d5Sandi
5860cecf9d5Sandi    function postConnect() {
5870cecf9d5Sandi        $this->Lexer->addExitPattern('</html>','html');
58807f89c3cSAnika Henke        $this->Lexer->addExitPattern('</HTML>','htmlblock');
5890cecf9d5Sandi    }
5900cecf9d5Sandi
591107b01d6Sandi    function getSort() {
592107b01d6Sandi        return 190;
593107b01d6Sandi    }
5940cecf9d5Sandi}
5950cecf9d5Sandi
5960cecf9d5Sandi//-------------------------------------------------------------------
597107b01d6Sandiclass Doku_Parser_Mode_preformatted extends Doku_Parser_Mode {
5980cecf9d5Sandi
5990cecf9d5Sandi    function connectTo($mode) {
6000cecf9d5Sandi        // Has hard coded awareness of lists...
6010cecf9d5Sandi        $this->Lexer->addEntryPattern('\n  (?![\*\-])',$mode,'preformatted');
6020cecf9d5Sandi        $this->Lexer->addEntryPattern('\n\t(?![\*\-])',$mode,'preformatted');
6030cecf9d5Sandi
6040cecf9d5Sandi        // How to effect a sub pattern with the Lexer!
6050cecf9d5Sandi        $this->Lexer->addPattern('\n  ','preformatted');
6060cecf9d5Sandi        $this->Lexer->addPattern('\n\t','preformatted');
6070cecf9d5Sandi
6080cecf9d5Sandi    }
6090cecf9d5Sandi
6100cecf9d5Sandi    function postConnect() {
6110cecf9d5Sandi        $this->Lexer->addExitPattern('\n','preformatted');
6120cecf9d5Sandi    }
6130cecf9d5Sandi
614107b01d6Sandi    function getSort() {
615107b01d6Sandi        return 20;
616107b01d6Sandi    }
6170cecf9d5Sandi}
6180cecf9d5Sandi
6190cecf9d5Sandi//-------------------------------------------------------------------
620107b01d6Sandiclass Doku_Parser_Mode_code extends Doku_Parser_Mode {
6210cecf9d5Sandi
6220cecf9d5Sandi    function connectTo($mode) {
623fc498a42SChristopher Smith        $this->Lexer->addEntryPattern('<code\b(?=.*</code>)',$mode,'code');
6240cecf9d5Sandi    }
6250cecf9d5Sandi
6260cecf9d5Sandi    function postConnect() {
6270cecf9d5Sandi        $this->Lexer->addExitPattern('</code>','code');
6280cecf9d5Sandi    }
6290cecf9d5Sandi
630107b01d6Sandi    function getSort() {
631107b01d6Sandi        return 200;
632107b01d6Sandi    }
6330cecf9d5Sandi}
6340cecf9d5Sandi
6350cecf9d5Sandi//-------------------------------------------------------------------
636107b01d6Sandiclass Doku_Parser_Mode_file extends Doku_Parser_Mode {
6370cecf9d5Sandi
6380cecf9d5Sandi    function connectTo($mode) {
639fc498a42SChristopher Smith        $this->Lexer->addEntryPattern('<file\b(?=.*</file>)',$mode,'file');
6400cecf9d5Sandi    }
6410cecf9d5Sandi
6420cecf9d5Sandi    function postConnect() {
6430cecf9d5Sandi        $this->Lexer->addExitPattern('</file>','file');
6440cecf9d5Sandi    }
6450cecf9d5Sandi
646107b01d6Sandi    function getSort() {
647107b01d6Sandi        return 210;
648107b01d6Sandi    }
6490cecf9d5Sandi}
6500cecf9d5Sandi
6510cecf9d5Sandi//-------------------------------------------------------------------
652107b01d6Sandiclass Doku_Parser_Mode_quote extends Doku_Parser_Mode {
6530cecf9d5Sandi
65426e22ab8SChristopher Smith    function __construct() {
655ee20e7d1Sandi        global $PARSER_MODES;
6560cecf9d5Sandi
6570cecf9d5Sandi        $this->allowedModes = array_merge (
658ee20e7d1Sandi                $PARSER_MODES['formatting'],
659ee20e7d1Sandi                $PARSER_MODES['substition'],
660ee20e7d1Sandi                $PARSER_MODES['disabled'],
661ee20e7d1Sandi                $PARSER_MODES['protected'] #XXX new
6620cecf9d5Sandi            );
663ee20e7d1Sandi            #$this->allowedModes[] = 'footnote';
664ee20e7d1Sandi            #$this->allowedModes[] = 'preformatted';
665ee20e7d1Sandi            #$this->allowedModes[] = 'unformatted';
6660cecf9d5Sandi    }
6670cecf9d5Sandi
6680cecf9d5Sandi    function connectTo($mode) {
6690cecf9d5Sandi        $this->Lexer->addEntryPattern('\n>{1,}',$mode,'quote');
6700cecf9d5Sandi    }
6710cecf9d5Sandi
6720cecf9d5Sandi    function postConnect() {
6730cecf9d5Sandi        $this->Lexer->addPattern('\n>{1,}','quote');
6740cecf9d5Sandi        $this->Lexer->addExitPattern('\n','quote');
6750cecf9d5Sandi    }
6760cecf9d5Sandi
677107b01d6Sandi    function getSort() {
678107b01d6Sandi        return 220;
679107b01d6Sandi    }
6800cecf9d5Sandi}
6810cecf9d5Sandi
6820cecf9d5Sandi//-------------------------------------------------------------------
683107b01d6Sandiclass Doku_Parser_Mode_acronym extends Doku_Parser_Mode {
6840cecf9d5Sandi    // A list
6850cecf9d5Sandi    var $acronyms = array();
6860cecf9d5Sandi    var $pattern = '';
6870cecf9d5Sandi
68826e22ab8SChristopher Smith    function __construct($acronyms) {
6897cc4b757SChris Smith        usort($acronyms,array($this,'_compare'));
6900cecf9d5Sandi        $this->acronyms = $acronyms;
6910cecf9d5Sandi    }
6920cecf9d5Sandi
6930cecf9d5Sandi    function preConnect() {
694901c1c87SAndreas Gohr        if(!count($this->acronyms)) return;
695901c1c87SAndreas Gohr
6968e266198SAndreas Gohr        $bound = '[\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]';
697e6258e07SAndreas Gohr        $acronyms = array_map('Doku_Lexer_Escape',$this->acronyms);
6988e266198SAndreas Gohr        $this->pattern = '(?<=^|'.$bound.')(?:'.join('|',$acronyms).')(?='.$bound.')';
6990cecf9d5Sandi    }
7000cecf9d5Sandi
7010cecf9d5Sandi    function connectTo($mode) {
702901c1c87SAndreas Gohr        if(!count($this->acronyms)) return;
703901c1c87SAndreas Gohr
7040cecf9d5Sandi        if ( strlen($this->pattern) > 0 ) {
7050cecf9d5Sandi            $this->Lexer->addSpecialPattern($this->pattern,$mode,'acronym');
7060cecf9d5Sandi        }
7070cecf9d5Sandi    }
7080cecf9d5Sandi
709107b01d6Sandi    function getSort() {
710107b01d6Sandi        return 240;
711107b01d6Sandi    }
7127cc4b757SChris Smith
7137cc4b757SChris Smith    /**
7147cc4b757SChris Smith     * sort callback to order by string length descending
715*f50a239bSTakamura     *
716*f50a239bSTakamura     * @param string $a
717*f50a239bSTakamura     * @param string $b
718*f50a239bSTakamura     *
719*f50a239bSTakamura     * @return int
7207cc4b757SChris Smith     */
7217cc4b757SChris Smith    function _compare($a,$b) {
7227cc4b757SChris Smith        $a_len = strlen($a);
7237cc4b757SChris Smith        $b_len = strlen($b);
7247cc4b757SChris Smith        if ($a_len > $b_len) {
7257cc4b757SChris Smith            return -1;
7267cc4b757SChris Smith        } else if ($a_len < $b_len) {
7277cc4b757SChris Smith            return 1;
7287cc4b757SChris Smith        }
7297cc4b757SChris Smith
7307cc4b757SChris Smith        return 0;
7317cc4b757SChris Smith    }
7320cecf9d5Sandi}
7330cecf9d5Sandi
7340cecf9d5Sandi//-------------------------------------------------------------------
735107b01d6Sandiclass Doku_Parser_Mode_smiley extends Doku_Parser_Mode {
7360cecf9d5Sandi    // A list
7370cecf9d5Sandi    var $smileys = array();
7380cecf9d5Sandi    var $pattern = '';
7390cecf9d5Sandi
74026e22ab8SChristopher Smith    function __construct($smileys) {
7410cecf9d5Sandi        $this->smileys = $smileys;
7420cecf9d5Sandi    }
7430cecf9d5Sandi
7440cecf9d5Sandi    function preConnect() {
745d4834a19SStephane Chazelas        if(!count($this->smileys) || $this->pattern != '') return;
746901c1c87SAndreas Gohr
7470cecf9d5Sandi        $sep = '';
7480cecf9d5Sandi        foreach ( $this->smileys as $smiley ) {
7491b26635bSAndreas Gohr            $this->pattern .= $sep.'(?<=\W|^)'.Doku_Lexer_Escape($smiley).'(?=\W|$)';
7500cecf9d5Sandi            $sep = '|';
7510cecf9d5Sandi        }
7520cecf9d5Sandi    }
7530cecf9d5Sandi
7540cecf9d5Sandi    function connectTo($mode) {
755901c1c87SAndreas Gohr        if(!count($this->smileys)) return;
756901c1c87SAndreas Gohr
7570cecf9d5Sandi        if ( strlen($this->pattern) > 0 ) {
7580cecf9d5Sandi            $this->Lexer->addSpecialPattern($this->pattern,$mode,'smiley');
7590cecf9d5Sandi        }
7600cecf9d5Sandi    }
7610cecf9d5Sandi
762107b01d6Sandi    function getSort() {
763107b01d6Sandi        return 230;
764107b01d6Sandi    }
7650cecf9d5Sandi}
7660cecf9d5Sandi
7670cecf9d5Sandi//-------------------------------------------------------------------
768107b01d6Sandiclass Doku_Parser_Mode_wordblock extends Doku_Parser_Mode {
7690cecf9d5Sandi    // A list
7700cecf9d5Sandi    var $badwords = array();
7710cecf9d5Sandi    var $pattern = '';
7720cecf9d5Sandi
77326e22ab8SChristopher Smith    function __construct($badwords) {
7740cecf9d5Sandi        $this->badwords = $badwords;
7750cecf9d5Sandi    }
7760cecf9d5Sandi
7770cecf9d5Sandi    function preConnect() {
7780cecf9d5Sandi
779d4834a19SStephane Chazelas        if ( count($this->badwords) == 0 || $this->pattern != '') {
7800cecf9d5Sandi            return;
7810cecf9d5Sandi        }
7820cecf9d5Sandi
7830cecf9d5Sandi        $sep = '';
7840cecf9d5Sandi        foreach ( $this->badwords as $badword ) {
7850cecf9d5Sandi            $this->pattern .= $sep.'(?<=\b)(?i)'.Doku_Lexer_Escape($badword).'(?-i)(?=\b)';
7860cecf9d5Sandi            $sep = '|';
7870cecf9d5Sandi        }
7880cecf9d5Sandi
7890cecf9d5Sandi    }
7900cecf9d5Sandi
7910cecf9d5Sandi    function connectTo($mode) {
7920cecf9d5Sandi        if ( strlen($this->pattern) > 0 ) {
7930cecf9d5Sandi            $this->Lexer->addSpecialPattern($this->pattern,$mode,'wordblock');
7940cecf9d5Sandi        }
7950cecf9d5Sandi    }
7960cecf9d5Sandi
797107b01d6Sandi    function getSort() {
798107b01d6Sandi        return 250;
799107b01d6Sandi    }
8000cecf9d5Sandi}
8010cecf9d5Sandi
8020cecf9d5Sandi//-------------------------------------------------------------------
803107b01d6Sandiclass Doku_Parser_Mode_entity extends Doku_Parser_Mode {
8040cecf9d5Sandi    // A list
8050cecf9d5Sandi    var $entities = array();
8060cecf9d5Sandi    var $pattern = '';
8070cecf9d5Sandi
80826e22ab8SChristopher Smith    function __construct($entities) {
8090cecf9d5Sandi        $this->entities = $entities;
8100cecf9d5Sandi    }
8110cecf9d5Sandi
8120cecf9d5Sandi    function preConnect() {
813d4834a19SStephane Chazelas        if(!count($this->entities) || $this->pattern != '') return;
814901c1c87SAndreas Gohr
8150cecf9d5Sandi        $sep = '';
8160cecf9d5Sandi        foreach ( $this->entities as $entity ) {
8170cecf9d5Sandi            $this->pattern .= $sep.Doku_Lexer_Escape($entity);
8180cecf9d5Sandi            $sep = '|';
8190cecf9d5Sandi        }
8200cecf9d5Sandi    }
8210cecf9d5Sandi
8220cecf9d5Sandi    function connectTo($mode) {
823901c1c87SAndreas Gohr        if(!count($this->entities)) return;
824901c1c87SAndreas Gohr
8250cecf9d5Sandi        if ( strlen($this->pattern) > 0 ) {
8260cecf9d5Sandi            $this->Lexer->addSpecialPattern($this->pattern,$mode,'entity');
8270cecf9d5Sandi        }
8280cecf9d5Sandi    }
8290cecf9d5Sandi
830107b01d6Sandi    function getSort() {
831107b01d6Sandi        return 260;
832107b01d6Sandi    }
8330cecf9d5Sandi}
8340cecf9d5Sandi
8350cecf9d5Sandi//-------------------------------------------------------------------
8360cecf9d5Sandi// Implements the 640x480 replacement
837107b01d6Sandiclass Doku_Parser_Mode_multiplyentity extends Doku_Parser_Mode {
8380cecf9d5Sandi
8390cecf9d5Sandi    function connectTo($mode) {
8400cecf9d5Sandi
8410cecf9d5Sandi        $this->Lexer->addSpecialPattern(
84268df1afcSChris Smith                    '(?<=\b)(?:[1-9]|\d{2,})[xX]\d+(?=\b)',$mode,'multiplyentity'
8430cecf9d5Sandi                );
8440cecf9d5Sandi
8450cecf9d5Sandi    }
8460cecf9d5Sandi
847107b01d6Sandi    function getSort() {
848107b01d6Sandi        return 270;
849107b01d6Sandi    }
8500cecf9d5Sandi}
8510cecf9d5Sandi
8520cecf9d5Sandi//-------------------------------------------------------------------
853107b01d6Sandiclass Doku_Parser_Mode_quotes extends Doku_Parser_Mode {
8540cecf9d5Sandi
8550cecf9d5Sandi    function connectTo($mode) {
8569426a41aSAndreas Gohr        global $conf;
8579426a41aSAndreas Gohr
8585fc8a925SAndreas Gohr        $ws   =  '\s/\#~:+=&%@\-\x28\x29\]\[{}><"\'';   // whitespace
8595fc8a925SAndreas Gohr        $punc =  ';,\.?!';
8600cecf9d5Sandi
8619426a41aSAndreas Gohr        if($conf['typography'] == 2){
8620cecf9d5Sandi            $this->Lexer->addSpecialPattern(
8635fc8a925SAndreas Gohr                        "(?<=^|[$ws])'(?=[^$ws$punc])",$mode,'singlequoteopening'
8640cecf9d5Sandi                    );
8650cecf9d5Sandi            $this->Lexer->addSpecialPattern(
8665fc8a925SAndreas Gohr                        "(?<=^|[^$ws]|[$punc])'(?=$|[$ws$punc])",$mode,'singlequoteclosing'
8670cecf9d5Sandi                    );
8680cecf9d5Sandi            $this->Lexer->addSpecialPattern(
8695fc8a925SAndreas Gohr                        "(?<=^|[^$ws$punc])'(?=$|[^$ws$punc])",$mode,'apostrophe'
8700cecf9d5Sandi                    );
8719426a41aSAndreas Gohr        }
8729426a41aSAndreas Gohr
8730cecf9d5Sandi        $this->Lexer->addSpecialPattern(
8745fc8a925SAndreas Gohr                    "(?<=^|[$ws])\"(?=[^$ws$punc])",$mode,'doublequoteopening'
8750cecf9d5Sandi                );
87657d757d1SAndreas Gohr        $this->Lexer->addSpecialPattern(
8775fc8a925SAndreas Gohr                    "\"",$mode,'doublequoteclosing'
87857d757d1SAndreas Gohr                );
87957d757d1SAndreas Gohr
8800cecf9d5Sandi    }
8810cecf9d5Sandi
882107b01d6Sandi    function getSort() {
883107b01d6Sandi        return 280;
884107b01d6Sandi    }
8850cecf9d5Sandi}
8860cecf9d5Sandi
8870cecf9d5Sandi//-------------------------------------------------------------------
888107b01d6Sandiclass Doku_Parser_Mode_camelcaselink extends Doku_Parser_Mode {
8890cecf9d5Sandi
8900cecf9d5Sandi    function connectTo($mode) {
8910cecf9d5Sandi        $this->Lexer->addSpecialPattern(
8920cecf9d5Sandi                '\b[A-Z]+[a-z]+[A-Z][A-Za-z]*\b',$mode,'camelcaselink'
8930cecf9d5Sandi            );
8940cecf9d5Sandi    }
8950cecf9d5Sandi
896107b01d6Sandi    function getSort() {
897107b01d6Sandi        return 290;
898107b01d6Sandi    }
8990cecf9d5Sandi}
9000cecf9d5Sandi
9010cecf9d5Sandi//-------------------------------------------------------------------
902107b01d6Sandiclass Doku_Parser_Mode_internallink extends Doku_Parser_Mode {
9030cecf9d5Sandi
9040cecf9d5Sandi    function connectTo($mode) {
9050cecf9d5Sandi        // Word boundaries?
90645a0fa15SAdrian Lang        $this->Lexer->addSpecialPattern("\[\[(?:(?:[^[\]]*?\[.*?\])|.*?)\]\]",$mode,'internallink');
9070cecf9d5Sandi    }
9080cecf9d5Sandi
909107b01d6Sandi    function getSort() {
910107b01d6Sandi        return 300;
911107b01d6Sandi    }
9120cecf9d5Sandi}
9130cecf9d5Sandi
9140cecf9d5Sandi//-------------------------------------------------------------------
915107b01d6Sandiclass Doku_Parser_Mode_media extends Doku_Parser_Mode {
9160cecf9d5Sandi
9170cecf9d5Sandi    function connectTo($mode) {
9180cecf9d5Sandi        // Word boundaries?
9190cecf9d5Sandi        $this->Lexer->addSpecialPattern("\{\{[^\}]+\}\}",$mode,'media');
9200cecf9d5Sandi    }
9210cecf9d5Sandi
922107b01d6Sandi    function getSort() {
923107b01d6Sandi        return 320;
924107b01d6Sandi    }
9250cecf9d5Sandi}
9260cecf9d5Sandi
9270cecf9d5Sandi//-------------------------------------------------------------------
928107b01d6Sandiclass Doku_Parser_Mode_rss extends Doku_Parser_Mode {
929b625487dSandi
930b625487dSandi    function connectTo($mode) {
931b625487dSandi        $this->Lexer->addSpecialPattern("\{\{rss>[^\}]+\}\}",$mode,'rss');
932b625487dSandi    }
933b625487dSandi
934107b01d6Sandi    function getSort() {
935107b01d6Sandi        return 310;
936107b01d6Sandi    }
937b625487dSandi}
938b625487dSandi
939b625487dSandi//-------------------------------------------------------------------
940107b01d6Sandiclass Doku_Parser_Mode_externallink extends Doku_Parser_Mode {
94136f2d7c1SGina Haeussge    var $schemes = array();
9420cecf9d5Sandi    var $patterns = array();
9430cecf9d5Sandi
9440cecf9d5Sandi    function preConnect() {
945d4834a19SStephane Chazelas        if(count($this->patterns)) return;
9460cecf9d5Sandi
9470cecf9d5Sandi        $ltrs = '\w';
9485d190f12SAndreas Gohr        $gunk = '/\#~:.?+=&%@!\-\[\]';
9490cecf9d5Sandi        $punc = '.:?\-;,';
9500cecf9d5Sandi        $host = $ltrs.$punc;
9510cecf9d5Sandi        $any  = $ltrs.$gunk.$punc;
9520cecf9d5Sandi
95336f2d7c1SGina Haeussge        $this->schemes = getSchemes();
9540cecf9d5Sandi        foreach ( $this->schemes as $scheme ) {
9556f0c5dbfSandi            $this->patterns[] = '\b(?i)'.$scheme.'(?-i)://['.$any.']+?(?=['.$punc.']*[^'.$any.'])';
9560cecf9d5Sandi        }
9570cecf9d5Sandi
9586f0c5dbfSandi        $this->patterns[] = '\b(?i)www?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])';
9596f0c5dbfSandi        $this->patterns[] = '\b(?i)ftp?(?-i)\.['.$host.']+?\.['.$host.']+?['.$any.']+?(?=['.$punc.']*[^'.$any.'])';
9600cecf9d5Sandi    }
9610cecf9d5Sandi
9620cecf9d5Sandi    function connectTo($mode) {
963d4834a19SStephane Chazelas
9640cecf9d5Sandi        foreach ( $this->patterns as $pattern ) {
9650cecf9d5Sandi            $this->Lexer->addSpecialPattern($pattern,$mode,'externallink');
9660cecf9d5Sandi        }
9670cecf9d5Sandi    }
9680cecf9d5Sandi
969107b01d6Sandi    function getSort() {
970107b01d6Sandi        return 330;
971107b01d6Sandi    }
9720cecf9d5Sandi}
9730cecf9d5Sandi
9740cecf9d5Sandi//-------------------------------------------------------------------
975107b01d6Sandiclass Doku_Parser_Mode_filelink extends Doku_Parser_Mode {
9760cecf9d5Sandi
9770cecf9d5Sandi    var $pattern;
9780cecf9d5Sandi
9790cecf9d5Sandi    function preConnect() {
9800cecf9d5Sandi
9810cecf9d5Sandi        $ltrs = '\w';
9820cecf9d5Sandi        $gunk = '/\#~:.?+=&%@!\-';
9830cecf9d5Sandi        $punc = '.:?\-;,';
9840cecf9d5Sandi        $host = $ltrs.$punc;
9850cecf9d5Sandi        $any  = $ltrs.$gunk.$punc;
9860cecf9d5Sandi
9870cecf9d5Sandi        $this->pattern = '\b(?i)file(?-i)://['.$any.']+?['.
9880cecf9d5Sandi            $punc.']*[^'.$any.']';
9890cecf9d5Sandi    }
9900cecf9d5Sandi
9910cecf9d5Sandi    function connectTo($mode) {
9920cecf9d5Sandi        $this->Lexer->addSpecialPattern(
9930cecf9d5Sandi            $this->pattern,$mode,'filelink');
9940cecf9d5Sandi    }
9950cecf9d5Sandi
996107b01d6Sandi    function getSort() {
997107b01d6Sandi        return 360;
998107b01d6Sandi    }
9990cecf9d5Sandi}
10000cecf9d5Sandi
10010cecf9d5Sandi//-------------------------------------------------------------------
1002107b01d6Sandiclass Doku_Parser_Mode_windowssharelink extends Doku_Parser_Mode {
10030cecf9d5Sandi
10040cecf9d5Sandi    var $pattern;
10050cecf9d5Sandi
10060cecf9d5Sandi    function preConnect() {
1007bfdeb23fSlupo49        $this->pattern = "\\\\\\\\\w+?(?:\\\\[\w-$]+)+";
10080cecf9d5Sandi    }
10090cecf9d5Sandi
10100cecf9d5Sandi    function connectTo($mode) {
10110cecf9d5Sandi        $this->Lexer->addSpecialPattern(
10120cecf9d5Sandi            $this->pattern,$mode,'windowssharelink');
10130cecf9d5Sandi    }
10140cecf9d5Sandi
1015107b01d6Sandi    function getSort() {
1016107b01d6Sandi        return 350;
1017107b01d6Sandi    }
10180cecf9d5Sandi}
10190cecf9d5Sandi
10200cecf9d5Sandi//-------------------------------------------------------------------
1021107b01d6Sandiclass Doku_Parser_Mode_emaillink extends Doku_Parser_Mode {
10220cecf9d5Sandi
10230cecf9d5Sandi    function connectTo($mode) {
10240a1d30bfSchris        // pattern below is defined in inc/mail.php
10250a1d30bfSchris        $this->Lexer->addSpecialPattern('<'.PREG_PATTERN_VALID_EMAIL.'>',$mode,'emaillink');
10260cecf9d5Sandi    }
10270cecf9d5Sandi
1028107b01d6Sandi    function getSort() {
1029107b01d6Sandi        return 340;
1030107b01d6Sandi    }
10310cecf9d5Sandi}
10320cecf9d5Sandi
1033340756e4Sandi
1034e3776c06SMichael Hamann//Setup VIM: ex: et ts=4 :
1035