j1m_toc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+