j1m_toc 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.md +21 -0
- data/README.md +41 -0
- data/_data/modules/default/j1_toc-0.0.1/j1_tocbot.yml +165 -0
- data/_data/resources/default/j1_toc-0.0.1/resource.yml +24 -0
- data/assets/themes/j1/j1/js/adapters/tocbot.js +161 -0
- data/assets/themes/j1/tocbot/css/tocbot.css +101 -0
- data/assets/themes/j1/tocbot/css/tocbot.min.css +43 -0
- data/assets/themes/j1/tocbot/js/tocbot.js +709 -0
- data/assets/themes/j1/tocbot/js/tocbot.min.js +18 -0
- data/assets/themes/j1/tocbot/js/tocbot.min.js.map +1 -0
- data/exe/console +14 -0
- data/exe/setup +8 -0
- data/lib/j1m_toc.rb +5 -0
- data/lib/j1m_toc/version.rb +3 -0
- metadata +104 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
---
|
2
|
+
regenerate: false
|
3
|
+
---
|
4
|
+
|
5
|
+
{% capture cache %}
|
6
|
+
|
7
|
+
/*
|
8
|
+
# -----------------------------------------------------------------------------
|
9
|
+
# J1: ~/assets/themes/j1/tocbot/css/tocbot.min.css
|
10
|
+
# Provides base styles for the toc navigation based on
|
11
|
+
# Tim Scanlin's Tocbot
|
12
|
+
#
|
13
|
+
# Product/Info:
|
14
|
+
# https://jekyll.one
|
15
|
+
# https://tscanlin.github.io/tocbot
|
16
|
+
#
|
17
|
+
# Copyright (C) 2016 Tim Scanlin
|
18
|
+
# Copyright (C) 2017 Juergen Adams
|
19
|
+
#
|
20
|
+
# J1 Template is licensed under the MIT License.
|
21
|
+
# For details, see https://jekyll.one
|
22
|
+
# Tocbot: Licensed under Open Source Iniative MIT.
|
23
|
+
# For details, see http://opensource.org/licenses/MIT
|
24
|
+
#
|
25
|
+
# -----------------------------------------------------------------------------
|
26
|
+
# Test data:
|
27
|
+
# liquid_var: {{ liquid_var | debug }}
|
28
|
+
#
|
29
|
+
# -----------------------------------------------------------------------------
|
30
|
+
# CSS file generated: {{site.time}}
|
31
|
+
# -----------------------------------------------------------------------------
|
32
|
+
*/
|
33
|
+
|
34
|
+
{% assign active_link_color_default = '#204A87' %}
|
35
|
+
{% assign config_tocbot = site.data.modules.j1_tocbot %}
|
36
|
+
{% assign active_link_color = config_tocbot.activeLinkColor %}
|
37
|
+
|
38
|
+
.toc{overflow-y:auto}.toc ul{overflow:hidden;position:relative;list-style:none;list-style-type:none!important}.toc-list{margin:0;padding-left:10px}a.toc-link{color:currentColor;height:100%;text-decoration:none!important}.is-collapsible{max-height:1000px;overflow:hidden;transition:all 300ms ease-in-out}.is-collapsed{max-height:0}.is-position-fixed{position:fixed!important;top:0}.is-active-link{font-weight:700}.toc-link::before{background-color:#EEE;content:' ';display:inline-block;height:inherit;left:0;margin-top:-1px;position:absolute;width:2px}.is-active-link::before{background-color:{{active_link_color}}}
|
39
|
+
|
40
|
+
{% endcapture %}
|
41
|
+
|
42
|
+
{{ cache | strip_empty_lines }}
|
43
|
+
{% assign cache = nil %}
|
@@ -0,0 +1,709 @@
|
|
1
|
+
/******/ (function(modules) { // webpackBootstrap
|
2
|
+
/******/ // The module cache
|
3
|
+
/******/ var installedModules = {};
|
4
|
+
/******/
|
5
|
+
/******/ // The require function
|
6
|
+
/******/ function __webpack_require__(moduleId) {
|
7
|
+
/******/
|
8
|
+
/******/ // Check if module is in cache
|
9
|
+
/******/ if(installedModules[moduleId])
|
10
|
+
/******/ return installedModules[moduleId].exports;
|
11
|
+
/******/
|
12
|
+
/******/ // Create a new module (and put it into the cache)
|
13
|
+
/******/ var module = installedModules[moduleId] = {
|
14
|
+
/******/ exports: {},
|
15
|
+
/******/ id: moduleId,
|
16
|
+
/******/ loaded: false
|
17
|
+
/******/ };
|
18
|
+
/******/
|
19
|
+
/******/ // Execute the module function
|
20
|
+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
21
|
+
/******/
|
22
|
+
/******/ // Flag the module as loaded
|
23
|
+
/******/ module.loaded = true;
|
24
|
+
/******/
|
25
|
+
/******/ // Return the exports of the module
|
26
|
+
/******/ return module.exports;
|
27
|
+
/******/ }
|
28
|
+
/******/
|
29
|
+
/******/
|
30
|
+
/******/ // expose the modules object (__webpack_modules__)
|
31
|
+
/******/ __webpack_require__.m = modules;
|
32
|
+
/******/
|
33
|
+
/******/ // expose the module cache
|
34
|
+
/******/ __webpack_require__.c = installedModules;
|
35
|
+
/******/
|
36
|
+
/******/ // __webpack_public_path__
|
37
|
+
/******/ __webpack_require__.p = "";
|
38
|
+
/******/
|
39
|
+
/******/ // Load entry module and return exports
|
40
|
+
/******/ return __webpack_require__(0);
|
41
|
+
/******/ })
|
42
|
+
/************************************************************************/
|
43
|
+
/******/ ([
|
44
|
+
/* 0 */
|
45
|
+
/*!*************************!*\
|
46
|
+
!*** ./src/js/index.js ***!
|
47
|
+
\*************************/
|
48
|
+
/***/ function(module, exports, __webpack_require__) {
|
49
|
+
|
50
|
+
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(global) {/**
|
51
|
+
* Tocbot
|
52
|
+
* Tocbot creates a toble of contents based on HTML headings on a page,
|
53
|
+
* this allows users to easily jump to different sections of the document.
|
54
|
+
* Tocbot was inspired by tocify (http://gregfranko.com/jquery.tocify.js/).
|
55
|
+
* The main differences are that it works natively without any need for jquery or jquery UI).
|
56
|
+
*
|
57
|
+
* @author Tim Scanlin
|
58
|
+
*/
|
59
|
+
|
60
|
+
/* globals define */
|
61
|
+
|
62
|
+
(function(root, factory) {
|
63
|
+
if (true) {
|
64
|
+
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory(root)), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
65
|
+
} else if (typeof exports === 'object') {
|
66
|
+
module.exports = factory(root);
|
67
|
+
} else {
|
68
|
+
root.tocbot = factory(root);
|
69
|
+
}
|
70
|
+
})(typeof global !== 'undefined' ? global : this.window || this.global, function(root) {
|
71
|
+
|
72
|
+
'use strict';
|
73
|
+
|
74
|
+
// Require smooth-scroll by default.
|
75
|
+
var smoothScroll = __webpack_require__(/*! smooth-scroll */ 1);
|
76
|
+
|
77
|
+
// Default options.
|
78
|
+
var defaultOptions = __webpack_require__(/*! ./default-options.js */ 2);
|
79
|
+
// Object to store current options.
|
80
|
+
var options = {};
|
81
|
+
// Object for public APIs.
|
82
|
+
var tocbot = {};
|
83
|
+
|
84
|
+
var BuildHtml = __webpack_require__(/*! ./build-html.js */ 3);
|
85
|
+
var ParseContent = __webpack_require__(/*! ./parse-content.js */ 4);
|
86
|
+
// Keep these variables at top scope once options are passed in.
|
87
|
+
var buildHtml;
|
88
|
+
var parseContent;
|
89
|
+
|
90
|
+
var doc = root.document;
|
91
|
+
var body = document.body;
|
92
|
+
var supports = !!root.document.querySelector && !!root.addEventListener; // Feature test
|
93
|
+
var headingsArray;
|
94
|
+
|
95
|
+
// From: https://github.com/Raynos/xtend
|
96
|
+
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
97
|
+
function extend() {
|
98
|
+
var target = {};
|
99
|
+
for (var i = 0; i < arguments.length; i++) {
|
100
|
+
var source = arguments[i];
|
101
|
+
for (var key in source) {
|
102
|
+
if (hasOwnProperty.call(source, key)) {
|
103
|
+
target[key] = source[key];
|
104
|
+
}
|
105
|
+
}
|
106
|
+
}
|
107
|
+
return target;
|
108
|
+
}
|
109
|
+
|
110
|
+
// From: https://remysharp.com/2010/07/21/throttling-function-calls
|
111
|
+
function throttle(fn, threshhold, scope) {
|
112
|
+
threshhold || (threshhold = 250);
|
113
|
+
var last;
|
114
|
+
var deferTimer;
|
115
|
+
return function() {
|
116
|
+
var context = scope || this;
|
117
|
+
var now = +new Date;
|
118
|
+
var args = arguments;
|
119
|
+
if (last && now < last + threshhold) {
|
120
|
+
// hold on to it
|
121
|
+
clearTimeout(deferTimer);
|
122
|
+
deferTimer = setTimeout(function() {
|
123
|
+
last = now;
|
124
|
+
fn.apply(context, args);
|
125
|
+
}, threshhold);
|
126
|
+
} else {
|
127
|
+
last = now;
|
128
|
+
fn.apply(context, args);
|
129
|
+
}
|
130
|
+
};
|
131
|
+
}
|
132
|
+
|
133
|
+
function updateTocListener(headings) {
|
134
|
+
return function updateToc() {
|
135
|
+
return buildHtml.updateToc(headings);
|
136
|
+
};
|
137
|
+
}
|
138
|
+
|
139
|
+
/**
|
140
|
+
* Destroy tocbot.
|
141
|
+
*/
|
142
|
+
tocbot.destroy = function() {
|
143
|
+
// Clear HTML.
|
144
|
+
try {
|
145
|
+
document.querySelector(options.tocSelector).innerHTML = '';
|
146
|
+
} catch (e) {
|
147
|
+
console.warn('Element not found: ' + options.tocSelector); // eslint-disable-line
|
148
|
+
}
|
149
|
+
|
150
|
+
// Remove event listeners.
|
151
|
+
document.removeEventListener('scroll', this._scrollListener, false);
|
152
|
+
document.removeEventListener('resize', this._scrollListener, false);
|
153
|
+
if (buildHtml) {
|
154
|
+
document.removeEventListener('click', this._clickListener, false);
|
155
|
+
}
|
156
|
+
|
157
|
+
// Destroy smoothScroll if it exists.
|
158
|
+
if (smoothScroll) {
|
159
|
+
smoothScroll.destroy();
|
160
|
+
}
|
161
|
+
};
|
162
|
+
|
163
|
+
/**
|
164
|
+
* Initialize tocbot.
|
165
|
+
* @param {object} customOptions
|
166
|
+
*/
|
167
|
+
tocbot.init = function(customOptions) {
|
168
|
+
// feature test
|
169
|
+
if (!supports) {
|
170
|
+
return;
|
171
|
+
}
|
172
|
+
|
173
|
+
// Merge defaults with user options.
|
174
|
+
// Set to options variable at the top.
|
175
|
+
options = extend(defaultOptions, customOptions || {});
|
176
|
+
this.options = options;
|
177
|
+
this.state = {};
|
178
|
+
|
179
|
+
// Pass options to these modules.
|
180
|
+
buildHtml = BuildHtml(options);
|
181
|
+
parseContent = ParseContent(options);
|
182
|
+
|
183
|
+
// For testing purposes.
|
184
|
+
this._buildHtml = buildHtml;
|
185
|
+
this._parseContent = parseContent;
|
186
|
+
|
187
|
+
// Destroy it if it exists first.
|
188
|
+
tocbot.destroy();
|
189
|
+
|
190
|
+
// Get headings array.
|
191
|
+
headingsArray = parseContent.selectHeadings(options.contentSelector, options.headingSelector);
|
192
|
+
// Return if no headings are found.
|
193
|
+
if (headingsArray === null) {
|
194
|
+
return;
|
195
|
+
}
|
196
|
+
|
197
|
+
// Build nested headings array.
|
198
|
+
var nestedHeadingsObj = parseContent.nestHeadingsArray(headingsArray);
|
199
|
+
var nestedHeadings = nestedHeadingsObj.nest;
|
200
|
+
|
201
|
+
// Render.
|
202
|
+
buildHtml.render(options.tocSelector, nestedHeadings);
|
203
|
+
|
204
|
+
// Update Sidebar and bind listeners.
|
205
|
+
// buildHtml.updateToc(headingsArray);
|
206
|
+
this._scrollListener = throttle(function() {
|
207
|
+
buildHtml.updateToc(headingsArray);
|
208
|
+
}, options.throttleTimeout);
|
209
|
+
this._scrollListener();
|
210
|
+
document.addEventListener('scroll', this._scrollListener, false);
|
211
|
+
document.addEventListener('resize', this._scrollListener, false);
|
212
|
+
|
213
|
+
// Bind click listeners to disable animation.
|
214
|
+
this._clickListener = throttle(function(event) {
|
215
|
+
buildHtml.disableTocAnimation(event); // Save reference so event is created / removed properly.
|
216
|
+
buildHtml.updateToc(headingsArray);
|
217
|
+
}, options.throttleTimeout);
|
218
|
+
document.addEventListener('click', this._clickListener, false);
|
219
|
+
|
220
|
+
// Initialize smoothscroll if it exists.
|
221
|
+
if (smoothScroll) {
|
222
|
+
this.smoothScroll = smoothScroll.init(extend(options.smoothScrollOptions, {
|
223
|
+
callback: buildHtml.enableTocAnimation
|
224
|
+
}));
|
225
|
+
}
|
226
|
+
|
227
|
+
return this;
|
228
|
+
};
|
229
|
+
|
230
|
+
/**
|
231
|
+
* Refresh tocbot.
|
232
|
+
*/
|
233
|
+
tocbot.refresh = function(customOptions) {
|
234
|
+
tocbot.destroy();
|
235
|
+
tocbot.init(customOptions || this.options);
|
236
|
+
};
|
237
|
+
|
238
|
+
// Make tocbot available globally.
|
239
|
+
root.tocbot = tocbot;
|
240
|
+
|
241
|
+
return tocbot;
|
242
|
+
});
|
243
|
+
|
244
|
+
/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
|
245
|
+
|
246
|
+
/***/ },
|
247
|
+
/* 1 */
|
248
|
+
/*!******************************************************!*\
|
249
|
+
!*** ./~/smooth-scroll/dist/js/smooth-scroll.min.js ***!
|
250
|
+
\******************************************************/
|
251
|
+
/***/ function(module, exports, __webpack_require__) {
|
252
|
+
|
253
|
+
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(global) {/*! smooth-scroll v10.0.1 | (c) 2016 Chris Ferdinandi | MIT License | http://github.com/cferdinandi/smooth-scroll */
|
254
|
+
!function(e,t){ true?!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (t(e)), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)):"object"==typeof exports?module.exports=t(e):e.smoothScroll=t(e)}("undefined"!=typeof global?global:this.window||this.global,function(e){"use strict";var t,n,o,r,a,i,u,c={},l="querySelector"in document&&"addEventListener"in e,s={selector:"[data-scroll]",selectorHeader:null,speed:500,easing:"easeInOutCubic",offset:0,callback:function(){}},f=function(){var e={},t=!1,n=0,o=arguments.length;"[object Boolean]"===Object.prototype.toString.call(arguments[0])&&(t=arguments[0],n++);for(var r=function(n){for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(t&&"[object Object]"===Object.prototype.toString.call(n[o])?e[o]=f(!0,e[o],n[o]):e[o]=n[o])};o>n;n++){var a=arguments[n];r(a)}return e},d=function(e){return Math.max(e.scrollHeight,e.offsetHeight,e.clientHeight)},h=function(e,t){var n,o,r=t.charAt(0),a="classList"in document.documentElement;for("["===r&&(t=t.substr(1,t.length-2),n=t.split("="),n.length>1&&(o=!0,n[1]=n[1].replace(/"/g,"").replace(/'/g,"")));e&&e!==document&&1===e.nodeType;e=e.parentNode){if("."===r)if(a){if(e.classList.contains(t.substr(1)))return e}else if(new RegExp("(^|\\s)"+t.substr(1)+"(\\s|$)").test(e.className))return e;if("#"===r&&e.id===t.substr(1))return e;if("["===r&&e.hasAttribute(n[0])){if(!o)return e;if(e.getAttribute(n[0])===n[1])return e}if(e.tagName.toLowerCase()===t)return e}return null},m=function(e){"#"===e.charAt(0)&&(e=e.substr(1));for(var t,n=String(e),o=n.length,r=-1,a="",i=n.charCodeAt(0);++r<o;){if(t=n.charCodeAt(r),0===t)throw new InvalidCharacterError("Invalid character: the input contains U+0000.");a+=t>=1&&31>=t||127==t||0===r&&t>=48&&57>=t||1===r&&t>=48&&57>=t&&45===i?"\\"+t.toString(16)+" ":t>=128||45===t||95===t||t>=48&&57>=t||t>=65&&90>=t||t>=97&&122>=t?n.charAt(r):"\\"+n.charAt(r)}return"#"+a},g=function(e,t){var n;return"easeInQuad"===e&&(n=t*t),"easeOutQuad"===e&&(n=t*(2-t)),"easeInOutQuad"===e&&(n=.5>t?2*t*t:-1+(4-2*t)*t),"easeInCubic"===e&&(n=t*t*t),"easeOutCubic"===e&&(n=--t*t*t+1),"easeInOutCubic"===e&&(n=.5>t?4*t*t*t:(t-1)*(2*t-2)*(2*t-2)+1),"easeInQuart"===e&&(n=t*t*t*t),"easeOutQuart"===e&&(n=1- --t*t*t*t),"easeInOutQuart"===e&&(n=.5>t?8*t*t*t*t:1-8*--t*t*t*t),"easeInQuint"===e&&(n=t*t*t*t*t),"easeOutQuint"===e&&(n=1+--t*t*t*t*t),"easeInOutQuint"===e&&(n=.5>t?16*t*t*t*t*t:1+16*--t*t*t*t*t),n||t},p=function(e,t,n){var o=0;if(e.offsetParent)do o+=e.offsetTop,e=e.offsetParent;while(e);return o=Math.max(o-t-n,0),Math.min(o,v()-b())},b=function(){return Math.max(document.documentElement.clientHeight,e.innerHeight||0)},v=function(){return Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight)},y=function(e){return e&&"object"==typeof JSON&&"function"==typeof JSON.parse?JSON.parse(e):{}},O=function(e){return e?d(e)+e.offsetTop:0},H=function(t,n,o){o||(t.focus(),document.activeElement.id!==t.id&&(t.setAttribute("tabindex","-1"),t.focus(),t.style.outline="none"),e.scrollTo(0,n))};c.animateScroll=function(n,o,i){var c=y(o?o.getAttribute("data-options"):null),l=f(t||s,i||{},c),d="[object Number]"===Object.prototype.toString.call(n)?!0:!1,h=d||!n.tagName?null:n;if(d||h){var m=e.pageYOffset;l.selectorHeader&&!r&&(r=document.querySelector(l.selectorHeader)),a||(a=O(r));var b,I,S=d?n:p(h,a,parseInt(l.offset,10)),E=S-m,A=v(),j=0,L=function(t,r,a){var i=e.pageYOffset;(t==r||i==r||e.innerHeight+i>=A)&&(clearInterval(a),H(n,r,d),l.callback(n,o))},w=function(){j+=16,b=j/parseInt(l.speed,10),b=b>1?1:b,I=m+E*g(l.easing,b),e.scrollTo(0,Math.floor(I)),L(I,S,u)},C=function(){clearInterval(u),u=setInterval(w,16)};0===e.pageYOffset&&e.scrollTo(0,0),C()}};var I=function(t){e.location.hash;n&&(n.id=n.getAttribute("data-scroll-id"),c.animateScroll(n,o),n=null,o=null)},S=function(r){if(0===r.button&&!r.metaKey&&!r.ctrlKey&&(o=h(r.target,t.selector),o&&"a"===o.tagName.toLowerCase()&&o.hostname===e.location.hostname&&o.pathname===e.location.pathname&&/#/.test(o.href))){var a=m(o.hash);if("#"===a){r.preventDefault(),n=document.body;var i=n.id?n.id:"smooth-scroll-top";return n.setAttribute("data-scroll-id",i),n.id="",void(e.location.hash.substring(1)===i?I():e.location.hash=i)}n=document.querySelector(a),n&&(n.setAttribute("data-scroll-id",n.id),n.id="",o.hash===e.location.hash&&(r.preventDefault(),I()))}},E=function(e){i||(i=setTimeout(function(){i=null,a=O(r)},66))};return c.destroy=function(){t&&(document.removeEventListener("click",S,!1),e.removeEventListener("resize",E,!1),t=null,n=null,o=null,r=null,a=null,i=null,u=null)},c.init=function(n){l&&(c.destroy(),t=f(s,n||{}),r=t.selectorHeader?document.querySelector(t.selectorHeader):null,a=O(r),document.addEventListener("click",S,!1),e.addEventListener("hashchange",I,!1),r&&e.addEventListener("resize",E,!1))},c});
|
255
|
+
/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
|
256
|
+
|
257
|
+
/***/ },
|
258
|
+
/* 2 */
|
259
|
+
/*!***********************************!*\
|
260
|
+
!*** ./src/js/default-options.js ***!
|
261
|
+
\***********************************/
|
262
|
+
/***/ function(module, exports) {
|
263
|
+
|
264
|
+
/**
|
265
|
+
* Tocbot default options should all live in this file.
|
266
|
+
*
|
267
|
+
* @author Tim Scanlin
|
268
|
+
*/
|
269
|
+
|
270
|
+
module.exports = {
|
271
|
+
// Where to render the table of contents.
|
272
|
+
tocSelector: '.js-toc',
|
273
|
+
// Where to grab the headings to build the table of contents.
|
274
|
+
contentSelector: '.js-toc-content',
|
275
|
+
// Which headings to grab inside of the contentSelector element.
|
276
|
+
headingSelector: 'h1, h2, h3',
|
277
|
+
// Headings that match the ignoreSelector will be skipped.
|
278
|
+
ignoreSelector: '.js-toc-ignore',
|
279
|
+
// Main class to add to links.
|
280
|
+
linkClass: 'toc-link',
|
281
|
+
// Extra classes to add to links.
|
282
|
+
extraLinkClasses: '',
|
283
|
+
// Class to add to active links,
|
284
|
+
// the link corresponding to the top most heading on the page.
|
285
|
+
activeLinkClass: 'is-active-link',
|
286
|
+
// Main class to add to lists.
|
287
|
+
listClass: 'toc-list',
|
288
|
+
// Extra classes to add to lists.
|
289
|
+
extraListClasses: '',
|
290
|
+
// Class that gets added when a list should be collapsed.
|
291
|
+
isCollapsedClass: 'is-collapsed',
|
292
|
+
// Class that gets added when a list should be able
|
293
|
+
// to be collapsed but isn't necessarily collpased.
|
294
|
+
collapsibleClass: 'is-collapsible',
|
295
|
+
// Class to add to list items.
|
296
|
+
listItemClass: 'toc-list-item',
|
297
|
+
// How many heading levels should not be collpased.
|
298
|
+
// For example, number 6 will show everything since
|
299
|
+
// there are only 6 heading levels and number 0 will collpase them all.
|
300
|
+
// The sections that are hidden will open
|
301
|
+
// and close as you scroll to headings within them.
|
302
|
+
collapseDepth: 0,
|
303
|
+
// smooth-scroll options object, see docs at:
|
304
|
+
// https://github.com/cferdinandi/smooth-scroll
|
305
|
+
smoothScrollOptions: {
|
306
|
+
easing: 'easeInOutCubic',
|
307
|
+
offset: 0,
|
308
|
+
speed: 300, // animation duration.
|
309
|
+
updateURL: true
|
310
|
+
},
|
311
|
+
// Headings offset between the headings and the top of the document.
|
312
|
+
headingsOffset: 0,
|
313
|
+
// Timeout between events firing to make sure it's
|
314
|
+
// not too rapid (for performance reasons).
|
315
|
+
throttleTimeout: 50,
|
316
|
+
// Element to add the positionFixedClass to.
|
317
|
+
positionFixedSelector: null,
|
318
|
+
// Fixed position class to add to make sidebar fixed after scrolling
|
319
|
+
// down past the fixedSidebarOffset.
|
320
|
+
positionFixedClass: 'is-position-fixed',
|
321
|
+
// fixedSidebarOffset can be any number but by default is set
|
322
|
+
// to auto which sets the fixedSidebarOffset to the sidebar
|
323
|
+
// element's offsetTop from the top of the document on init.
|
324
|
+
fixedSidebarOffset: 'auto',
|
325
|
+
// includeHtml can be set to true to include the HTML markup from the
|
326
|
+
// heading node instead of just including the textContent.
|
327
|
+
includeHtml: false
|
328
|
+
};
|
329
|
+
|
330
|
+
|
331
|
+
/***/ },
|
332
|
+
/* 3 */
|
333
|
+
/*!******************************!*\
|
334
|
+
!*** ./src/js/build-html.js ***!
|
335
|
+
\******************************/
|
336
|
+
/***/ function(module, exports) {
|
337
|
+
|
338
|
+
/**
|
339
|
+
* This file is responsible for building the DOM and updating DOM state.
|
340
|
+
*
|
341
|
+
* @author Tim Scanlin
|
342
|
+
*/
|
343
|
+
|
344
|
+
module.exports = function(options) {
|
345
|
+
var forEach = [].forEach;
|
346
|
+
var some = [].some;
|
347
|
+
var body = document.body;
|
348
|
+
var currentlyHighlighting = true;
|
349
|
+
var SPACE_CHAR = ' ';
|
350
|
+
|
351
|
+
/**
|
352
|
+
* Create link and list elements.
|
353
|
+
* @param {Object} d
|
354
|
+
* @param {HTMLElement} container
|
355
|
+
* @return {HTMLElement}
|
356
|
+
*/
|
357
|
+
function createEl(d, container) {
|
358
|
+
var link = container.appendChild(createLink(d));
|
359
|
+
if (d.children.length) {
|
360
|
+
var list = createList(d.isCollapsed);
|
361
|
+
d.children.forEach(function(child) {
|
362
|
+
createEl(child, list);
|
363
|
+
});
|
364
|
+
link.appendChild(list);
|
365
|
+
}
|
366
|
+
}
|
367
|
+
|
368
|
+
/**
|
369
|
+
* Render nested heading array data into a given selector.
|
370
|
+
* @param {String} selector
|
371
|
+
* @param {Array} data
|
372
|
+
* @return {HTMLElement}
|
373
|
+
*/
|
374
|
+
function render(selector, data) {
|
375
|
+
var self = this;
|
376
|
+
var collapsed = false;
|
377
|
+
var container = createList(collapsed);
|
378
|
+
|
379
|
+
data.forEach(function(d) {
|
380
|
+
createEl(d, container);
|
381
|
+
});
|
382
|
+
|
383
|
+
var parent = document.querySelector(selector);
|
384
|
+
|
385
|
+
// Return if no parent is found.
|
386
|
+
if (parent === null) {
|
387
|
+
return;
|
388
|
+
}
|
389
|
+
|
390
|
+
// Remove existing child if it exists.
|
391
|
+
if (parent.firstChild) {
|
392
|
+
parent.removeChild(parent.firstChild);
|
393
|
+
}
|
394
|
+
|
395
|
+
// Append the Elements that have been created;
|
396
|
+
return parent.appendChild(container);
|
397
|
+
}
|
398
|
+
|
399
|
+
/**
|
400
|
+
* Create link element.
|
401
|
+
* @param {Object} data
|
402
|
+
* @return {HTMLElement}
|
403
|
+
*/
|
404
|
+
function createLink(data) {
|
405
|
+
var item = document.createElement('li');
|
406
|
+
var a = document.createElement('a');
|
407
|
+
if (options.listItemClass) {
|
408
|
+
item.setAttribute('class', options.listItemClass);
|
409
|
+
}
|
410
|
+
if (options.includeHtml && data.childNodes.length) {
|
411
|
+
forEach.call(data.childNodes, function(node) {
|
412
|
+
a.appendChild(node.cloneNode(true));
|
413
|
+
});
|
414
|
+
} else {
|
415
|
+
// Default behavior.
|
416
|
+
a.textContent = data.textContent;
|
417
|
+
}
|
418
|
+
// Property for smooth-scroll.
|
419
|
+
a.setAttribute('data-scroll', '');
|
420
|
+
a.setAttribute('href', '#' + data.id);
|
421
|
+
a.setAttribute('class', options.linkClass
|
422
|
+
+ SPACE_CHAR + 'node-name--' + data.nodeName
|
423
|
+
+ SPACE_CHAR + options.extraLinkClasses);
|
424
|
+
item.appendChild(a);
|
425
|
+
return item;
|
426
|
+
}
|
427
|
+
|
428
|
+
/**
|
429
|
+
* Create list element.
|
430
|
+
* @param {Boolean} isCollapsed
|
431
|
+
* @return {HTMLElement}
|
432
|
+
*/
|
433
|
+
function createList(isCollapsed) {
|
434
|
+
var list = document.createElement('ul');
|
435
|
+
var classes = options.listClass
|
436
|
+
+ SPACE_CHAR + options.extraListClasses;
|
437
|
+
if (isCollapsed) {
|
438
|
+
classes += SPACE_CHAR + options.collapsibleClass;
|
439
|
+
classes += SPACE_CHAR + options.isCollapsedClass;
|
440
|
+
}
|
441
|
+
list.setAttribute('class', classes);
|
442
|
+
return list;
|
443
|
+
}
|
444
|
+
|
445
|
+
/**
|
446
|
+
* Update fixed sidebar class.
|
447
|
+
* @return {HTMLElement}
|
448
|
+
*/
|
449
|
+
function updateFixedSidebarClass() {
|
450
|
+
var top = document.documentElement.scrollTop || body.scrollTop;
|
451
|
+
var posFixedEl = document.querySelector(options.positionFixedSelector);
|
452
|
+
|
453
|
+
if (options.fixedSidebarOffset === 'auto') {
|
454
|
+
options.fixedSidebarOffset = document.querySelector(options.tocSelector).offsetTop;
|
455
|
+
}
|
456
|
+
|
457
|
+
if (top > options.fixedSidebarOffset) {
|
458
|
+
if (posFixedEl.className.indexOf(options.positionFixedClass) === -1) {
|
459
|
+
posFixedEl.className += SPACE_CHAR + options.positionFixedClass;
|
460
|
+
}
|
461
|
+
} else {
|
462
|
+
posFixedEl.className = posFixedEl.className.split(SPACE_CHAR + options.positionFixedClass).join('');
|
463
|
+
}
|
464
|
+
}
|
465
|
+
|
466
|
+
/**
|
467
|
+
* Update TOC highlighting and collpased groupings.
|
468
|
+
*/
|
469
|
+
function updateToc(headingsArray) {
|
470
|
+
var top = document.documentElement.scrollTop || body.scrollTop;
|
471
|
+
|
472
|
+
// Add fixed class at offset;
|
473
|
+
if (options.positionFixedSelector) {
|
474
|
+
updateFixedSidebarClass();
|
475
|
+
}
|
476
|
+
|
477
|
+
// Get the top most heading currently visible on the page so we know what to highlight.
|
478
|
+
var headings = headingsArray;
|
479
|
+
var topHeader;
|
480
|
+
// Using some instead of each so that we can escape early.
|
481
|
+
if (currentlyHighlighting
|
482
|
+
&& document.querySelector(options.tocSelector) !== null
|
483
|
+
&& headings.length > 0) {
|
484
|
+
some.call(headings, function(heading, i) {
|
485
|
+
if (heading.offsetTop > top + options.headingsOffset) {
|
486
|
+
// Don't allow negative index value.
|
487
|
+
var index = (i === 0) ? i : i - 1;
|
488
|
+
topHeader = headings[index];
|
489
|
+
return true;
|
490
|
+
} else if (i === headings.length - 1) {
|
491
|
+
// This allows scrolling for the last heading on the page.
|
492
|
+
topHeader = headings[headings.length - 1];
|
493
|
+
return true;
|
494
|
+
}
|
495
|
+
});
|
496
|
+
|
497
|
+
// Remove the active class from the other tocLinks.
|
498
|
+
var tocLinks = document.querySelector(options.tocSelector)
|
499
|
+
.querySelectorAll('.' + options.linkClass);
|
500
|
+
forEach.call(tocLinks, function(tocLink) {
|
501
|
+
tocLink.className = tocLink.className.split(SPACE_CHAR + options.activeLinkClass).join('');
|
502
|
+
});
|
503
|
+
|
504
|
+
// Add the active class to the active tocLink.
|
505
|
+
var activeTocLink = document.querySelector(options.tocSelector)
|
506
|
+
.querySelector('.' + options.linkClass
|
507
|
+
+ '.node-name--' + topHeader.nodeName
|
508
|
+
+ '[href="#' + topHeader.id + '"]');
|
509
|
+
activeTocLink.className += SPACE_CHAR + options.activeLinkClass;
|
510
|
+
|
511
|
+
var tocLists = document.querySelector(options.tocSelector)
|
512
|
+
.querySelectorAll('.' + options.listClass + '.' + options.collapsibleClass);
|
513
|
+
|
514
|
+
// Collapse the other collapsible lists.
|
515
|
+
forEach.call(tocLists, function(list) {
|
516
|
+
var collapsedClass = SPACE_CHAR + options.isCollapsedClass;
|
517
|
+
if (list.className.indexOf(collapsedClass) === -1) {
|
518
|
+
list.className += SPACE_CHAR + options.isCollapsedClass;
|
519
|
+
}
|
520
|
+
});
|
521
|
+
|
522
|
+
// Expand the active link's collapsible list and its sibling if applicable.
|
523
|
+
if (activeTocLink.nextSibling) {
|
524
|
+
activeTocLink.nextSibling.className = activeTocLink.nextSibling.className.split(SPACE_CHAR + options.isCollapsedClass).join('');
|
525
|
+
}
|
526
|
+
removeCollapsedFromParents(activeTocLink.parentNode.parentNode);
|
527
|
+
}
|
528
|
+
}
|
529
|
+
|
530
|
+
/**
|
531
|
+
* Remove collpased class from parent elements.
|
532
|
+
* @param {HTMLElement} element
|
533
|
+
* @return {HTMLElement}
|
534
|
+
*/
|
535
|
+
function removeCollapsedFromParents(element) {
|
536
|
+
if (element.className.indexOf(options.collapsibleClass) !== -1) {
|
537
|
+
element.className = element.className.split(SPACE_CHAR + options.isCollapsedClass).join('');
|
538
|
+
return removeCollapsedFromParents(element.parentNode.parentNode);
|
539
|
+
}
|
540
|
+
return element;
|
541
|
+
}
|
542
|
+
|
543
|
+
/**
|
544
|
+
* Disable TOC Animation when a link is clicked.
|
545
|
+
* @param {Event} event
|
546
|
+
*/
|
547
|
+
function disableTocAnimation(event) {
|
548
|
+
var target = event.target || event.srcElement;
|
549
|
+
if (target.className.indexOf(options.linkClass) === -1) {
|
550
|
+
return;
|
551
|
+
}
|
552
|
+
// Bind to tocLink clicks to temporarily disable highlighting
|
553
|
+
// while smoothScroll is animating.
|
554
|
+
currentlyHighlighting = false;
|
555
|
+
}
|
556
|
+
|
557
|
+
/**
|
558
|
+
* Enable TOC Animation.
|
559
|
+
*/
|
560
|
+
function enableTocAnimation() {
|
561
|
+
currentlyHighlighting = true;
|
562
|
+
}
|
563
|
+
|
564
|
+
return {
|
565
|
+
enableTocAnimation: enableTocAnimation,
|
566
|
+
disableTocAnimation: disableTocAnimation,
|
567
|
+
render: render,
|
568
|
+
updateToc: updateToc
|
569
|
+
};
|
570
|
+
};
|
571
|
+
|
572
|
+
|
573
|
+
/***/ },
|
574
|
+
/* 4 */
|
575
|
+
/*!*********************************!*\
|
576
|
+
!*** ./src/js/parse-content.js ***!
|
577
|
+
\*********************************/
|
578
|
+
/***/ function(module, exports) {
|
579
|
+
|
580
|
+
/**
|
581
|
+
* This file is responsible for parsing the content from the DOM and making
|
582
|
+
* sure data is nested properly.
|
583
|
+
*
|
584
|
+
* @author Tim Scanlin
|
585
|
+
*/
|
586
|
+
|
587
|
+
module.exports = function parseContent(options) {
|
588
|
+
var reduce = [].reduce;
|
589
|
+
|
590
|
+
/**
|
591
|
+
* Get the last item in an array and return a reference to it.
|
592
|
+
* @param {Array} array
|
593
|
+
* @return {Object}
|
594
|
+
*/
|
595
|
+
function getLastItem(array) {
|
596
|
+
return array[array.length - 1];
|
597
|
+
}
|
598
|
+
|
599
|
+
/**
|
600
|
+
* Get heading level for a heading dom node.
|
601
|
+
* @param {HTMLElement} heading
|
602
|
+
* @return {Number}
|
603
|
+
*/
|
604
|
+
function getHeadingLevel(heading) {
|
605
|
+
return +heading.nodeName.split('H').join('');
|
606
|
+
}
|
607
|
+
|
608
|
+
/**
|
609
|
+
* Get important properties from a heading element and store in a plain object.
|
610
|
+
* @param {HTMLElement} heading
|
611
|
+
* @return {Object}
|
612
|
+
*/
|
613
|
+
function getHeadingObject(heading) {
|
614
|
+
var obj = {
|
615
|
+
id: heading.id,
|
616
|
+
children: [],
|
617
|
+
nodeName: heading.nodeName,
|
618
|
+
headingLevel: getHeadingLevel(heading),
|
619
|
+
textContent: heading.textContent.trim()
|
620
|
+
};
|
621
|
+
|
622
|
+
if (options.includeHtml) {
|
623
|
+
obj.childNodes = heading.childNodes;
|
624
|
+
}
|
625
|
+
|
626
|
+
return obj;
|
627
|
+
}
|
628
|
+
|
629
|
+
/**
|
630
|
+
* Add a node to the nested array.
|
631
|
+
* @param {Object} node
|
632
|
+
* @param {Array} nest
|
633
|
+
* @return {Array}
|
634
|
+
*/
|
635
|
+
function addNode(node, nest) {
|
636
|
+
var obj = getHeadingObject(node);
|
637
|
+
var level = getHeadingLevel(node);
|
638
|
+
var array = nest;
|
639
|
+
var lastItem = getLastItem(array);
|
640
|
+
var lastItemLevel = lastItem
|
641
|
+
? lastItem.headingLevel
|
642
|
+
: 0;
|
643
|
+
var counter = level - lastItemLevel;
|
644
|
+
|
645
|
+
while (counter > 0) {
|
646
|
+
lastItem = getLastItem(array);
|
647
|
+
if (lastItem && lastItem.children !== undefined) {
|
648
|
+
array = lastItem.children;
|
649
|
+
}
|
650
|
+
counter--;
|
651
|
+
}
|
652
|
+
|
653
|
+
if (level >= options.collapseDepth) {
|
654
|
+
obj.isCollapsed = true;
|
655
|
+
}
|
656
|
+
|
657
|
+
array.push(obj);
|
658
|
+
return array;
|
659
|
+
}
|
660
|
+
|
661
|
+
/**
|
662
|
+
* Select headings in content area, exclude any selector in options.ignoreSelector
|
663
|
+
* @param {String} contentSelector
|
664
|
+
* @param {Array} headingSelector
|
665
|
+
* @return {Array}
|
666
|
+
*/
|
667
|
+
function selectHeadings(contentSelector, headingSelector) {
|
668
|
+
var selectors = headingSelector;
|
669
|
+
if (options.ignoreSelector) {
|
670
|
+
selectors = headingSelector.split(',')
|
671
|
+
.map(function mapSelectors(selector) {
|
672
|
+
return selector.trim() + ':not(' + options.ignoreSelector + ')';
|
673
|
+
});
|
674
|
+
}
|
675
|
+
try {
|
676
|
+
return document.querySelector(contentSelector)
|
677
|
+
.querySelectorAll(selectors);
|
678
|
+
} catch (e) {
|
679
|
+
console.warn('Element not found: ' + contentSelector); // eslint-disable-line
|
680
|
+
return null;
|
681
|
+
}
|
682
|
+
}
|
683
|
+
|
684
|
+
/**
|
685
|
+
* Nest headings array into nested arrays with 'children' property.
|
686
|
+
* @param {Array} headingsArray
|
687
|
+
* @return {Object}
|
688
|
+
*/
|
689
|
+
function nestHeadingsArray(headingsArray) {
|
690
|
+
return reduce.call(headingsArray, function reducer(prev, curr) {
|
691
|
+
var currentHeading = getHeadingObject(curr);
|
692
|
+
|
693
|
+
addNode(currentHeading, prev.nest);
|
694
|
+
return prev;
|
695
|
+
}, {
|
696
|
+
nest: []
|
697
|
+
});
|
698
|
+
}
|
699
|
+
|
700
|
+
return {
|
701
|
+
nestHeadingsArray: nestHeadingsArray,
|
702
|
+
selectHeadings: selectHeadings
|
703
|
+
};
|
704
|
+
};
|
705
|
+
|
706
|
+
|
707
|
+
/***/ }
|
708
|
+
/******/ ]);
|
709
|
+
|