Files
2010-02-26 12:23:45 -05:00

287 lines
11 KiB
PHP

<?php if (!defined('PmWiki')) exit();
/*
The pagetoc script adds support for automatically generating
a table of contents for a wiki page.
Version 2.0.29 (development version; works with PmWiki beta 13 or above)
Copyright 2004, 2005 John Rankin (john.rankin@affinity.co.nz)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/
SDV($TocSize,'smaller');
SDV($TocFloat,false);
$HTMLStylesFmt['toc'] = "
span.anchor {
float: left;
font-size: 10px;
margin-left: -10px;
width: 10px;
position:relative; top:-0.1em;
text-align: center;
}
span.anchor a { text-decoration: none; }
span.anchor a:hover { text-decoration: underline; }
ol.toc { text-indent:-20px; list-style: none; }
ol.toc ol.toc { text-indent:-40px; }";
$HTMLStylesFmt['tocf'] = "
div.tocfloat { font-size: $TocSize; margin-bottom: 10px;
border-top: 1px dotted #555555; border-bottom: 1px dotted #555555;
padding-top: 5px; padding-bottom: 5px;
width: 38%; float: right; margin-left: 10px; clear: right;
margin-right:-13px; padding-right: 13px; padding-left: 13px;
background-color: #eeeeee; }
div.toc { font-size: $TocSize;
padding: 4px; border: 1px dotted #cccccc;
background: #f7f7f7;
margin-bottom: 10px; }";
SDV($ToggleText, array('hide', 'show'));
$HTMLHeaderFmt['toggle'] = "<script type=\"text/javascript\">
function toggle(obj) {
var elstyle = document.getElementById(obj).style;
var text = document.getElementById(obj + \"tog\");
if (elstyle.display == 'none') {
elstyle.display = 'block';
text.innerHTML = \"{$ToggleText[0]}\";
} else {
elstyle.display = 'none';
text.innerHTML = \"{$ToggleText[1]}\";
}
}
</script>";
## in-page cross-references
Markup('[[#|#','>nl1','/\[\[#([A-Za-z][-.:\w]*)\s*\|\s*#\]\]/e',
"'[[#$1 | '.CrossReference(\$pagename,\$x,'$1').']]'");
Markup('[[#|*','<[[|','/\[\[#([A-Za-z][-.:\w]*)\s*\|\s*\*\]\]/',
'[[#$1 | $1]]');
Markup('[[#|+','<[[|','/\[\[#([A-Za-z][-.:\w]*)\s*\|\s*\+\]\]/',
'[[#$1 | Back to $1]]');
Markup("[^#",'<[[#|#','/\[\^#([A-Za-z][-.:\w]*)\^\]/e',"Shortcut(\$x,'$1')");
SDVA($LinkCleanser, array(
'/`\..*?$/' => '...',
"/\\[\\[([^|\\]]+)\\|\\s*(.*?)\\]\\]($SuffixPattern)/e" =>
"MakeLink(\$pagename,PSS('$1'),PSS('$2'),'$3','\$LinkText')",
"/\\[\\[([^\\]]+?)\\s*-+&gt;\\s*(.*?)\\]\\]($SuffixPattern)/e" =>
"MakeLink(\$pagename,PSS('$2'),PSS('$1'),'$3','\$LinkText')",
'/\\[\\[#([A-Za-z][-.:\\w]*)\\]\\]/' => "",
"/\\[\\[(.*?)\\]\\]($SuffixPattern)/e" =>
"MakeLink(\$pagename,PSS('$1'),NULL,'$2','\$LinkText')",
'/[\\[\\{](.*?)\\|(.*?)[\\]\\}]/' => '$1',
"/`(($GroupPattern([\\/.]))?($WikiWordPattern))/" => '$1',
"/$GroupPattern\\/($WikiWordPattern)/" => '$1'
));
function CrossReference($pagename,$text,$anchor) {
global $LinkCleanser;
$r = Shortcut($text,$anchor);
foreach ($LinkCleanser as $p => $c) $r = preg_replace($p,$c,$r);
return $r;
}
function Shortcut($text,$anchor) {
if (preg_match("/\\[\\[#+$anchor\\]\\]\\n?([^\n]+)/",$text,$match)) {
return preg_replace("/^[#*!:]+\s*/","",
preg_replace("/([^!]+)!.+/","$1",$match[1]));
} else {
return "<em>$anchor</em> not found";
}
}
## [[##visibleanchor]]
SDV($VisibleAnchor,'&sect;');
SDV($VisibleAnchorLinks,false);
SDV($DefaultTocAnchor,'toc');
$RefOrTitle = ($VisibleAnchorLinks) ? 'href' : 'title';
## autonumber anchors
Markup('^!#','<links','/^(!+|Q?:)#(#?)/e',"'$1'.TocAnchor('$2')");
function TocAnchor($visible) {
global $DefaultTocAnchor;
static $toccounter;
return "[[$visible#$DefaultTocAnchor" . ++$toccounter . "]]";
}
## (:markup:) that excludes heading markup examples
function HMarkupMarkup($pagename, $lead, $texta, $textb) {
return "$lead<:block>" .
Keep("<table class='markup' align='center'><tr><td class='markup1'><pre>" .
wordwrap($texta, 70) . "</pre></td></tr><tr><td class='markup2'>") .
"\n$textb\n(:divend:)</td></tr></table>\n";
}
Markup('`markup','<markup',
"/(^|\\(:nl:\\))\\(:markup:\\)[^\\S\n]*\\[([=@])((?:\n`\\.!+.*?)+)\\2\\]/seim",
"HMarkupMarkup(\$pagename, '$1', PSS(str_replace('`.','','$3')), PSS('$3'))");
#Markup("`.",'>links',"/`\./",''); ## included in extendmarkup.php
## page table of contents
$IdPattern = "[A-Za-z][-.:\w]*";
if ($format=='pdf') {
SDV($DefaultTocTitle,'Contents');
SDV($TocHeaderFmt,
'[[#toc]]<tbook:visual markup="bf">$TocTitle</tbook:visual>');
SDV($RemoteTocFmt,
'<tbook:visual markup="bf">Contents of [[$Toc(#toc)]]</tbook:visual>');
} else {
SDV($DefaultTocTitle,'On this page...');
SDV($TocHeaderFmt,'[[#toc]]<b>$TocTitle</b>');
SDV($RemoteTocFmt,'<b>On page [[$Toc(#toc)]]...</b>');
}
SDV($NumberToc,true);
SDV($L1TocChar, '.');
SDV($OmitQMarkup,false);
if ($action=="print" || $action=="publish") {
Markup('[[##','<[[#','/\[\[##([A-Za-z][-.:\w]*)\]\]/','[[#$1]]');
if ($action=='publish') Markup('toc','>include',
'/\(:([#\*])?toc(?:-(float|hide))?(?:\s+anchors=(v)isible)?(?:\s+(.*?))?:\)/', '');
Markup('tocback','directives','/\(:toc-back(?:\s+(.*?))?:\)/','');
} else {
Markup('[[##','<[[#','/\[\[##([A-Za-z][-.:\w]*)\]\]/e',
"Keep(\"<span class='anchor'><a name='$1' id='$1' $RefOrTitle='#$1'>$VisibleAnchor</a></span>\",
'L')");
}
Markup('toc','>nl1',
'/\(:([#\*])?toc(?:-(float|hide))?(?:\s+anchors=(v)isible)?(?:\s+(.*?))?(?:\s+(Q))?:\)(.*)$/se',
"TableOfContents(\$pagename,'$1','$2',PSS('$4'),'$5',PSS('$6')).
TocEntryAnchors('$3',PSS('$6'))");
SDV($TocBackFmt,'&uarr; Contents');
Markup('tocback','directives','/\(:toc-back(?:\s+(.*?))?:\)/e',
"'[[#toc | '.TocLinkText(PSS('$1')).']]'");
Markup('tocpage','directives','/\(:toc-page\s+(.*?)(?:\s+self=([01]))?:\)/e',
"RemoteTableOfContents(\$pagename,'$1','$2')");
function RemoteTableOfContents($pagename,$ref,$self=0) {
global $TocHeaderFmt,$RemoteTocFmt;
$oTocHeader = $TocHeaderFmt;
$TocHeaderFmt = str_replace('$Toc',$ref,$RemoteTocFmt);
$tocname = MakePageName($pagename,$ref);
if ($tocname==$pagename && $self==0) return '';
$tocpage=RetrieveAuthPage($tocname,'read',false);
$toctext=@$tocpage['text'];
if (preg_match('/\(:([#\*])?toc(?:-(float|hide))?(?:\s+anchors=(v)isible)?(?:\s+(.*?))?(?:\s+(Q))?:\)(.*)$/se',$toctext,$m))
$toc = str_replace('[[#',"[[$ref#",
TableOfContents($tocname,$m[1],'page','',$m[5],PSS($m[6])));
$TocHeaderFmt = $oTocHeader;
return $toc;
}
function TocLinkText($text) {
global $TocBackFmt;
if ($text) $TocBackFmt = $text;
return $TocBackFmt;
}
function TocEntryAnchors($visible,$text) {
global $IdPattern;
return preg_replace("/\n(!+|Q:)((\[\[#+$IdPattern\]\])|##?)?/e",
'"\n$1".InsertAnchor($visible,"$1","$2")',$text);
}
function InsertAnchor($visible,$h,$mark) {
global $OmitQMarkup, $NumberToc, $L1TocChar;
static $l1,$l2,$toc1,$toc2;
if ($h=='Q:' && $OmitQMarkup) return $mark;
if ($mark=='') $visibility = ($visible=='') ? '#' : '##';
else $visibility = $mark;
if ($h=='Q:') return $visibility;
$r = '';
$len = strlen($h);
if ($l1==0) { $l1 = $len; }
else if ($len!=$l1 && $l2==0) { $l2 = $len; }
# if ($l1==$len || $l2==$len) $r = $visibility;
if ($l1==$len) {
$toc1++; $toc2 = 0; $r = $visibility;
if ($NumberToc) $r .= "$toc1$L1TocChar&nbsp;";
} elseif ($l2==$len) {
$toc2++; $r = $visibility;
if ($NumberToc) $r .= "$toc1.$toc2&nbsp;";
}
return $r;
}
function TableOfContents($pagename,$number,$float,$title,$includeq,$text) {
global $DefaultTocTitle,$TocHeaderFmt,$IdPattern,$NumberToc,$OmitQMarkup,
$format,$L1TocChar,$DefaultTocAnchor,$TocFloat,$HTMLHeaderFmt,
$ToggleText;
if ($includeq) $OmitQMarkup = (!$OmitQMarkup);
if ($float=='float') $TocFloat = (!$TocFloat);
$l1 = 0; $l2 = 0; $l3 = 0;
$q = 0; $prelen = 1; $counter = 0;
$r = ''; $toc1 = 0;
if (!$title) $title = $DefaultTocTitle;
$toc = str_replace('$TocTitle',$title,$TocHeaderFmt);
if ($number=='*') $NumberToc = false;
elseif ($number=='#') $NumberToc = true;
$closel = 0;
if ($format=='pdf') {
$l = 'tbook:item';
$s = ($NumberToc) ? 'tbook:enumerate' : 'tbook:itemize'; $sc = $s;
$toc = "<tbook:group class='toc'><tbook:p>$toc</tbook:p>".
"<$sc><$l>\$List</$l></$s></tbook:group>";
} elseif ($float=='hide') { return '';
} else {
$tocid = ($float=='page') ? 'ptocid' : 'tocid'; // remote toc?
$toggle = " (<a id=\"{$tocid}tog\" href=\"javascript:toggle('$tocid');\">{$ToggleText[0]}</a>)";
$l = 'li'; $s = ($NumberToc) ? 'ol' : 'ul';
$sc = "$s class='toc'";
$f = ($TocFloat) ? 'float' : '';
$toc = "<div class='toc$f'><p>$toc$toggle</p>" .
"<$sc id='$tocid'><$l>\$List</$l></$s></div>";
}
preg_match_all("/\n(!+|Q?:)\s*(\[\[#+$IdPattern\]\]|#*)([^\n]*)/",$text, $match);
for ($i=0;$i<count($match[0]);$i++) {
if ($match[1][$i]==':' || ($match[1][$i]=='Q:' && $OmitQMarkup)) {
if ($match[2][$i] && $match[2][$i][0]=='#') $counter++;
continue; }
$len = ($match[1][$i]=='Q:') ? 9 : strlen($match[1][$i]);
if ($len==9) $q = 1;
if ($l1==0) { $l1 = $len; $prelen = $l1; }
if ($len!=$l1 && $l2==0) { $l2 = $len; }
if ($len!=$l1 && $len!=$l2 && $q==1 && $l3==0) { $l3 = $len; }
if ($len==$l2 && $l1==9) { $len = $l1; }
if ($len==$l3) { $len = $l2; }
if ($len!=$prelen) {
if ($len==$l1) { $r .= "</$l></$s>"; }
else if ($len==$l2) { $r .= "<$sc><$l>";
$toc2 = 0;
$closel = 0;
}
}
if ($len==$l1 || $len==$l2) {
$prelen = $len;
if ($len==$l1) {
$toc1++;
$tocout = ($NumberToc) ? "$toc1$L1TocChar&nbsp;" : '';
} else {
$toc2++;
$tocout = ($NumberToc) ? "$toc1.$toc2&nbsp;" : '';
}
if ($format=='pdf') $tocout = '';
$m = preg_replace("/^(\\[\\[#)#/","$1",$match[2][$i]);
$m = preg_replace("/^#+/",'',$m);
$t = $match[3][$i];
if ($closel==1) $r .= "</$l><$l>";
$closel = 1;
if (strpos($m,'[#')==1)
$r .= $tocout.str_replace(']]',' | '.
CrossReference($pagename,"$m$t",
preg_replace("/\[\[#(.*?)\]\]/","$1",$m)).']]',$m);
else {
$counter++;
$r .= $tocout."[[#$DefaultTocAnchor$counter | ".
CrossReference($pagename,"[[#]]$t","").']]';
}
}
}
if ($prelen==$l2) $r .= "</$l></$s>";
if ($r!='') $r = str_replace('$List',$r,$toc);
return $r;
}
?>