1<?php
2
3if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
4if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
5require_once(DOKU_PLUGIN.'syntax.php');
6
7/**
8 * All DokuWiki plugins to extend the parser/rendering mechanism
9 * need to inherit from this class
10 */
11class syntax_plugin_revealjs_fragment extends DokuWiki_Syntax_Plugin {
12
13    public function getType() { return 'container'; }
14    public function getAllowedTypes() { return array('formatting', 'substition', 'disabled'); }
15    public function getSort() { return 33; } // must be after fragmentblock and fragmentlist, otherwise to much matches
16    public function getPType() { return 'normal'; }
17
18
19    /**
20     * Connect lookup pattern to lexer.
21     *
22     * @param $aMode String The desired rendermode.
23     * @return none
24     * @public
25     * @see render()
26     */
27    public function connectTo($mode) {
28        $this->Lexer->addEntryPattern('<fragment\b.*?>(?=[\s\S]*?<\/fragment>)', $mode, 'plugin_revealjs_fragment');
29    }
30    public function postConnect() { $this->Lexer->addExitPattern('<\/fragment>','plugin_revealjs_fragment'); }
31
32
33    /**
34     * Handler to prepare matched data for the rendering process.
35     *
36     * @param $aMatch String The text matched by the patterns.
37     * @param $aState Integer The lexer state for the match.
38     * @param $aPos Integer The character position of the matched text.
39     * @param $aHandler Object Reference to the Doku_Handler object.
40     * @return Integer The current lexer state for the match.
41     * @public
42     * @see render()
43     * @static
44     */
45    public function handle($match, $state, $pos, Doku_Handler $handler) {
46        switch ($state) {
47            case DOKU_LEXER_ENTER :
48                list($type, $param1, $param2) = preg_split("/\s+/", substr($match, 1, -1), 3);
49                if ($param1) {
50                    if ($this->_is_valid_style($param1)) $style = $param1;
51                    elseif (intval($param1) > 0) $index = $param1;
52                }
53                if ($param2) {
54                    if (intval($param2) > 0) $index = $param2;
55                    elseif ($this->_is_valid_style($param2)) $style = $param2;
56                }
57                return array($state, array($style, $index));
58
59            case DOKU_LEXER_UNMATCHED :  return array($state, $match);
60            case DOKU_LEXER_EXIT :       return array($state, '');
61        }
62    }
63
64
65    /**
66     * Handle the actual output creation.
67     *
68     * @param $aFormat String The output format to generate.
69     * @param $aRenderer Object A reference to the renderer object.
70     * @param $aData Array The data created by the <tt>handle()</tt>
71     * method.
72     * @return Boolean <tt>TRUE</tt> if rendered successfully, or
73     * <tt>FALSE</tt> otherwise.
74     * @public
75     * @see handle()
76     */
77    public function render($mode, Doku_Renderer $renderer, $data) {
78        if($mode == 'xhtml') {
79            list($state, $match) = $data;
80            switch ($state) {
81                case DOKU_LEXER_ENTER :
82                    if (is_a($renderer, 'renderer_plugin_revealjs')){
83                        list($style, $index) = $match;
84                        $renderer->doc .= '<span class="fragment' . ($style ? ' '.$style : '') . '"' .
85                            ($index ? ' data-fragment-index="'.$index.'"' : '') . '>';
86                    }
87                    break;
88                case DOKU_LEXER_UNMATCHED :
89                    $renderer->doc .= $renderer->_xmlEntities($match);
90                    break;
91                case DOKU_LEXER_EXIT :
92                    if (is_a($renderer, 'renderer_plugin_revealjs')){
93                        $renderer->doc .= '</span>';
94                    }
95                    break;
96            }
97            return true;
98        }
99        return false;
100    }
101
102
103    /**
104     * Validate fragment style: $style
105     */
106    private function _is_valid_style($style) {
107        $pattern = '/fade-(?:in|out)|current-visible|highlight(?:-current)?-(?:red|green|blue)/';
108        if (preg_match($pattern, $style)) return $style;
109        return '';
110    }
111
112}
113