├── .gitignore
├── LICENSE.txt
├── toc.js
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 Alex Ghiculescu
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
--------------------------------------------------------------------------------
/toc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/ghiculescu/jekyll-table-of-contents
2 | (function($){
3 | $.fn.toc = function(options) {
4 | var defaults = {
5 | noBackToTopLinks: false,
6 | title: 'Jump to...',
7 | minimumHeaders: 3,
8 | headers: 'h1, h2, h3, h4, h5, h6',
9 | listType: 'ol', // values: [ol|ul]
10 | showEffect: 'show', // values: [show|slideDown|fadeIn|none]
11 | showSpeed: 'slow', // set to 0 to deactivate effect
12 | classes: { list: '',
13 | item: '',
14 | link: ''
15 | }
16 | },
17 | settings = $.extend(defaults, options);
18 |
19 | function fixedEncodeURIComponent (str) {
20 | return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
21 | return '%' + c.charCodeAt(0).toString(16);
22 | });
23 | }
24 |
25 | function createLink (header) {
26 | var innerText = (header.textContent === undefined) ? header.innerText : header.textContent;
27 | return "" + innerText + "";
28 | }
29 |
30 | var headers = $(settings.headers).filter(function() {
31 | // get all headers with an ID
32 | var previousSiblingName = $(this).prev().attr( "name" );
33 | if (!this.id && previousSiblingName) {
34 | this.id = $(this).attr( "id", previousSiblingName.replace(/\./g, "-") );
35 | }
36 | return this.id;
37 | }), output = $(this);
38 | if (!headers.length || headers.length < settings.minimumHeaders || !output.length) {
39 | $(this).hide();
40 | return;
41 | }
42 |
43 | if (0 === settings.showSpeed) {
44 | settings.showEffect = 'none';
45 | }
46 |
47 | var render = {
48 | show: function() { output.hide().html(html).show(settings.showSpeed); },
49 | slideDown: function() { output.hide().html(html).slideDown(settings.showSpeed); },
50 | fadeIn: function() { output.hide().html(html).fadeIn(settings.showSpeed); },
51 | none: function() { output.html(html); }
52 | };
53 |
54 | var get_level = function(ele) { return parseInt(ele.nodeName.replace("H", ""), 10); };
55 | var highest_level = headers.map(function(_, ele) { return get_level(ele); }).get().sort()[0];
56 | var return_to_top = ' ';
57 |
58 | var level = get_level(headers[0]),
59 | this_level,
60 | html = settings.title + " <" +settings.listType + " class=\"" + settings.classes.list +"\">";
61 | headers.on('click', function() {
62 | if (!settings.noBackToTopLinks) {
63 | window.location.hash = this.id;
64 | }
65 | })
66 | .addClass('clickable-header')
67 | .each(function(_, header) {
68 | this_level = get_level(header);
69 | if (!settings.noBackToTopLinks && this_level === highest_level) {
70 | $(header).addClass('top-level-header').after(return_to_top);
71 | }
72 | if (this_level === level) // same level as before; same indenting
73 | html += "
" + createLink(header);
74 | else if (this_level <= level){ // higher level than before; end parent ol
75 | for(var i = this_level; i < level; i++) {
76 | html += ""+settings.listType+">"
77 | }
78 | html += "" + createLink(header);
79 | }
80 | else if (this_level > level) { // lower level than before; expand the previous to contain a ol
81 | for(i = this_level; i > level; i--) {
82 | html += "<" + settings.listType + " class=\"" + settings.classes.list +"\">" +
83 | ""
84 | }
85 | html += createLink(header);
86 | }
87 | level = this_level; // update for the next one
88 | });
89 | html += ""+settings.listType+">";
90 | if (!settings.noBackToTopLinks) {
91 | $(document).on('click', '.back-to-top', function() {
92 | $(window).scrollTop(0);
93 | window.location.hash = '';
94 | });
95 | }
96 |
97 | render[settings.showEffect]();
98 | };
99 | })(jQuery);
100 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # jekyll-table-of-contents
2 |
3 | A simple JavaScript table of contents generator. Works well with [jekyll](https://github.com/mojombo/jekyll) static sites.
4 |
5 | ## Usage
6 |
7 | ### Basic Usage
8 |
9 | The script requires jQuery. First, reference `toc.js` in templates where you would like to add the table of content.
10 | Then, create an HTML element wherever you want your table of contents to appear:
11 |
12 | ```html
13 |
14 | ```
15 |
16 | Finally, call the `.toc()` function when the DOM is ready:
17 |
18 | ```html
19 |
24 | ```
25 |
26 | If you use redcarpet, you need to have the option `with_toc_data` in order to add HTML anchors to each header:
27 | ```yaml
28 | markdown: redcarpet
29 | redcarpet:
30 | extensions: [with_toc_data]
31 | ```
32 |
33 | If you use rdiscount, enable the following option in order to generate the TOC:
34 | ```yaml
35 | markdown: rdiscount
36 | rdiscount:
37 | extensions:
38 | - generate_toc
39 | ```
40 |
41 | ### How It Works
42 |
43 | The script works by looking for headers (h1, h2, h3, h4, h5, h6) which have an `id`.
44 | An id is added automatically if you're using Jekyll and [Markdown](http://daringfireball.net/projects/markdown/syntax#header).
45 |
46 | The table of contents automatically handles nesting of headers. For example, this Markdown post:
47 |
48 | ## Title
49 | ## Page 1
50 | ### Note on Paragraph 3
51 | ## Page 2
52 | ### Note on Paragraph 2
53 | ### Note on Paragraph 4
54 |
55 | Will render this table of contents:
56 |
57 | 1. Title
58 | 2. Page 1
59 | a. Note on Paragraph 3
60 | 3. Page 2
61 | a. Note on Paragraph 2
62 | b. Note on Paragraph 4
63 |
64 | ### Configuration
65 |
66 | #### List Type
67 | By default the table of contents is rendered as an ``, so you can change the number formatting using CSS.
68 | However you can use the `` tag, using the `listType` option:
69 |
70 | ```javascript
71 | $('#toc').toc({ listType: 'ul' });
72 | ```
73 |
74 | #### Header Styling
75 | The script also adds an `` tag next to each header. This uses the class `icon-arrow-up`, which if you're using [Bootstrap](http://twitter.github.io/bootstrap/), will be an arrow pointing to the top of the page.
76 | Clicking that arrow will scroll you to the top, while clicking on a header will get a permanent link to that particular header (using `window.location.hash`).
77 |
78 | If you don't want this feature, add this setting:
79 |
80 | ```javascript
81 | $('#toc').toc({ noBackToTopLinks: true });
82 | ```
83 |
84 | Otherwise, you can use the stylesheet below to have the icon and the header aligned nicely:
85 |
86 | ```css
87 | .clickable-header {
88 | cursor:pointer;
89 | }
90 | .clickable-header:hover {
91 | text-decoration:underline;
92 | }
93 | .top-level-header {
94 | display:inline;
95 | }
96 | .back-to-top {
97 | margin-left:5px;
98 | cursor:pointer;
99 | }
100 | ```
101 |
102 | #### Headers Used
103 | By default the table of content is displayed when at least 3 headers are found.
104 | You can customize the minimum number of headers required with this setting:
105 |
106 | ```javascript
107 | $('#toc').toc({ minimumHeaders: 2 });
108 | ```
109 |
110 | And you can also select which headers you want to link to. By default `h1, h2, h3, h4, h5, h6` are displayed, but changing the `headers` setting lets you tweak it:
111 |
112 | ```javascript
113 | $('#toc').toc({ headers: 'h3, h4, h5, h6' });
114 | $('#toc').toc({ headers: '.content h1, .content h2, .content h3, .content h4, .content h5, .content h6' });
115 | ```
116 |
117 | #### Effects
118 | Finally, you can also change the way the toc is displayed, choosing a `slideShow` or a `fadeIn` effect instead of `show`:
119 |
120 | ```javascript
121 | $('#toc').toc({ showEffect: 'slideDown' });
122 | ```
123 |
124 | Otherwise, to deactivate the effect, set it up like this:
125 |
126 | ```javascript
127 | $('#toc').toc({ showSpeed: 0 });
128 | ```
129 |
130 |
131 | #### List And Item Styling
132 | You can specify additional CSS classes for both lists (`, `) and items (`- `):
133 |
134 | ```javascript
135 | $('#toc').toc({ classes: { list: 'lorem ipsum',
136 | item: 'dolor sit amet'
137 | }
138 | });
139 | ```
140 |
141 |
142 | ## Copyright
143 |
144 | See LICENSE.txt for further details. But basically, do what you like with this.
145 |
--------------------------------------------------------------------------------