Questions answered by this recipe
How can I create a table of contents for included files?
How can I create a table of contents for a page whose content is generated via pagelist?
Most of the existing table-of-contents recipes have this limitation: they can only generate a table of contents from the information in the source of the page they're used in. If data is included later (either with (:include :), or, even more tricky, with IncludeUpload) then they don't have the data to base the table-of-contents on.
To activate this recipe, unzip the archive; this will create a handytoc-(version) directory; you then need to move or copy the contents of this into your pmwiki directory. The directory contains:
- File contains markup and functions.
Add the following line to your local/config.php:
The simplest usage is to just put the
(:htoc:) directive on the page where you want to have a table-of-contents.
You can add a title to your table of contents simply by adding it to the directive:
(:htoc This is my table of contents:)
There are also options.
|start||start=2||What level of header the table of contents starts at|
|end||end=3||What level of header the table of contents ends at|
|ignoreh1||ignoreh1=true||The ignoreh1= option can be either true or false. If true, then if there is only one H1 header in the content, then it will be ignored. If false, it won't be (providing that the start option equals 1).|
|class||class=htoneline||set the class name for the div that the table of contents is inside. Useful for additional CSS styling for different kinds of ToCs.|
|anchorafterlement||anchorafterelement=true||Can be true or false. If true, anchor is inserted after a heading (equivalent of |
|smartanchors||smartanchors=true||Can be true or false. See below for details.|
|automaticanchors||automaticanchors=true||Can be true or false. See below for details.|
|pathanchors||pathanchors=true||Can be true or false. See below for details.|
The above will start with h2 headers.
The above will end at h3 headers.
Note that if there are no H1 headers inside the content at all, then the table-of-contents will start at level 2 automatically (unless a greater start level is already specified), even of the headers are in an odd order.
These can be set in local/config.php
|$HandyTocStartAt||Define the (default) level the table-of-contents starts at||1|
|$HandyTocEndAt||Define the (default) level the table-of-contents ends at||6|
|$HandyTocIgnoreSoleH1||If true, then if there's only one h1 header in the content, it will be ignored.||true|
|$HandyTocPubDir||Directory where the HandyToc css and js files are||"|
|$HandyTocPubDirUrl||Url of directory where the HandyToc css and js files are||"\|
|$HandyTocAnchorAfterElement||If true, anchor is inserted after heading; otherwise, before.||true|
|$HandyTocSmartAnchors||If true, smart anchors are enabled (see below).||false|
|$HandyTocAutomaticAnchors||If true, automatic anchors are enabled (see below).||false|
|$HandyTocPathAnchors||If true, path anchors are enabled (see below).||false|
|$HandyTocDefaultTitle||Provides the default title, if none is provided in the page directive.||empty (no title)|
|$HandyTocExcludeWithin||Specifies a CSS selector, all headings matching and within which will be excluded from the ToC||empty (no exclusions)|
|$HandyTocVersionedAssets||If true, the HandyTOC ||true|
The “smart anchors” option (off by default; enabled by setting
$HandyTocSmartAnchors = true; in
config.php or using the
smartanchors=true argument in the
(:htoc:) directive) uses a more modern and cleaner way of creating ToC anchor links. Instead of adding an
<a> element next to a heading, it sets the
id attribute of the heading element itself. If the heading already has an
id attribute set, that existing
id attribute is not overwritten, but kept intact, and used as the link (in place of the usual
(The reason for using this option is twofold: first, it avoids cluttering up the page source with unnecessary anchor tags; second, if your headings have semantically meaningful
id values, your ToC will now use those values and therefore generate semantically meaningful links.)
Note: If smart anchors are enabled, the
$HandyTocAnchorAfterElement setting is ignored (as it is inapplicable in that case).
The “automatic anchors” option (off by default; enabled by setting
$HandyTocAutomaticAnchors = true; in
config.php or using the
automaticanchors=true argument in the
(:htoc:) directive) causes anchor IDs (either the the
id attribute of the
<a> element next to a heading, or—if smart anchors are enabled—the
id attribute of the heading element) to be generated from the text of the heading itself. The heading text is transformed for compatibility when it’s turned into an
id: lowercase forms are used, spaces turned into dashes, periods into underscores, and all characters except alphanumerics, dashes, and underscores are removed. (For example, “My cool heading!” would get an
my-cool-heading, while “Document section 5.2.1: odds & ends” gets an
Just as with the “smart anchors” option, if the heading already has an
id attribute set, that existing
id attribute is not overwritten, but kept intact.
The “path anchors” option (off by default; enabled by setting
$HandyTocPathAnchors = true; in
config.php or using the
pathanchors=true argument in the
(:htoc:) directive) causes the automatically-generated anchor IDs (created by the automatic anchors option) to include all higher-level headings as well as the heading itself.
This can make anchor IDs more informative, and can often prevent duplicate IDs. For example, suppose that you have the following headings:
Chapter 1 Introduction Section 1 Section 2 Conclusion Chapter 2 Introduction Section 1 Section 2 Conclusion
Without path anchors, the “Introduction” subheading under the “Chapter 1” heading would have the same ID (
#introduction) as the “Introduction” subheading under the “Chapter 2” heading.
With path anchors, they would have IDs of
Note: This option has no effect if automatic anchors are not enabled.
The “exclude within” option allows you to specify a CSS selector (such as
#something-more-complex + p, .other-stuff:last-child). HandyTOC will then omit any headings that either match that selector, or are descendants of any element that matches that selector.
(This is useful for excluding heading elements within sidebars, floating frames, etc., from the table of contents.)
You can specify the exclude-within selector in
$HandyTocExcludeWithin = ".some-class, .other-class, #some-id";
Or, you can pass it as an option within the
(:htoc excludewithin=".some-class, .other-class, #some-id" :)
(If you do both, then the directive will override the config file.)
The exclude-within selector is empty by default (i.e., nothing is excluded).
The table of contents is put inside a div with id='htoc', and the table-of-contents title (if there is one) is put in a H3 header. The <ul> element in the div has id='htoc_ul'. While the recipe comes with its own CSS styling (in pub/handytoc/handytoc.css) this can be overridden with your own custom CSS in pub/css/local.css
If the "class=" option is used, then the class is set for the same div; that is, it will be
<div id="htoc" class="classname">
so keep that in mind when using this option.
There is also a .htoneline (handy-toc one line) class in the CSS file, which can be used (with the "class=" option) to make the table-of-contents all on one line, with | separators between each item. This is useful for pages where the headers are, say, single letters of the alphabet (as may happen with indexes). The CSS for this, however, may not work in less-advanced browsers.
This does not have a show/hide toggle button like some of the other TOC recipes; if it's defined for that page, then it's there all the time. If you want to show and hide the toc, you can use the Toggle recipe with markup such as the following:
(:toggle init=hide id=htoc lshow='Show Table of Contents' lhide='Hide Table of Contents':)
Note that this recipe will not work if the skin you are using does not have <!--HTMLFooter--> markup in it.
- 2023-03-20: Added “path anchors” option.
- 2021-11-10: Added “automatic anchors” and “versioned assets” options.
- 2020-05-01: Fixed bug.
- 2020-04-26: Added $HandyTocExcludeWithin.
- 2017-12-17: Only inject HandyTableOfContents JS and CSS if a ToC is actually used.
- 2017-11-26: Added “smart anchors” option.
- 2017-11-05: Fixed bug that caused the same id to be assigned to multiple elements in the ToC block.
- 2017-09-07: Fixed bug that would sometimes prevent the ToC from being created if
- 2017-08-22: Added id of
<ul>element inside the
#htocdiv (to allow just the list to be shown/hidden by Toggle).
- 2017-08-16: Added $HandyTocDefaultTitle.
- 2017-08-16: Added $HandyTocAnchorAfterElement; fixed bug where "start"/$HandyTocStartAt would have no effect in many cases.
- 2017-06-21: changed Markup for PHP 7.2 compatibility (HansB)
- 2016-09-02: HansB: update for PHP5 compatibility.
- (2007-02-18) Added "class=" option, and .htoneline CSS class
$HTMLFooterFmtonly if the markup is present.
- (2007-02-11) Added $HandyTocIgnoreSoleH1 and ignore=h1
- (2007-02-08) Now only looks inside #wikitext (page content); also fixed problems with different header levels in random order. Now XHTML compliant!
- (2007-02-07a) fixed overlooked bug (forgot to rename something)
- (2007-02-07) Initial version
- Cookbook /
- AutoTOC Unobtrusive Automatic Table of Contents links (stable)
- NumberedHeaders Display numbered headers, indented paragraphs and table of contents (Stable)
- NumberedSections Add section numbers on a page (stable)
- PageTableOfContents Adds a clickable table of contents to a page (Stable)
- QuickPageTableOfContents Adds a dropdown clickable table of contents to a page - client side processing (Stable)
- SlimTableOfContents Simple or Numbered Table of Contents, Compatible with SectionEdit Recipe (not working with php5.5)
- PmWiki /
See discussion at HandyTableOfContents-Talk