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_header extends DokuWiki_Syntax_Plugin { 12 13 public function getType() { return 'substition'; } 14 public function getSort() { return 32; } 15 public function getPType() { return 'block'; } 16 17 18 /** 19 * Connect lookup pattern to lexer. 20 * 21 * @param $aMode String The desired rendermode. 22 * @return none 23 * @public 24 * @see render() 25 */ 26 public function connectTo($mode) { 27 /* We want to override the DokuWiki default header handling in cases, where 28 our Reveal.js plugin is active. Therefore we reuse the header pattern from 29 DokuWiki with a lower sort number to be able to fetch the headers before DokuWiki. 30 See also /inc/parser/parser.php around line 282 */ 31 $this->Lexer->addSpecialPattern('[ \t]*={2,}[^\n]+={2,}[ \t]*(?=\n)', $mode, 'plugin_revealjs_header'); 32 } 33 34 35 /** 36 * Handler to prepare matched data for the rendering process. 37 * 38 * @param $aMatch String The text matched by the patterns. 39 * @param $aState Integer The lexer state for the match. 40 * @param $aPos Integer The character position of the matched text. 41 * @param $aHandler Object Reference to the Doku_Handler object. 42 * @return Integer The current lexer state for the match. 43 * @public 44 * @see render() 45 * @static 46 */ 47 public function handle($match, $state, $pos, Doku_Handler $handler) { 48 /* We reuse and adapt here the default DokuWiki header handler code. See also 49 /inc/parser/handler.php around line 97. */ 50 51 // get level and title 52 $title = trim($match); 53 $level = 7 - strspn($title,'='); 54 if($level < 1) $level = 1; 55 $title = trim($title,'= '); 56 if ($this->getConf('revealjs_active') || $_GET['do']=='export_revealjs') { 57 /* We are now on a reveal.js activated page and we want to do our 58 own section handling to be able to get all relevant content from 59 one slide into one edit section. Since sections are header driven, 60 we have to do also our own header handling. 61 Because we are in a plugin context, we are automatically called and 62 do our work in the render function (see below).*/ 63 // pass 64 } 65 else { 66 /* This is the DokuWiki default header/section handling, we use it on NON Reveal.js 67 activated pages (keyword ~~REVEAL~~ not found on page). See also theme.php */ 68 $handler->_addCall('header', array($title, $level, $pos), $pos); 69 } 70 return array($title, $level, $pos); 71 } 72 73 /** 74 * Handle the actual output creation. 75 * 76 * @param $aFormat String The output format to generate. 77 * @param $aRenderer Object A reference to the renderer object. 78 * @param $aData Array The data created by the <tt>handle()</tt> 79 * method. 80 * @return Boolean <tt>TRUE</tt> if rendered successfully, or 81 * <tt>FALSE</tt> otherwise. 82 * @public 83 * @see handle() 84 */ 85 public function render($mode, Doku_Renderer $renderer, $data) { 86 global $conf; 87 if($mode == 'xhtml') { 88 list($text, $level, $pos) = $data; 89 $horizontal_slide_level = $this->getConf('horizontal_slide_level'); 90 /* examples: 91 horizontal_slide_level=2 ==> headers level 1-3 open slides, headers 4-6 are only content on slides 92 horizontal_slide_level=1 ==> headers level 1-2 open slides, headers 3-6 are only content on slides */ 93 94 // rendering the slideshow 95 if (is_a($renderer, 'renderer_plugin_revealjs')){ 96 // slide indicator: special horizontal rules ---- section orange zoom slow no-footer ----> 97 if (!$renderer->slide_indicator_headers) { 98 $renderer->doc .= '<h'. $level .'>'; 99 $renderer->doc .= $renderer->_xmlEntities($text); 100 $renderer->doc .= '</h'. $level .'>'.DOKU_LF; 101 } 102 // slide indicator: headers 103 else { 104 // check, if we have to open a slide 105 if ($level <= $horizontal_slide_level + 1) { 106 // check, if we have to open a column 107 if ($level <= $horizontal_slide_level) { 108 $renderer->open_slide_container(); 109 } 110 $renderer->open_slide(); 111 } 112 $level_calculated = ($level > $horizontal_slide_level && $this->getConf('enlarge_vertical_slide_headers') ? $level - 1 : $level); 113 $renderer->doc .= '<h'. $level_calculated .'>'; 114 $renderer->doc .= $renderer->_xmlEntities($text); 115 $renderer->doc .= '</h'. $level_calculated .'>'.DOKU_LF; 116 } 117 } 118 119 // rendering the normal wiki page 120 else if ($this->getConf('revealjs_active') ) { 121 /* could be, that {{no-footer}} is used before and we need to align the 122 start position definition for the section editing */ 123 if ($renderer->wikipage_next_slide_no_footer_position > 0) { 124 $pos = $renderer->wikipage_next_slide_no_footer_position; 125 $renderer->wikipage_next_slide_no_footer_position = 0; 126 } 127 /** 128 * Render a heading (aligned copy of /inc/parser/xhtml.php around line 184) 129 * 130 * @param string $text the text to display 131 * @param int $level header level 132 * @param int $pos byte position in the original source 133 */ 134 if (!$text) return; //skip empty headlines 135 $hid = $this->_headerToLink($text, $renderer->wikipage_unique_headers); 136 //only add items within configured levels 137 $renderer->toc_additem($hid, $text, $level); 138 // handle section editing 139 if ($renderer->wikipage_slide_indicator_headers && 140 $level <= $horizontal_slide_level + 1 && 141 $renderer->wikipage_slide_edit_section_open && 142 !$renderer->wikipage_slide_background_defined) { 143 $renderer->wikipage_slide_edit_section_open = false; 144 $renderer->doc .= DOKU_LF.'</div>'.DOKU_LF; 145 $renderer->finishSectionEdit($pos - 1); 146 } 147 if ($renderer->wikipage_slide_indicator_headers && 148 $level <= $horizontal_slide_level + 1 && 149 !$renderer->wikipage_slide_edit_section_open) { 150 $renderer->wikipage_slide_number += 1; 151 152 $sectionEditStartData = ['target' => 'section']; 153 if (!defined('SEC_EDIT_PATTERN')) { 154 // backwards-compatibility for Frusterick Manners (2017-02-19) 155 $sectionEditStartData = 'section'; 156 } 157 158 /* write slide details to page - we need to use a fake header (<h1 style="display:none...) here 159 to force dokuwiki to show correct section edit highlighting by hoovering the edit button */ 160 $renderer->doc .= DOKU_LF.DOKU_LF.'<h2 style="display:none;" class="' . 161 $renderer->startSectionEdit($pos, $sectionEditStartData, 'Slide '.$renderer->wikipage_slide_number).'"></h2>' . ($this->getConf('show_slide_details') ? 162 '<div class="slide-details-hr'.($renderer->wikipage_slide_number == 1 ? ' first-slide' : '').'"></div>' . 163 '<div class="slide-details-text">'.($level <= $horizontal_slide_level?'→':'↓') . 164 ' Slide '.$renderer->wikipage_slide_number.($renderer->wikipage_next_slide_no_footer ? ' no-footer' : '').'</div>' : ''); 165 // open new edit section 166 $renderer->wikipage_slide_edit_section_open = true; 167 $renderer->doc .= DOKU_LF.'<div class="level2">'.DOKU_LF; 168 $renderer->wikipage_next_slide_no_footer = false; 169 } 170 // write the header 171 $renderer->doc .= DOKU_LF.'<h'.$level.' id="'.$hid.'">'.$renderer->_xmlEntities($text)."</h$level>"; 172 $renderer->wikipage_slide_background_defined = false; 173 } 174 return true; 175 } 176 return false; 177 } 178 179 /** 180 * Creates a linkid from a headline 181 * 182 * Local version for this plugin which can work on a string instead of an array. 183 * See also /inc/pageutils.php around line 222 184 * 185 * @author Andreas Gohr <andi@splitbrain.org> 186 * @author Ottmar Gobrecht <ottmar.gobrecht@gmail.com> 187 * @param string $title The headline title 188 * @return string 189 */ 190 function _headerToLink($title, &$check) { 191 $title = str_replace(array(':','.'),'',cleanID($title)); 192 $new = ltrim($title,'0123456789_-'); 193 if(empty($new)){ 194 $title = 'section'.preg_replace('/[^0-9]+/','',$title); //keep numbers from headline 195 } 196 else { 197 $title = $new; 198 } 199 // make sure titles are unique 200 $count = 1; 201 while (strpos($check, '{'.$title.'}')) { 202 $title .= $count; 203 $count += 1; 204 } 205 $check .= '{'.$title.'}'; 206 return $title; 207 } 208 209} 210