From b8595a660455f6778266779753c6238127664a28 Mon Sep 17 00:00:00 2001 From: Andreas Gohr <andi@splitbrain.org> Date: Sun, 5 Aug 2007 15:24:05 +0200 Subject: [PATCH] separated TOC from page This patch introduces a tpl_toc() function which can be used to freely place the Table of Contents in a template. When used, tpl_content should be called with a parameter of false to supress the automatic TOC placement. Note: if tpl_toc() us run *before* tpl_content(), TOCs will not work in the preview. A work around is to run tpl_content() in a output buffer first. This patch also adds a getTOC() function for admin plugins which allows plugin authors to put create their own TOC which will be placed correctly in the template. A convenience function html_mktocitem() is available. The config manager was adjusted to make ue of this new feature, but some bugs might remain. darcs-hash:20070805132405-7ad00-77d2c3cdf66cc62b2d408cc6580f938636a109af.gz --- inc/html.php | 64 +++++++++++++++++++++++++--- inc/init.php | 3 ++ inc/parser/metadata.php | 3 ++ inc/parser/xhtml.php | 43 +++---------------- inc/parserutils.php | 2 +- inc/template.php | 82 ++++++++++++++++++++++++++++++------ lib/plugins/admin.php | 4 ++ lib/plugins/config/admin.php | 49 +++++++++++---------- 8 files changed, 165 insertions(+), 85 deletions(-) diff --git a/inc/html.php b/inc/html.php index ff2194f2b..58886dce5 100644 --- a/inc/html.php +++ b/inc/html.php @@ -200,6 +200,7 @@ function html_show($txt=''){ global $ID; global $REV; global $HIGH; + global $INFO; //disable section editing for old revisions or in preview if($txt || $REV){ $secedit = false; @@ -209,18 +210,22 @@ function html_show($txt=''){ if ($txt){ //PreviewHeader - print '<br id="scroll__here" />'; - print p_locale_xhtml('preview'); - print '<div class="preview">'; - print html_secedit(p_render('xhtml',p_get_instructions($txt),$info),$secedit); - print '<div class="clearer"></div>'; - print '</div>'; + echo '<br id="scroll__here" />'; + echo p_locale_xhtml('preview'); + echo '<div class="preview">'; + $html = html_secedit(p_render('xhtml',p_get_instructions($txt),$info),$secedit); + if($INFO['prependTOC']) $html = tpl_toc(true).$html; + echo $html; + echo '<div class="clearer"></div>'; + echo '</div>'; }else{ if ($REV) print p_locale_xhtml('showrev'); $html = p_wiki_xhtml($ID,$REV,true); $html = html_secedit($html,$secedit); - print html_hilight($html,$HIGH); + if($INFO['prependTOC']) $html = tpl_toc(true).$html; + $html = html_hilight($html,$HIGH); + echo $html; } } @@ -1245,6 +1250,51 @@ function html_resendpwd() { print '</div>'.NL; } +/** + * Return the TOC rendered to XHTML + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function html_TOC($toc){ + if(!count($toc)) return ''; + global $lang; + $out = '<!-- TOC START -->'.DOKU_LF; + $out .= '<div class="toc">'.DOKU_LF; + $out .= '<div class="tocheader toctoggle" id="toc__header">'; + $out .= $lang['toc']; + $out .= '</div>'.DOKU_LF; + $out .= '<div id="toc__inside">'.DOKU_LF; + $out .= html_buildlist($toc,'toc','html_list_toc'); + $out .= '</div>'.DOKU_LF.'</div>'.DOKU_LF; + $out .= '<!-- TOC END -->'.DOKU_LF; + return $out; } + +/** + * Callback for html_buildlist + */ +function html_list_toc($item){ + return '<span class="li"><a href="'.$item['link'].'" class="toc">'. + hsc($item['title']).'</a></span>'; +} + +/** + * Helper function to build TOC items + * + * Returns an array ready to be added to a TOC array + * + * @param string $link - where to link (if $hash set to '#' it's a local anchor) + * @param string $text - what to display in the TOC + * @param int $level - nesting level + * @param string $hash - is prepended to the given $link, set blank if you want full links + */ +function html_mktocitem($link, $text, $level, $hash='#'){ + global $conf; + return array( 'link' => $hash.$link, + 'title' => $text, + 'type' => 'ul', + 'level' => $level-$conf['toptoclevel']+1); +} + /** * Output a Doku_Form object. * Triggers an event with the form name: HTML_{$name}FORM_OUTPUT diff --git a/inc/init.php b/inc/init.php index f8697a845..286850e94 100644 --- a/inc/init.php +++ b/inc/init.php @@ -63,6 +63,9 @@ } } + // define whitespace + if(!defined('DOKU_LF')) define ('DOKU_LF',"\n"); + if(!defined('DOKU_TAB')) define ('DOKU_TAB',"\t"); // define cookie and session id if (!defined('DOKU_COOKIE')) define('DOKU_COOKIE', 'DW'.md5(DOKU_URL)); diff --git a/inc/parser/metadata.php b/inc/parser/metadata.php index 5f06865cf..6e93fd61f 100644 --- a/inc/parser/metadata.php +++ b/inc/parser/metadata.php @@ -42,6 +42,9 @@ class Doku_Renderer_metadata extends Doku_Renderer { } function document_end(){ + // store internal info in metadata (notoc,nocache) + $this->meta['internal'] = $this->info; + if (!$this->meta['description']['abstract']){ // cut off too long abstracts $this->doc = trim($this->doc); diff --git a/inc/parser/xhtml.php b/inc/parser/xhtml.php index 30e154af6..e22298fa3 100644 --- a/inc/parser/xhtml.php +++ b/inc/parser/xhtml.php @@ -82,55 +82,22 @@ class Doku_Renderer_xhtml extends Doku_Renderer { $this->doc .= '</div>'.DOKU_LF; } - // prepend the TOC - if($this->info['toc']){ - $this->doc = $this->render_TOC($this->toc).$this->doc; + // Prepare the TOC + if($this->info['toc'] && is_array($this->toc) && count($this->toc) > 2){ + global $TOC; + $TOC = $this->toc; } // make sure there are no empty paragraphs $this->doc = preg_replace('#<p>\s*</p>#','',$this->doc); } - /** - * Return the TOC rendered to XHTML - * - * @author Andreas Gohr <andi@splitbrain.org> - */ - function render_TOC($toc=null){ - if(is_null($toc) && is_array($this->toc)) $toc = $this->toc; - - if(count($toc) < 3) return ''; - global $lang; - $out = '<!-- TOC START -->'.DOKU_LF; - $out .= '<div class="toc">'.DOKU_LF; - $out .= '<div class="tocheader toctoggle" id="toc__header">'; - $out .= $lang['toc']; - $out .= '</div>'.DOKU_LF; - $out .= '<div id="toc__inside">'.DOKU_LF; - $out .= html_buildlist($toc,'toc',array(__CLASS__,'_tocitem')); - $out .= '</div>'.DOKU_LF.'</div>'.DOKU_LF; - $out .= '<!-- TOC END -->'.DOKU_LF; - return $out; - } - - /** - * Callback for html_buildlist - */ - function _tocitem($item){ - return '<span class="li"><a href="#'.$item['hid'].'" class="toc">'. - Doku_Renderer_xhtml::_xmlEntities($item['title']).'</a></span>'; - } - function toc_additem($id, $text, $level) { global $conf; //handle TOC if($level >= $conf['toptoclevel'] && $level <= $conf['maxtoclevel']){ - // the TOC is one of our standard ul list arrays ;-) - $this->toc[] = array( 'hid' => $id, - 'title' => $text, - 'type' => 'ul', - 'level' => $level-$conf['toptoclevel']+1); + $this->toc[] = html_mktocitem("#$id", $text, $level); } } diff --git a/inc/parserutils.php b/inc/parserutils.php index 20971ac03..e4e51c5a5 100644 --- a/inc/parserutils.php +++ b/inc/parserutils.php @@ -1,6 +1,6 @@ <?php /** - * Utilities for collecting data from config files + * Utilities for accessing the parser * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) * @author Harry Fuecks <hfuecks@gmail.com> diff --git a/inc/template.php b/inc/template.php index 10ecd9f70..196aedb4b 100644 --- a/inc/template.php +++ b/inc/template.php @@ -12,7 +12,6 @@ /** * Returns the path to the given template, uses * default one if the custom version doesn't exist. - * Also enables gzip compression if configured. * * @author Andreas Gohr <andi@splitbrain.org> */ @@ -37,18 +36,17 @@ function template($tpl){ * * @author Andreas Gohr <andi@splitbrain.org> */ -function tpl_content() { - global $ACT; - - ob_start(); - - trigger_event('TPL_ACT_RENDER',$ACT,'tpl_content_core'); - - $html_output = ob_get_clean(); +function tpl_content($prependTOC=true) { + global $ACT; + global $INFO; + $INFO['prependTOC'] = $prependTOC; - trigger_event('TPL_CONTENT_DISPLAY',$html_output,'ptln'); + ob_start(); + trigger_event('TPL_ACT_RENDER',$ACT,'tpl_content_core'); + $html_output = ob_get_clean(); + trigger_event('TPL_CONTENT_DISPLAY',$html_output,'ptln'); - return !empty($html_output); + return !empty($html_output); } function tpl_content_core(){ @@ -135,6 +133,59 @@ function tpl_content_core(){ return true; } +/** + * Places the TOC where the function is called + * + * If you use this you most probably want to call tpl_content with + * a false argument + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function tpl_toc($return=false){ + global $TOC; + global $ACT; + global $ID; + global $REV; + global $INFO; + $toc = array(); + + if(is_array($TOC)){ + // if a TOC was prepared in global scope, always use it + $toc = $TOC; + }elseif($ACT == 'show' && !$REV){ + // get TOC from metadata, render if neccessary + $meta = p_get_metadata($ID, false, true); + if(isset($meta['internal']['toc'])){ + $tocok = $meta['internal']['toc']; + }else{ + $tokok = true; + } + $toc = $meta['description']['tableofcontents']; + if(!$tocok || !is_array($toc) || count($toc) < 3){ + $toc = array(); + } + }elseif($ACT == 'admin'){ + // try to load admin plugin TOC FIXME: duplicates code from tpl_admin + $plugin = null; + if (!empty($_REQUEST['page'])) { + $pluginlist = plugin_list('admin'); + if (in_array($_REQUEST['page'], $pluginlist)) { + // attempt to load the plugin + $plugin =& plugin_load('admin',$_REQUEST['page']); + } + } + if ( ($plugin !== null) && + (!$plugin->forAdminOnly() || $INFO['isadmin']) ){ + $toc = $plugin->getTOC(); + $TOC = $toc; // avoid later rebuild + } + } + + $html = html_TOC($toc); + if($return) return $html; + echo $html; +} + /** * Handle the admin page contents * @@ -142,8 +193,9 @@ function tpl_content_core(){ */ function tpl_admin(){ global $INFO; + global $TOC; - $plugin = NULL; + $plugin = null; if (!empty($_REQUEST['page'])) { $pluginlist = plugin_list('admin'); @@ -154,11 +206,13 @@ function tpl_admin(){ } } - if ($plugin !== NULL){ + if ($plugin !== null){ if($plugin->forAdminOnly() && !$INFO['isadmin']){ msg('For admins only',-1); html_admin(); }else{ + if(!is_array($TOC)) $TOC = $plugin->getTOC(); //if TOC wasn't requested yet + if($INFO['prependTOC']) tpl_toc(); $plugin->html(); } }else{ @@ -1061,4 +1115,4 @@ function tpl_mediaTree(){ ptln('</div>'); } -//Setup VIM: ex: et ts=2 enc=utf-8 : +//Setup VIM: ex: et ts=4 enc=utf-8 : diff --git a/lib/plugins/admin.php b/lib/plugins/admin.php index 00a07a054..2eeda3f7b 100644 --- a/lib/plugins/admin.php +++ b/lib/plugins/admin.php @@ -41,5 +41,9 @@ class DokuWiki_Admin_Plugin extends DokuWiki_Plugin { function forAdminOnly() { return true; } + + function getTOC(){ + return array(); + } } //Setup VIM: ex: et ts=4 enc=utf-8 : diff --git a/lib/plugins/config/admin.php b/lib/plugins/config/admin.php index 1e12df53a..26880b390 100644 --- a/lib/plugins/config/admin.php +++ b/lib/plugins/config/admin.php @@ -32,7 +32,7 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin { var $_changed = false; // set to true if configuration has altered var $_error = false; var $_session_started = false; - var $_localised_prompts = false; + var $_localised_prompts = false; /** * return some info @@ -42,7 +42,7 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin { return array( 'author' => 'Christopher Smith', 'email' => 'chris@jalakai.co.uk', - 'date' => '2006-01-24', + 'date' => '2007-08-05', 'name' => 'Configuration Manager', 'desc' => "Manage Dokuwiki's Configuration Settings", 'url' => 'http://wiki.splitbrain.org/plugin:config', @@ -99,7 +99,6 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin { if (is_null($this->_config)) { $this->_config = new configuration($this->_file); } $this->setupLocale(true); - $this->_print_config_toc(); print $this->locale_xhtml('intro'); ptln('<div id="config__manager">'); @@ -277,10 +276,10 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin { } closedir($dh); } - + // the same for the active template $tpl = $conf['template']; - + if (@file_exists(DOKU_TPLINC.$enlangfile)){ $lang = array(); @include(DOKU_TPLINC.$enlangfile); @@ -295,17 +294,19 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin { $this->lang['tpl'.CM_KEYMARKER.$tpl.CM_KEYMARKER.'template_settings_name'] = ucwords(str_replace('_', ' ', $tpl)).' '.$this->getLang('_template_sufix'); } - + return true; } /** - * Generates a two-level table of contents for the config plugin. - * Uses inc/parser/xhtml.php#render_TOC to format the output. - * - * @author Ben Coburn <btcoburn@silicodon.net> - */ - function _print_config_toc() { + * Generates a two-level table of contents for the config plugin. + * + * @author Ben Coburn <btcoburn@silicodon.net> + */ + function getTOC() { + if (is_null($this->_config)) { $this->_config = new configuration($this->_file); } + $this->setupLocale(true); + $allow_debug = $GLOBALS['conf']['allowdebug']; // avoid global $conf; here. // gather toc data @@ -325,35 +326,33 @@ class admin_plugin_config extends DokuWiki_Admin_Plugin { } } - // use the xhtml renderer to make the toc - require_once(DOKU_INC.'inc/parser/xhtml.php'); - $r = new Doku_Renderer_xhtml; - // build toc - $r->toc_additem('configuration_manager', $this->getLang('_configuration_manager'), 1); - $r->toc_additem('dokuwiki_settings', $this->getLang('_header_dokuwiki'), 1); + $t = array(); + + $t[] = html_mktocitem('configuration_manager', $this->getLang('_configuration_manager'), 1); + $t[] = html_mktocitem('dokuwiki_settings', $this->getLang('_header_dokuwiki'), 1); foreach($toc['conf'] as $setting) { $name = $setting->prompt($this); - $r->toc_additem($setting->_key, $name, 2); + $t[] = html_mktocitem($setting->_key, $name, 2); } if (!empty($toc['plugin'])) { - $r->toc_additem('plugin_settings', $this->getLang('_header_plugin'), 1); + $t[] = html_mktocitem('plugin_settings', $this->getLang('_header_plugin'), 1); } foreach($toc['plugin'] as $setting) { $name = $setting->prompt($this); - $r->toc_additem($setting->_key, $name, 2); + $t[] = html_mktocitem($setting->_key, $name, 2); } if (isset($toc['template'])) { - $r->toc_additem('template_settings', $this->getLang('_header_template'), 1); + $t[] = html_mktocitem('template_settings', $this->getLang('_header_template'), 1); $setting = $toc['template']; $name = $setting->prompt($this); - $r->toc_additem($setting->_key, $name, 2); + $t[] = html_mktocitem($setting->_key, $name, 2); } if ($has_undefined && $allow_debug) { - $r->toc_additem('undefined_settings', $this->getLang('_header_undefined'), 1); + $t[] = html_mktocitem('undefined_settings', $this->getLang('_header_undefined'), 1); } - print $r->render_TOC(); + return $t; } function _print_h1($id, $text) { -- GitLab