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
This commit is contained in:
Andreas Gohr 2007-08-05 15:24:05 +02:00
parent 71f7bde783
commit b8595a6604
8 changed files with 165 additions and 85 deletions

View File

@ -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

View File

@ -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));

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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>

View File

@ -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;
function tpl_content($prependTOC=true) {
global $ACT;
global $INFO;
$INFO['prependTOC'] = $prependTOC;
ob_start();
ob_start();
trigger_event('TPL_ACT_RENDER',$ACT,'tpl_content_core');
$html_output = ob_get_clean();
trigger_event('TPL_CONTENT_DISPLAY',$html_output,'ptln');
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 :

View File

@ -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 :

View File

@ -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) {