mirror of
https://github.com/kennethreitz-archive/mdWiki.git
synced 2026-06-05 15:20:18 +00:00
287 lines
11 KiB
PHP
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*-+>\\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,'§');
|
|
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,'↑ 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 ";
|
|
} elseif ($l2==$len) {
|
|
$toc2++; $r = $visibility;
|
|
if ($NumberToc) $r .= "$toc1.$toc2 ";
|
|
}
|
|
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 " : '';
|
|
} else {
|
|
$toc2++;
|
|
$tocout = ($NumberToc) ? "$toc1.$toc2 " : '';
|
|
}
|
|
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;
|
|
}
|
|
|
|
?>
|