Published 2020-10-03.
Last modified 2023-05-23.
Time to read: 2 minutes.
jekyll_plugins
collection, categorized under Jekyll.
This Jekyll tag plugin creates a clickable table of contents.
You can see it in action in several areas of this web site:
Django / Django-Oscar index
{% outline attribution django %} 0: Django / Oscar Evaluation 400: Notes 800: Digging Deeper 1900: Debugging 2700: Production {% endoutline %}
Jekyll index
{% outline attribution jekyll %} 0000: Setup 2000: Operation 4000: Scripts 6000: Plugins 10000: Creating and Debugging Custom Jekyll Plugins 12000: Jekyll Internals {% endoutline %} <!-- #region images --> <div style="display: none"> {% img align="right" class="" id="outline_6000" src="/blog/jekyll/rubygems_logo_red.webp" size="eighthsize" style="margin-top: 0" wrapper_class="clear" %} {% img align="right" id="outline_12000" src="/blog/images/magnifying-glass.webp" size="eighthsize" style="margin-top: 0" wrapper_class="clear" %} {% img align="right" class="" id="outline_10000" src="/blog/images/magic_wand.webp" size="eighthsize" style="margin-top: 0" wrapper_class="clear" %} </div> <!-- endregion --> {% outline_js wrap_in_script_tag %}
Jekyll Plugins index
{% outline attribution fields="title </a> – description" jekyll_plugins %} 0000: Organization 2000: Filters 6000: HTML 8000: Utilities 10000: Plugin Components {% endoutline %}
Installation
Add the following line to your Jekyll project's Gemfile
, within the jekyll_plugins
group:
group :jekyll_plugins do gem 'jekyll_outline' end
And then execute:
$ bundle
Fields
By default, each displayed entry consists of a document title, wrapped within an <a href> HTML tag that links to the page for that entry, followed by an indication of whether the document is visible (a draft) or not.
Entries can include following fields:
draft
, categories
, description
,
date
, last_modified_at
, layout
,
order
, title
, slug
, ext
,
tags
, and excerpt
.
Specify the fields like this:
{% outline fields="title – description " %} 000: Topic 0..19 020: Topic 20..39 040: Topic 40.. {% endoutline %}
Words that are not a known field are transcribed into the output.
In the above example, notice that the HTML is space delimited from the field names. The parser is simple and stupid: each token is matched against the known keywords. Tokens are separated by white space.
CSS
The CSS used for the demo website should be copied to your project.
See the sections of demo/assets/css/styles.css
as shown:
/* Start of jekyll_plugin_support css */ ... copy this portion ... /* End of jekyll_plugin_support css */ /* Start of jekyll_outline css */ ... copy this portion ... /* End of jekyll_outline css */
JavaScript
This project's outline_js
tag returns the JavaScript necessary to position images relating to the outline.
If used without parameters it just returns the JavaScript; use the tag this way:
<script> {%= outline_js %} </script>
If passed the wrap_in_script_tag
parameter,
it wraps the JavaScript in <script></script>
.
Use the tag this way:
{% outline_js wrap_in_script_tag %}
Explanation
Given an outline that looks like this:
{% outline my_collection %} 000: Topic 0..19 020: Topic 20..39 040: Topic 40.. {% endoutline %}
...and given pages in the stuff
collection with the following names:
010-published.html
has title Published Stuff Post 010020-unpublished.html
has title Unpublished Post 020030-unpublished.html
has title Unpublished Post 030
Then links to the pages in the stuff
collection's pages are interleaved into the generated outline like this:
<div class="outer_posts"> <h3 class='post_title clear' id="title_0">Topic 0..19</h3> <div id='posts_wrapper_0' class='clearfix'> <div id='posts_0' class='posts'> <span>2022-04-01</span> <span><a href='/stuff/010-published.html'>Published Stuff Post 010</a></span> <span>2022-04-17</span> <span><a href='/stuff/020-unpublished.html'>Unpublished Post 020</a> <i class='jekyll_draft'>Draft</i></span> </div> </div> <h3 class='post_title clear' id="title_20">Topic 20..39</h3> <div id='posts_wrapper_20' class='clearfix'> <div id='posts_20' class='posts'> <span>2022-04-17</span> <span><a href='/stuff/030-unpublished.html'>Unpublished Post 030</a> <i class='jekyll_draft'>Draft</i></span> </div> </div> </div>
The JavaScript searches for images in the current page that were created by
the jekyll_img
plugin,
and have id
s that correspond to outline sections.
Each of following image’s id
s have an outline_
prefix,
followed by a number, which corresponds to one of the sections.
Note that leading zeros in the first column above are not present in the id
s below.
If you want to provide images to embed at appropriate locations within the outline,
wrap them within an invisible div
so the web page does not jump around as the images are loaded.
<div style="display: none;"> {% img align="right" id="outline_0" size="quartersize" src="/assets/images/porcelain_washbasin.webp" style="margin-top: 0" wrapper_class="clear" %} {% img align="right" id="outline_20" size="quartersize" src="/assets/images/pipes.webp" style="margin-top: 0" wrapper_class="clear" %} {% img align="right" id="outline_40" size="quartersize" src="/assets/images/libgit2.webp" style="margin-top: 0" wrapper_class="clear" %} </div>
The JavaScript identifies the images and repositions them in the DOM such that they follow the appropriate heading. If no image corresponds to a heading, no error or warning is generated. The images can be located anywhere on the page; they will be relocated appropriately. If an image does not correspond to a heading, it is deleted.
Attribution
See the jekyll_plugin_support
plugin for an explanation of
attribution
.
Demo
A demo / test website is provided in the demo
directory.
It can be used to debug the plugin or to run freely.
Please examine the HTML
files in the demo to see how the plugin works.
-
To run the demo freely from the command line, type:
Shell$ demo/_bin/debug -r
- View the generated website at
localhost:4444
.