Simple table of content action
Well I didnt see a nice table of contents addition anywhere that did what I wanted, so I just wrote one. I am not going to claim its the best way to do it, I am just offering my work in hopes that it proves useful to somebody else. In addition to automatic table of contents generation, it also changes the link functionality to understand anchor links (mainly for internal pages).
The table of contents is generated based on headers within the page, with an extra anchor name attribute attached. Only headers with this parenthesised anchor name will be included in the table of contents. This anchor name also serves as a valid anchor in the page for external linking purposes.
Example:
=====(section1) Section 1: Monkey=====
Example of linking to another page with anchor:
[[JoeBob#section1 Section 1 of Joe's page]]
You generate the TOC with:
{{toc}}
Optional arguments:
{{toc title="The Table" format="roman num bullet"}}
This functionality should work well for making FAQ pages as well as any sort of sectioned manual. I made the table as raw as possible to allow you to put it wherever you want, either just at the top of the page or in a float or whatever. It should all be within the 'toc' class for style sheet purposes, but I havent tried to change anything about it.
Known Issues
- Preview mode does not show an accurate table of contents because I use an action instead of a formatter, and I dont feel like changing it. (its slower too I imagine, again, dont wanna change it)
Heres the diff against 1.1.6.0
diff -ru Wikka/formatters/wakka.php Wikka/formatters/wakka.php
--- OldWikka/formatters/wakka.php 2005-05-25 08:53:02.000000000 -0700
+++ Wikka/formatters/wakka.php 2005-05-25 08:53:08.000000000 -0700
@@ -131,35 +137,60 @@
} else
return $wakka->Link($url).$matches[2];
}
- // header level 5
- else if ($thing == "==")
+ // header level 1
+ else if (substr($thing,0,6) == "======")
{
$br = 0;
- return (++$trigger_l[5] % 2 ? "<h5>" : "</h5>\n");
+ $pfx = "";
+ if(preg_match("/=\(([a-zA-Z0-9]+)\)/", $thing, $matches)) {
+ $n = $matches[1];
+ $pfx = "<a name='$n' id='$n'></a>";
+ }
+ return (++$trigger_l[1] % 2 ? "$pfx<h1>" : "</h1>\n");
}
- // header level 4
- else if ($thing == "===")
+ // header level 2
+ else if (substr($thing,0,5) == "=====")
{
$br = 0;
- return (++$trigger_l[4] % 2 ? "<h4>" : "</h4>\n");
+ $pfx = "";
+ if(preg_match("/=\(([a-zA-Z0-9]+)\)/", $thing, $matches)) {
+ $n = $matches[1];
+ $pfx = "<a name='$n' id='$n'></a>";
+ }
+ return (++$trigger_l[2] % 2 ? "$pfx<h2>" : "</h2>\n");
}
// header level 3
- else if ($thing == "====")
+ else if (substr($thing,0,4) == "====")
{
$br = 0;
- return (++$trigger_l[3] % 2 ? "<h3>" : "</h3>\n");
+ $pfx = "";
+ if(preg_match("/=\(([a-zA-Z0-9]+)\)/", $thing, $matches)) {
+ $n = $matches[1];
+ $pfx = "<a name='$n' id='$n'></a>";
+ }
+ return (++$trigger_l[3] % 2 ? "$pfx<h3>" : "</h3>\n");
}
- // header level 2
- else if ($thing == "=====")
+ // header level 4
+ else if (substr($thing,0,3) == "===")
{
$br = 0;
- return (++$trigger_l[2] % 2 ? "<h2>" : "</h2>\n");
+ $pfx = "";
+ if(preg_match("/=\(([a-zA-Z0-9]+)\)/", $thing, $matches)) {
+ $n = $matches[1];
+ $pfx = "<a name='$n' id='$n'></a>";
+ }
+ return (++$trigger_l[4] % 2 ? "$pfx<h4>" : "</h4>\n");
}
- // header level 1
- else if ($thing == "======")
+ // header level 5
+ else if (substr($thing,0,2) == "==")
{
$br = 0;
- return (++$trigger_l[1] % 2 ? "<h1>" : "</h1>\n");
+ $pfx = "";
+ if(preg_match("/=\(([a-zA-Z0-9]+)\)/", $thing, $matches)) {
+ $n = $matches[1];
+ $pfx = "<a name='$n' id='$n'></a>";
+ }
+ return (++$trigger_l[5] % 2 ? "$pfx<h5>" : "</h5>\n");
}
// forced line breaks
else if ($thing == "---")
@@ -367,8 +398,8 @@
"\[\[[^\[]*?\]\]|". # forced link
"-{4,}|---|". # separator (hr)
"\b[a-z]+:\/\/\S+|". # URL
"\*\*|\'\'|\#\#|\#\%|@@|::c::|\>\>|\<\<|££|¥¥|\+\+|__|<|>|\/\/|". # Wiki markup
- "======|=====|====|===|==|". # headings
+ "======(\([a-zA-Z0-9]+\))?|=====(\([a-zA-Z0-9]+\))?|====(\([a-zA-Z0-9]+\))?|===(\([a-zA-Z0-9]+\))?|==(\([a-zA-Z0-9]+\))?|". # headings
"\n([\t~]+)(-|&|[0-9a-zA-Z]+\))?|". # indents and lists
"\{\{.*?\}\}|". # action
"\b[A-ZÄÖÜ][A-Za-zÄÖÜßäöü]+[:](?![=_])\S*\b|". # InterWiki link
diff -ru Wikka/wikka.php Wikka/wikka.php
--- OldWikka/wikka.php 2005-05-25 08:53:03.000000000 -0700
+++ Wikka/wikka.php 2005-05-25 08:53:08.000000000 -0700
@@ -626,6 +626,11 @@
// escape text?
if ($escapeText) $text = $this->htmlspecialchars_ent($text);
$url = '';
+ $anchor = '';
+ if(preg_match("/(.+)\#(.+)/", $tag, $matches)) {
+ $anchor = "#".$matches[2];
+ $tag = $matches[1];
+ }
// is this an interwiki link?
if (preg_match("/^([A-ZÄÖÜ][A-Za-zÄÖÜßäöü]+)[:](\S*)$/", $tag, $matches)) # before the : should be a WikiName; anything after can be (nearly) anything that's allowed in a URL
@@ -656,10 +661,10 @@
if ($_SESSION["linktracking"] && $track) $this->TrackLinkTo($tag);
$linkedPage = $this->LoadPage($tag);
// return ($linkedPage ? "<a href=\"".$this->Href($method, $linkedPage['tag'])."\">".$text."</a>" : "<span class=\"missingpage\">".$text."</span><a href=\"".$this->Href("edit", $tag)."\" title=\"Create this page\">?</a>");
- return ($linkedPage ? "<a href=\"".$this->Href($method, $linkedPage['tag'])."\" title=\"$title\">".$text."</a>" : "<a class=\"missingpage\" href=\"".$this->Href("edit", $tag)."\" title=\"Create this page\">".$text."</a>");
+ return ($linkedPage ? "<a href=\"".$this->Href($method, $linkedPage['tag'])."$anchor\" title=\"$title\">".$text."</a>" : "<a class=\"missingpage\" href=\"".$this->Href("edit", $tag)."\" title=\"Create this page\">".$text."</a>");
}
$external_link_tail = $this->GetConfigValue("external_link_tail");
- return $url ? "<a class=\"ext\" href=\"$url\">$text</a>$external_link_tail" : $text;
+ return $url ? "<a class=\"ext\" href=\"$url$anchor\">$text</a>$external_link_tail" : $text;
}
// function PregPageLink($matches) { return $this->Link($matches[1]); }
@@ -1205,4 +1210,4 @@
ob_end_clean();
echo $page_output;
-?>
\ No newline at end of file
+?>
diff -rubBN Wikka/actions/toc.php emuwiki-1.0/actions/toc.php
--- OldWikka/actions/toc.php 1969-12-31 17:00:00.000000000 -0700
+++ Wikka/actions/toc.php 2005-05-25 08:53:08.000000000 -0700
@@ -0,0 +1,98 @@
+<?
+
+/*
+(C) 2005 Alan Jones
+
+format idea and switch stolen from http://mindwiki.de/wikka_toc
+
+*/
+
+
+$title = "Table Of Contents";
+if(array_key_exists('title', $vars)) { $title = $vars['title']; }
+
+//format code
+$format = "num";
+if(array_key_exists('format', $vars)) { $format = $vars['format']; }
+ // assign formatting specs to the found levels
+ //default values for level formatting
+ $deflevel = array("<ol>", "</ol>", "<li>", "</li>");
+ $level = array($deflevel, $deflevel, $deflevel, $deflevel, $deflevel, $deflevel);
+ $lvls = explode(" ", $format);
+ for ($i = 0; $i < count($lvls); $i++) {
+ switch ($lvls[$i]) {
+ //case "indent": $opener = "<div class='indent'>"; $closer = "</div>"; $item = ""; $itemc = "<br />"; break;
+ case "bullet": $opener = "<ul>"; $closer = "</ul>"; $item = "<li>"; $itemc = "</li>"; break;
+ case "num": $opener = "<ol>"; $closer = "</ol>"; $item = "<li>"; $itemc = "</li>"; break;
+ case "alpha": $opener = "<ol type='A'>"; $closer = "</ol>"; $item = "<li>"; $itemc = "</li>"; break;
+ case "roman": $opener = "<ol type='I'>"; $closer = "</ol>"; $item = "<li>"; $itemc = "</li>"; break;
+ case "loweralpha": $opener = "<ol type='a'>"; $closer = "</ol>"; $item = "<li>"; $itemc = "</li>"; break;
+ case "lowerroman": $opener = "<ol type='i'>"; $closer = "</ol>"; $item = "<li>"; $itemc = "</li>"; break;
+ }
+ $level[$i] = array($opener, $closer, $item, $itemc);
+ }
+
+
+//grab the page text, this is a bad hack, dosent work in preview mode
+$tag = $this->getPageTag();
+$page = $this->LoadPage($tag);
+$toc = $page["body"];
+
+preg_match_all("/(={2,5})\(([a-zA-Z0-9_]+)\)(.+)==/", $toc, $matches, PREG_SET_ORDER);
+
+if(count($matches) > 0) {
+ echo "<div id='toc'>";
+ if($title) {
+ echo "<h3>$title</h3>";
+ }
+
+ $initlvl = 6 - strlen($matches[0][1]);
+ //shift format levels over to make the first level the first format entry
+ for($r = 0; $r < $initlvl; $r++) { array_unshift($level, array()); }
+ $last = $initlvl - 1;
+ foreach($matches as $entry) {
+ $lvl = 6 - strlen($entry[1]);
+ if($lvl < $initlvl) { $lvl = $initlvl; }
+ $anchor = $entry[2];
+ $text = $entry[3];
+ //fix up a little looseness in the regex above
+ $text = preg_replace("/={1,4}/", "", $text);
+ if($lvl < $last) {
+ //we have gone up a number of levels
+ while($lvl < $last) {
+ //close out the level.
+ $fmt = $level[$last];
+ echo $fmt[1]."\n";
+ //move up one
+ $last--;
+ }
+ } else if($lvl > $last) {
+ //we need to go down a number of levels
+ while($lvl > $last) {
+ //move down one
+ $last++;
+ //Open the new level.
+ $fmt = $level[$last];
+ echo $fmt[0]."\n";
+ }
+ }
+
+ $fmt = $level[$lvl];
+// echo $fmt[2]."<a href='#$anchor'>$text</a>".$fmt[3]."\n";
+ echo $fmt[2];
+ echo $this->Link("$tag#$anchor", '', $text);
+ echo $fmt[3]."\n";
+ } //end foreach entry
+
+ //close out any open levels
+ while($last >= $initlvl) {
+ $fmt = $level[$last];
+ echo $fmt[1]."\n";
+ //move up one
+ $last--;
+ }
+
+ echo "</div>\n";
+} //end if TOC is not empty
+
+?>
--- OldWikka/formatters/wakka.php 2005-05-25 08:53:02.000000000 -0700
+++ Wikka/formatters/wakka.php 2005-05-25 08:53:08.000000000 -0700
@@ -131,35 +137,60 @@
} else
return $wakka->Link($url).$matches[2];
}
- // header level 5
- else if ($thing == "==")
+ // header level 1
+ else if (substr($thing,0,6) == "======")
{
$br = 0;
- return (++$trigger_l[5] % 2 ? "<h5>" : "</h5>\n");
+ $pfx = "";
+ if(preg_match("/=\(([a-zA-Z0-9]+)\)/", $thing, $matches)) {
+ $n = $matches[1];
+ $pfx = "<a name='$n' id='$n'></a>";
+ }
+ return (++$trigger_l[1] % 2 ? "$pfx<h1>" : "</h1>\n");
}
- // header level 4
- else if ($thing == "===")
+ // header level 2
+ else if (substr($thing,0,5) == "=====")
{
$br = 0;
- return (++$trigger_l[4] % 2 ? "<h4>" : "</h4>\n");
+ $pfx = "";
+ if(preg_match("/=\(([a-zA-Z0-9]+)\)/", $thing, $matches)) {
+ $n = $matches[1];
+ $pfx = "<a name='$n' id='$n'></a>";
+ }
+ return (++$trigger_l[2] % 2 ? "$pfx<h2>" : "</h2>\n");
}
// header level 3
- else if ($thing == "====")
+ else if (substr($thing,0,4) == "====")
{
$br = 0;
- return (++$trigger_l[3] % 2 ? "<h3>" : "</h3>\n");
+ $pfx = "";
+ if(preg_match("/=\(([a-zA-Z0-9]+)\)/", $thing, $matches)) {
+ $n = $matches[1];
+ $pfx = "<a name='$n' id='$n'></a>";
+ }
+ return (++$trigger_l[3] % 2 ? "$pfx<h3>" : "</h3>\n");
}
- // header level 2
- else if ($thing == "=====")
+ // header level 4
+ else if (substr($thing,0,3) == "===")
{
$br = 0;
- return (++$trigger_l[2] % 2 ? "<h2>" : "</h2>\n");
+ $pfx = "";
+ if(preg_match("/=\(([a-zA-Z0-9]+)\)/", $thing, $matches)) {
+ $n = $matches[1];
+ $pfx = "<a name='$n' id='$n'></a>";
+ }
+ return (++$trigger_l[4] % 2 ? "$pfx<h4>" : "</h4>\n");
}
- // header level 1
- else if ($thing == "======")
+ // header level 5
+ else if (substr($thing,0,2) == "==")
{
$br = 0;
- return (++$trigger_l[1] % 2 ? "<h1>" : "</h1>\n");
+ $pfx = "";
+ if(preg_match("/=\(([a-zA-Z0-9]+)\)/", $thing, $matches)) {
+ $n = $matches[1];
+ $pfx = "<a name='$n' id='$n'></a>";
+ }
+ return (++$trigger_l[5] % 2 ? "$pfx<h5>" : "</h5>\n");
}
// forced line breaks
else if ($thing == "---")
@@ -367,8 +398,8 @@
"\[\[[^\[]*?\]\]|". # forced link
"-{4,}|---|". # separator (hr)
"\b[a-z]+:\/\/\S+|". # URL
"\*\*|\'\'|\#\#|\#\%|@@|::c::|\>\>|\<\<|££|¥¥|\+\+|__|<|>|\/\/|". # Wiki markup
- "======|=====|====|===|==|". # headings
+ "======(\([a-zA-Z0-9]+\))?|=====(\([a-zA-Z0-9]+\))?|====(\([a-zA-Z0-9]+\))?|===(\([a-zA-Z0-9]+\))?|==(\([a-zA-Z0-9]+\))?|". # headings
"\n([\t~]+)(-|&|[0-9a-zA-Z]+\))?|". # indents and lists
"\{\{.*?\}\}|". # action
"\b[A-ZÄÖÜ][A-Za-zÄÖÜßäöü]+[:](?![=_])\S*\b|". # InterWiki link
diff -ru Wikka/wikka.php Wikka/wikka.php
--- OldWikka/wikka.php 2005-05-25 08:53:03.000000000 -0700
+++ Wikka/wikka.php 2005-05-25 08:53:08.000000000 -0700
@@ -626,6 +626,11 @@
// escape text?
if ($escapeText) $text = $this->htmlspecialchars_ent($text);
$url = '';
+ $anchor = '';
+ if(preg_match("/(.+)\#(.+)/", $tag, $matches)) {
+ $anchor = "#".$matches[2];
+ $tag = $matches[1];
+ }
// is this an interwiki link?
if (preg_match("/^([A-ZÄÖÜ][A-Za-zÄÖÜßäöü]+)[:](\S*)$/", $tag, $matches)) # before the : should be a WikiName; anything after can be (nearly) anything that's allowed in a URL
@@ -656,10 +661,10 @@
if ($_SESSION["linktracking"] && $track) $this->TrackLinkTo($tag);
$linkedPage = $this->LoadPage($tag);
// return ($linkedPage ? "<a href=\"".$this->Href($method, $linkedPage['tag'])."\">".$text."</a>" : "<span class=\"missingpage\">".$text."</span><a href=\"".$this->Href("edit", $tag)."\" title=\"Create this page\">?</a>");
- return ($linkedPage ? "<a href=\"".$this->Href($method, $linkedPage['tag'])."\" title=\"$title\">".$text."</a>" : "<a class=\"missingpage\" href=\"".$this->Href("edit", $tag)."\" title=\"Create this page\">".$text."</a>");
+ return ($linkedPage ? "<a href=\"".$this->Href($method, $linkedPage['tag'])."$anchor\" title=\"$title\">".$text."</a>" : "<a class=\"missingpage\" href=\"".$this->Href("edit", $tag)."\" title=\"Create this page\">".$text."</a>");
}
$external_link_tail = $this->GetConfigValue("external_link_tail");
- return $url ? "<a class=\"ext\" href=\"$url\">$text</a>$external_link_tail" : $text;
+ return $url ? "<a class=\"ext\" href=\"$url$anchor\">$text</a>$external_link_tail" : $text;
}
// function PregPageLink($matches) { return $this->Link($matches[1]); }
@@ -1205,4 +1210,4 @@
ob_end_clean();
echo $page_output;
-?>
\ No newline at end of file
+?>
diff -rubBN Wikka/actions/toc.php emuwiki-1.0/actions/toc.php
--- OldWikka/actions/toc.php 1969-12-31 17:00:00.000000000 -0700
+++ Wikka/actions/toc.php 2005-05-25 08:53:08.000000000 -0700
@@ -0,0 +1,98 @@
+<?
+
+/*
+(C) 2005 Alan Jones
+
+format idea and switch stolen from http://mindwiki.de/wikka_toc
+
+*/
+
+
+$title = "Table Of Contents";
+if(array_key_exists('title', $vars)) { $title = $vars['title']; }
+
+//format code
+$format = "num";
+if(array_key_exists('format', $vars)) { $format = $vars['format']; }
+ // assign formatting specs to the found levels
+ //default values for level formatting
+ $deflevel = array("<ol>", "</ol>", "<li>", "</li>");
+ $level = array($deflevel, $deflevel, $deflevel, $deflevel, $deflevel, $deflevel);
+ $lvls = explode(" ", $format);
+ for ($i = 0; $i < count($lvls); $i++) {
+ switch ($lvls[$i]) {
+ //case "indent": $opener = "<div class='indent'>"; $closer = "</div>"; $item = ""; $itemc = "<br />"; break;
+ case "bullet": $opener = "<ul>"; $closer = "</ul>"; $item = "<li>"; $itemc = "</li>"; break;
+ case "num": $opener = "<ol>"; $closer = "</ol>"; $item = "<li>"; $itemc = "</li>"; break;
+ case "alpha": $opener = "<ol type='A'>"; $closer = "</ol>"; $item = "<li>"; $itemc = "</li>"; break;
+ case "roman": $opener = "<ol type='I'>"; $closer = "</ol>"; $item = "<li>"; $itemc = "</li>"; break;
+ case "loweralpha": $opener = "<ol type='a'>"; $closer = "</ol>"; $item = "<li>"; $itemc = "</li>"; break;
+ case "lowerroman": $opener = "<ol type='i'>"; $closer = "</ol>"; $item = "<li>"; $itemc = "</li>"; break;
+ }
+ $level[$i] = array($opener, $closer, $item, $itemc);
+ }
+
+
+//grab the page text, this is a bad hack, dosent work in preview mode
+$tag = $this->getPageTag();
+$page = $this->LoadPage($tag);
+$toc = $page["body"];
+
+preg_match_all("/(={2,5})\(([a-zA-Z0-9_]+)\)(.+)==/", $toc, $matches, PREG_SET_ORDER);
+
+if(count($matches) > 0) {
+ echo "<div id='toc'>";
+ if($title) {
+ echo "<h3>$title</h3>";
+ }
+
+ $initlvl = 6 - strlen($matches[0][1]);
+ //shift format levels over to make the first level the first format entry
+ for($r = 0; $r < $initlvl; $r++) { array_unshift($level, array()); }
+ $last = $initlvl - 1;
+ foreach($matches as $entry) {
+ $lvl = 6 - strlen($entry[1]);
+ if($lvl < $initlvl) { $lvl = $initlvl; }
+ $anchor = $entry[2];
+ $text = $entry[3];
+ //fix up a little looseness in the regex above
+ $text = preg_replace("/={1,4}/", "", $text);
+ if($lvl < $last) {
+ //we have gone up a number of levels
+ while($lvl < $last) {
+ //close out the level.
+ $fmt = $level[$last];
+ echo $fmt[1]."\n";
+ //move up one
+ $last--;
+ }
+ } else if($lvl > $last) {
+ //we need to go down a number of levels
+ while($lvl > $last) {
+ //move down one
+ $last++;
+ //Open the new level.
+ $fmt = $level[$last];
+ echo $fmt[0]."\n";
+ }
+ }
+
+ $fmt = $level[$lvl];
+// echo $fmt[2]."<a href='#$anchor'>$text</a>".$fmt[3]."\n";
+ echo $fmt[2];
+ echo $this->Link("$tag#$anchor", '', $text);
+ echo $fmt[3]."\n";
+ } //end foreach entry
+
+ //close out any open levels
+ while($last >= $initlvl) {
+ $fmt = $level[$last];
+ echo $fmt[1]."\n";
+ //move up one
+ $last--;
+ }
+
+ echo "</div>\n";
+} //end if TOC is not empty
+
+?>
CategoryUserContributions