123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077 |
- /******/ (() => { // webpackBootstrap
- /******/ var __webpack_modules__ = ({
- /***/ "./src/js/build-html.js":
- /*!******************************!*\
- !*** ./src/js/build-html.js ***!
- \******************************/
- /***/ ((module) => {
- /* eslint no-var: off */
- /**
- * This file is responsible for building the DOM and updating DOM state.
- *
- * @author Tim Scanlin
- */
- module.exports = function (options) {
- var forEach = [].forEach
- var some = [].some
- var body = document.body
- var tocElement
- var currentlyHighlighting = true
- var SPACE_CHAR = ' '
- /**
- * Create link and list elements.
- * @param {Object} d
- * @param {HTMLElement} container
- * @return {HTMLElement}
- */
- function createEl (d, container) {
- var link = container.appendChild(createLink(d))
- if (d.children.length) {
- var list = createList(d.isCollapsed)
- d.children.forEach(function (child) {
- createEl(child, list)
- })
- link.appendChild(list)
- }
- }
- /**
- * Render nested heading array data into a given element.
- * @param {HTMLElement} parent Optional. If provided updates the {@see tocElement} to match.
- * @param {Array} data
- * @return {HTMLElement}
- */
- function render (parent, data) {
- var collapsed = false
- var container = createList(collapsed)
- data.forEach(function (d) {
- createEl(d, container)
- })
- // Return if no TOC element is provided or known.
- tocElement = parent || tocElement
- if (tocElement === null) {
- return
- }
- // Remove existing child if it exists.
- if (tocElement.firstChild) {
- tocElement.removeChild(tocElement.firstChild)
- }
- // Just return the parent and don't append the list if no links are found.
- if (data.length === 0) {
- return tocElement
- }
- // Append the Elements that have been created
- return tocElement.appendChild(container)
- }
- /**
- * Create link element.
- * @param {Object} data
- * @return {HTMLElement}
- */
- function createLink (data) {
- var item = document.createElement('li')
- var a = document.createElement('a')
- if (options.listItemClass) {
- item.setAttribute('class', options.listItemClass)
- }
- if (options.onClick) {
- a.onclick = options.onClick
- }
- if (options.includeTitleTags) {
- a.setAttribute('title', data.textContent)
- }
- if (options.includeHtml && data.childNodes.length) {
- forEach.call(data.childNodes, function (node) {
- a.appendChild(node.cloneNode(true))
- })
- } else {
- // Default behavior. Set to textContent to keep tests happy.
- a.textContent = data.textContent
- }
- a.setAttribute('href', options.basePath + '#' + data.id)
- a.setAttribute('class', options.linkClass +
- SPACE_CHAR + 'node-name--' + data.nodeName +
- SPACE_CHAR + options.extraLinkClasses)
- item.appendChild(a)
- return item
- }
- /**
- * Create list element.
- * @param {Boolean} isCollapsed
- * @return {HTMLElement}
- */
- function createList (isCollapsed) {
- var listElement = (options.orderedList) ? 'ol' : 'ul'
- var list = document.createElement(listElement)
- var classes = options.listClass + SPACE_CHAR + options.extraListClasses
- if (isCollapsed) {
- // No plus/equals here fixes compilcation issue.
- classes = classes + SPACE_CHAR + options.collapsibleClass
- classes = classes + SPACE_CHAR + options.isCollapsedClass
- }
- list.setAttribute('class', classes)
- return list
- }
- /**
- * Update fixed sidebar class.
- * @return {HTMLElement}
- */
- function updateFixedSidebarClass () {
- if (options.scrollContainer && document.querySelector(options.scrollContainer)) {
- var top
- top = document.querySelector(options.scrollContainer).scrollTop
- } else {
- top = document.documentElement.scrollTop || body.scrollTop
- }
- var posFixedEl = document.querySelector(options.positionFixedSelector)
- if (options.fixedSidebarOffset === 'auto') {
- options.fixedSidebarOffset = tocElement.offsetTop
- }
- if (top > options.fixedSidebarOffset) {
- if (posFixedEl.className.indexOf(options.positionFixedClass) === -1) {
- posFixedEl.className += SPACE_CHAR + options.positionFixedClass
- }
- } else {
- posFixedEl.className = posFixedEl.className.replace(SPACE_CHAR + options.positionFixedClass, '')
- }
- }
- /**
- * Get top position of heading
- * @param {HTMLElement} obj
- * @return {int} position
- */
- function getHeadingTopPos (obj) {
- var position = 0
- if (obj !== null) {
- position = obj.offsetTop
- if (options.hasInnerContainers) { position += getHeadingTopPos(obj.offsetParent) }
- }
- return position
- }
- /**
- * Update className only when changed.
- * @param {HTMLElement} obj
- * @param {string} className
- * @return {HTMLElement} obj
- */
- function updateClassname (obj, className) {
- if (obj && obj.className !== className) {
- obj.className = className
- }
- return obj
- }
- /**
- * Update TOC highlighting and collapsed groupings.
- */
- function updateToc (headingsArray) {
- // If a fixed content container was set
- if (options.scrollContainer && document.querySelector(options.scrollContainer)) {
- var top
- top = document.querySelector(options.scrollContainer).scrollTop
- } else {
- top = document.documentElement.scrollTop || body.scrollTop
- }
- // Add fixed class at offset
- if (options.positionFixedSelector) {
- updateFixedSidebarClass()
- }
- // Get the top most heading currently visible on the page so we know what to highlight.
- var headings = headingsArray
- var topHeader
- // Using some instead of each so that we can escape early.
- if (currentlyHighlighting &&
- tocElement !== null &&
- headings.length > 0) {
- some.call(headings, function (heading, i) {
- if (getHeadingTopPos(heading) > top + options.headingsOffset + 10) {
- // Don't allow negative index value.
- var index = (i === 0) ? i : i - 1
- topHeader = headings[index]
- return true
- } else if (i === headings.length - 1) {
- // This allows scrolling for the last heading on the page.
- topHeader = headings[headings.length - 1]
- return true
- }
- })
- var oldActiveTocLink = tocElement.querySelector('.' + options.activeLinkClass)
- var activeTocLink = tocElement
- .querySelector('.' + options.linkClass +
- '.node-name--' + topHeader.nodeName +
- '[href="' + options.basePath + '#' + topHeader.id.replace(/([ #;&,.+*~':"!^$[\]()=>|/\\@])/g, '\\$1') + '"]')
- // Performance improvement to only change the classes
- // for the toc if a new link should be highlighted.
- if (oldActiveTocLink === activeTocLink) {
- return
- }
- // Remove the active class from the other tocLinks.
- var tocLinks = tocElement
- .querySelectorAll('.' + options.linkClass)
- forEach.call(tocLinks, function (tocLink) {
- updateClassname(tocLink, tocLink.className.replace(SPACE_CHAR + options.activeLinkClass, ''))
- })
- var tocLis = tocElement
- .querySelectorAll('.' + options.listItemClass)
- forEach.call(tocLis, function (tocLi) {
- updateClassname(tocLi, tocLi.className.replace(SPACE_CHAR + options.activeListItemClass, ''))
- })
- // Add the active class to the active tocLink.
- if (activeTocLink && activeTocLink.className.indexOf(options.activeLinkClass) === -1) {
- activeTocLink.className += SPACE_CHAR + options.activeLinkClass
- }
- var li = activeTocLink && activeTocLink.parentNode
- if (li && li.className.indexOf(options.activeListItemClass) === -1) {
- li.className += SPACE_CHAR + options.activeListItemClass
- }
- var tocLists = tocElement
- .querySelectorAll('.' + options.listClass + '.' + options.collapsibleClass)
- // Collapse the other collapsible lists.
- forEach.call(tocLists, function (list) {
- if (list.className.indexOf(options.isCollapsedClass) === -1) {
- list.className += SPACE_CHAR + options.isCollapsedClass
- }
- })
- // Expand the active link's collapsible list and its sibling if applicable.
- if (activeTocLink && activeTocLink.nextSibling && activeTocLink.nextSibling.className.indexOf(options.isCollapsedClass) !== -1) {
- updateClassname(activeTocLink.nextSibling, activeTocLink.nextSibling.className.replace(SPACE_CHAR + options.isCollapsedClass, ''))
- }
- removeCollapsedFromParents(activeTocLink && activeTocLink.parentNode.parentNode)
- }
- }
- /**
- * Remove collapsed class from parent elements.
- * @param {HTMLElement} element
- * @return {HTMLElement}
- */
- function removeCollapsedFromParents (element) {
- if (element && element.className.indexOf(options.collapsibleClass) !== -1 && element.className.indexOf(options.isCollapsedClass) !== -1) {
- updateClassname(element, element.className.replace(SPACE_CHAR + options.isCollapsedClass, ''))
- return removeCollapsedFromParents(element.parentNode.parentNode)
- }
- return element
- }
- /**
- * Disable TOC Animation when a link is clicked.
- * @param {Event} event
- */
- function disableTocAnimation (event) {
- var target = event.target || event.srcElement
- if (typeof target.className !== 'string' || target.className.indexOf(options.linkClass) === -1) {
- return
- }
- // Bind to tocLink clicks to temporarily disable highlighting
- // while smoothScroll is animating.
- currentlyHighlighting = false
- }
- /**
- * Enable TOC Animation.
- */
- function enableTocAnimation () {
- currentlyHighlighting = true
- }
- return {
- enableTocAnimation,
- disableTocAnimation,
- render,
- updateToc
- }
- }
- /***/ }),
- /***/ "./src/js/default-options.js":
- /*!***********************************!*\
- !*** ./src/js/default-options.js ***!
- \***********************************/
- /***/ ((module) => {
- module.exports = {
- // Where to render the table of contents.
- tocSelector: '.js-toc',
- // Where to grab the headings to build the table of contents.
- contentSelector: '.js-toc-content',
- // Which headings to grab inside of the contentSelector element.
- headingSelector: 'h1, h2, h3',
- // Headings that match the ignoreSelector will be skipped.
- ignoreSelector: '.js-toc-ignore',
- // For headings inside relative or absolute positioned containers within content
- hasInnerContainers: false,
- // Main class to add to links.
- linkClass: 'toc-link',
- // Extra classes to add to links.
- extraLinkClasses: '',
- // Class to add to active links,
- // the link corresponding to the top most heading on the page.
- activeLinkClass: 'is-active-link',
- // Main class to add to lists.
- listClass: 'toc-list',
- // Extra classes to add to lists.
- extraListClasses: '',
- // Class that gets added when a list should be collapsed.
- isCollapsedClass: 'is-collapsed',
- // Class that gets added when a list should be able
- // to be collapsed but isn't necessarily collapsed.
- collapsibleClass: 'is-collapsible',
- // Class to add to list items.
- listItemClass: 'toc-list-item',
- // Class to add to active list items.
- activeListItemClass: 'is-active-li',
- // How many heading levels should not be collapsed.
- // For example, number 6 will show everything since
- // there are only 6 heading levels and number 0 will collapse them all.
- // The sections that are hidden will open
- // and close as you scroll to headings within them.
- collapseDepth: 0,
- // Smooth scrolling enabled.
- scrollSmooth: true,
- // Smooth scroll duration.
- scrollSmoothDuration: 420,
- // Smooth scroll offset.
- scrollSmoothOffset: 0,
- // Callback for scroll end.
- scrollEndCallback: function (e) {},
- // Headings offset between the headings and the top of the document (this is meant for minor adjustments).
- headingsOffset: 1,
- // Timeout between events firing to make sure it's
- // not too rapid (for performance reasons).
- throttleTimeout: 50,
- // Element to add the positionFixedClass to.
- positionFixedSelector: null,
- // Fixed position class to add to make sidebar fixed after scrolling
- // down past the fixedSidebarOffset.
- positionFixedClass: 'is-position-fixed',
- // fixedSidebarOffset can be any number but by default is set
- // to auto which sets the fixedSidebarOffset to the sidebar
- // element's offsetTop from the top of the document on init.
- fixedSidebarOffset: 'auto',
- // includeHtml can be set to true to include the HTML markup from the
- // heading node instead of just including the innerText.
- includeHtml: false,
- // includeTitleTags automatically sets the html title tag of the link
- // to match the title. This can be useful for SEO purposes or
- // when truncating titles.
- includeTitleTags: false,
- // onclick function to apply to all links in toc. will be called with
- // the event as the first parameter, and this can be used to stop,
- // propagation, prevent default or perform action
- onClick: function (e) {},
- // orderedList can be set to false to generate unordered lists (ul)
- // instead of ordered lists (ol)
- orderedList: true,
- // If there is a fixed article scroll container, set to calculate titles' offset
- scrollContainer: null,
- // prevent ToC DOM rendering if it's already rendered by an external system
- skipRendering: false,
- // Optional callback to change heading labels.
- // For example it can be used to cut down and put ellipses on multiline headings you deem too long.
- // Called each time a heading is parsed. Expects a string and returns the modified label to display.
- // Additionally, the attribute `data-heading-label` may be used on a heading to specify
- // a shorter string to be used in the TOC.
- // function (string) => string
- headingLabelCallback: false,
- // ignore headings that are hidden in DOM
- ignoreHiddenElements: false,
- // Optional callback to modify properties of parsed headings.
- // The heading element is passed in node parameter and information parsed by default parser is provided in obj parameter.
- // Function has to return the same or modified obj.
- // The heading will be excluded from TOC if nothing is returned.
- // function (object, HTMLElement) => object | void
- headingObjectCallback: null,
- // Set the base path, useful if you use a `base` tag in `head`.
- basePath: '',
- // Only takes affect when `tocSelector` is scrolling,
- // keep the toc scroll position in sync with the content.
- disableTocScrollSync: false,
- // Offset for the toc scroll (top) position when scrolling the page.
- // Only effective if `disableTocScrollSync` is false.
- tocScrollOffset: 0
- }
- /***/ }),
- /***/ "./src/js/index.js":
- /*!*************************!*\
- !*** ./src/js/index.js ***!
- \*************************/
- /***/ ((module, exports, __webpack_require__) => {
- var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* eslint no-var: off */
- /**
- * Tocbot
- * Tocbot creates a table of contents based on HTML headings on a page,
- * this allows users to easily jump to different sections of the document.
- * Tocbot was inspired by tocify (http://gregfranko.com/jquery.tocify.js/).
- * The main differences are that it works natively without any need for jquery or jquery UI).
- *
- * @author Tim Scanlin
- */
- /* globals define */
- (function (root, factory) {
- if (true) {
- !(__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__))
- } else {}
- })(typeof __webpack_require__.g !== 'undefined' ? __webpack_require__.g : window || __webpack_require__.g, function (root) {
- 'use strict'
- // Default options.
- var defaultOptions = __webpack_require__(/*! ./default-options.js */ "./src/js/default-options.js")
- // Object to store current options.
- var options = {}
- // Object for public APIs.
- var tocbot = {}
- var BuildHtml = __webpack_require__(/*! ./build-html.js */ "./src/js/build-html.js")
- var ParseContent = __webpack_require__(/*! ./parse-content.js */ "./src/js/parse-content.js")
- var updateTocScroll = __webpack_require__(/*! ./update-toc-scroll.js */ "./src/js/update-toc-scroll.js")
- // Keep these variables at top scope once options are passed in.
- var buildHtml
- var parseContent
- // Just return if its not a browser.
- var supports = !!root && !!root.document && !!root.document.querySelector && !!root.addEventListener // Feature test
- if (typeof window === 'undefined' && !supports) {
- return
- }
- var headingsArray
- // From: https://github.com/Raynos/xtend
- var hasOwnProperty = Object.prototype.hasOwnProperty
- function extend () {
- var target = {}
- for (var i = 0; i < arguments.length; i++) {
- var source = arguments[i]
- for (var key in source) {
- if (hasOwnProperty.call(source, key)) {
- target[key] = source[key]
- }
- }
- }
- return target
- }
- // From: https://remysharp.com/2010/07/21/throttling-function-calls
- function throttle (fn, threshold, scope) {
- threshold || (threshold = 250)
- var last
- var deferTimer
- return function () {
- var context = scope || this
- var now = +new Date()
- var args = arguments
- if (last && now < last + threshold) {
- // hold on to it
- clearTimeout(deferTimer)
- deferTimer = setTimeout(function () {
- last = now
- fn.apply(context, args)
- }, threshold)
- } else {
- last = now
- fn.apply(context, args)
- }
- }
- }
- function getContentElement (options) {
- try {
- return options.contentElement || document.querySelector(options.contentSelector)
- } catch (e) {
- console.warn('Contents element not found: ' + options.contentSelector) // eslint-disable-line
- return null
- }
- }
- function getTocElement (options) {
- try {
- return options.tocElement || document.querySelector(options.tocSelector)
- } catch (e) {
- console.warn('TOC element not found: ' + options.tocSelector) // eslint-disable-line
- return null
- }
- }
- /**
- * Destroy tocbot.
- */
- tocbot.destroy = function () {
- var tocElement = getTocElement(options)
- if (tocElement === null) {
- return
- }
- if (!options.skipRendering) {
- // Clear HTML.
- if (tocElement) {
- tocElement.innerHTML = ''
- }
- }
- // Remove event listeners.
- if (options.scrollContainer && document.querySelector(options.scrollContainer)) {
- document.querySelector(options.scrollContainer).removeEventListener('scroll', this._scrollListener, false)
- document.querySelector(options.scrollContainer).removeEventListener('resize', this._scrollListener, false)
- if (buildHtml) {
- document.querySelector(options.scrollContainer).removeEventListener('click', this._clickListener, false)
- }
- } else {
- document.removeEventListener('scroll', this._scrollListener, false)
- document.removeEventListener('resize', this._scrollListener, false)
- if (buildHtml) {
- document.removeEventListener('click', this._clickListener, false)
- }
- }
- }
- /**
- * Initialize tocbot.
- * @param {object} customOptions
- */
- tocbot.init = function (customOptions) {
- // feature test
- if (!supports) {
- return
- }
- // Merge defaults with user options.
- // Set to options variable at the top.
- options = extend(defaultOptions, customOptions || {})
- this.options = options
- this.state = {}
- // Init smooth scroll if enabled (default).
- if (options.scrollSmooth) {
- options.duration = options.scrollSmoothDuration
- options.offset = options.scrollSmoothOffset
- tocbot.scrollSmooth = (__webpack_require__(/*! ./scroll-smooth */ "./src/js/scroll-smooth/index.js").initSmoothScrolling)(options)
- }
- // Pass options to these modules.
- buildHtml = BuildHtml(options)
- parseContent = ParseContent(options)
- // For testing purposes.
- this._buildHtml = buildHtml
- this._parseContent = parseContent
- this._headingsArray = headingsArray
- // Destroy it if it exists first.
- tocbot.destroy()
- var contentElement = getContentElement(options)
- if (contentElement === null) {
- return
- }
- var tocElement = getTocElement(options)
- if (tocElement === null) {
- return
- }
- // Get headings array.
- headingsArray = parseContent.selectHeadings(contentElement, options.headingSelector)
- // Return if no headings are found.
- if (headingsArray === null) {
- return
- }
- // Build nested headings array.
- var nestedHeadingsObj = parseContent.nestHeadingsArray(headingsArray)
- var nestedHeadings = nestedHeadingsObj.nest
- // Render.
- if (!options.skipRendering) {
- buildHtml.render(tocElement, nestedHeadings)
- } else {
- // No need to attach listeners if skipRendering is true, this was causing errors.
- return this
- }
- // Update Sidebar and bind listeners.
- this._scrollListener = throttle(function (e) {
- buildHtml.updateToc(headingsArray)
- !options.disableTocScrollSync && updateTocScroll(options)
- var isTop = e && e.target && e.target.scrollingElement && e.target.scrollingElement.scrollTop === 0
- if ((e && (e.eventPhase === 0 || e.currentTarget === null)) || isTop) {
- buildHtml.updateToc(headingsArray)
- if (options.scrollEndCallback) {
- options.scrollEndCallback(e)
- }
- }
- }, options.throttleTimeout)
- this._scrollListener()
- if (options.scrollContainer && document.querySelector(options.scrollContainer)) {
- document.querySelector(options.scrollContainer).addEventListener('scroll', this._scrollListener, false)
- document.querySelector(options.scrollContainer).addEventListener('resize', this._scrollListener, false)
- } else {
- document.addEventListener('scroll', this._scrollListener, false)
- document.addEventListener('resize', this._scrollListener, false)
- }
- // Bind click listeners to disable animation.
- var timeout = null
- this._clickListener = throttle(function (event) {
- if (options.scrollSmooth) {
- buildHtml.disableTocAnimation(event)
- }
- buildHtml.updateToc(headingsArray)
- // Timeout to re-enable the animation.
- timeout && clearTimeout(timeout)
- timeout = setTimeout(function () {
- buildHtml.enableTocAnimation()
- }, options.scrollSmoothDuration)
- }, options.throttleTimeout)
- if (options.scrollContainer && document.querySelector(options.scrollContainer)) {
- document.querySelector(options.scrollContainer).addEventListener('click', this._clickListener, false)
- } else {
- document.addEventListener('click', this._clickListener, false)
- }
- return this
- }
- /**
- * Refresh tocbot.
- */
- tocbot.refresh = function (customOptions) {
- tocbot.destroy()
- tocbot.init(customOptions || this.options)
- }
- // Make tocbot available globally.
- root.tocbot = tocbot
- return tocbot
- })
- /***/ }),
- /***/ "./src/js/parse-content.js":
- /*!*********************************!*\
- !*** ./src/js/parse-content.js ***!
- \*********************************/
- /***/ ((module) => {
- /* eslint no-var: off */
- /**
- * This file is responsible for parsing the content from the DOM and making
- * sure data is nested properly.
- *
- * @author Tim Scanlin
- */
- module.exports = function parseContent (options) {
- var reduce = [].reduce
- /**
- * Get the last item in an array and return a reference to it.
- * @param {Array} array
- * @return {Object}
- */
- function getLastItem (array) {
- return array[array.length - 1]
- }
- /**
- * Get heading level for a heading dom node.
- * @param {HTMLElement} heading
- * @return {Number}
- */
- function getHeadingLevel (heading) {
- return +heading.nodeName.toUpperCase().replace('H', '')
- }
- /**
- * Determine whether the object is an HTML Element.
- * Also works inside iframes. HTML Elements might be created by the parent document.
- * @param {Object} maybeElement
- * @return {Number}
- */
- function isHTMLElement (maybeElement) {
- try {
- return (
- maybeElement instanceof window.HTMLElement ||
- maybeElement instanceof window.parent.HTMLElement
- )
- } catch (e) {
- return maybeElement instanceof window.HTMLElement
- }
- }
- /**
- * Get important properties from a heading element and store in a plain object.
- * @param {HTMLElement} heading
- * @return {Object}
- */
- function getHeadingObject (heading) {
- // each node is processed twice by this method because nestHeadingsArray() and addNode() calls it
- // first time heading is real DOM node element, second time it is obj
- // that is causing problem so I am processing only original DOM node
- if (!isHTMLElement(heading)) return heading
- if (options.ignoreHiddenElements && (!heading.offsetHeight || !heading.offsetParent)) {
- return null
- }
- const headingLabel = heading.getAttribute('data-heading-label') ||
- (options.headingLabelCallback ? String(options.headingLabelCallback(heading.innerText)) : (heading.innerText || heading.textContent).trim())
- var obj = {
- id: heading.id,
- children: [],
- nodeName: heading.nodeName,
- headingLevel: getHeadingLevel(heading),
- textContent: headingLabel
- }
- if (options.includeHtml) {
- obj.childNodes = heading.childNodes
- }
- if (options.headingObjectCallback) {
- return options.headingObjectCallback(obj, heading)
- }
- return obj
- }
- /**
- * Add a node to the nested array.
- * @param {Object} node
- * @param {Array} nest
- * @return {Array}
- */
- function addNode (node, nest) {
- var obj = getHeadingObject(node)
- var level = obj.headingLevel
- var array = nest
- var lastItem = getLastItem(array)
- var lastItemLevel = lastItem
- ? lastItem.headingLevel
- : 0
- var counter = level - lastItemLevel
- while (counter > 0) {
- lastItem = getLastItem(array)
- // Handle case where there are multiple h5+ in a row.
- if (lastItem && level === lastItem.headingLevel) {
- break
- } else if (lastItem && lastItem.children !== undefined) {
- array = lastItem.children
- }
- counter--
- }
- if (level >= options.collapseDepth) {
- obj.isCollapsed = true
- }
- array.push(obj)
- return array
- }
- /**
- * Select headings in content area, exclude any selector in options.ignoreSelector
- * @param {HTMLElement} contentElement
- * @param {Array} headingSelector
- * @return {Array}
- */
- function selectHeadings (contentElement, headingSelector) {
- var selectors = headingSelector
- if (options.ignoreSelector) {
- selectors = headingSelector.split(',')
- .map(function mapSelectors (selector) {
- return selector.trim() + ':not(' + options.ignoreSelector + ')'
- })
- }
- try {
- return contentElement.querySelectorAll(selectors)
- } catch (e) {
- console.warn('Headers not found with selector: ' + selectors); // eslint-disable-line
- return null
- }
- }
- /**
- * Nest headings array into nested arrays with 'children' property.
- * @param {Array} headingsArray
- * @return {Object}
- */
- function nestHeadingsArray (headingsArray) {
- return reduce.call(headingsArray, function reducer (prev, curr) {
- var currentHeading = getHeadingObject(curr)
- if (currentHeading) {
- addNode(currentHeading, prev.nest)
- }
- return prev
- }, {
- nest: []
- })
- }
- return {
- nestHeadingsArray,
- selectHeadings
- }
- }
- /***/ }),
- /***/ "./src/js/scroll-smooth/index.js":
- /*!***************************************!*\
- !*** ./src/js/scroll-smooth/index.js ***!
- \***************************************/
- /***/ ((__unused_webpack_module, exports) => {
- /* eslint no-var: off */
- /* globals location, requestAnimationFrame */
- exports.initSmoothScrolling = initSmoothScrolling
- function initSmoothScrolling (options) {
- // if (isCssSmoothSCrollSupported()) { return }
- var duration = options.duration
- var offset = options.offset
- var pageUrl = location.hash
- ? stripHash(location.href)
- : location.href
- delegatedLinkHijacking()
- function delegatedLinkHijacking () {
- document.body.addEventListener('click', onClick, false)
- function onClick (e) {
- if (
- !isInPageLink(e.target) ||
- e.target.className.indexOf('no-smooth-scroll') > -1 ||
- (e.target.href.charAt(e.target.href.length - 2) === '#' &&
- e.target.href.charAt(e.target.href.length - 1) === '!') ||
- e.target.className.indexOf(options.linkClass) === -1) {
- return
- }
- // Don't prevent default or hash doesn't change.
- // e.preventDefault()
- jump(e.target.hash, {
- duration,
- offset,
- callback: function () {
- setFocus(e.target.hash)
- }
- })
- }
- }
- function isInPageLink (n) {
- return n.tagName.toLowerCase() === 'a' &&
- (n.hash.length > 0 || n.href.charAt(n.href.length - 1) === '#') &&
- (stripHash(n.href) === pageUrl || stripHash(n.href) + '#' === pageUrl)
- }
- function stripHash (url) {
- return url.slice(0, url.lastIndexOf('#'))
- }
- // function isCssSmoothSCrollSupported () {
- // return 'scrollBehavior' in document.documentElement.style
- // }
- // Adapted from:
- // https://www.nczonline.net/blog/2013/01/15/fixing-skip-to-content-links/
- function setFocus (hash) {
- var element = document.getElementById(hash.substring(1))
- if (element) {
- if (!/^(?:a|select|input|button|textarea)$/i.test(element.tagName)) {
- element.tabIndex = -1
- }
- element.focus()
- }
- }
- }
- function jump (target, options) {
- var start = window.pageYOffset
- var opt = {
- duration: options.duration,
- offset: options.offset || 0,
- callback: options.callback,
- easing: options.easing || easeInOutQuad
- }
- // This makes ids that start with a number work: ('[id="' + decodeURI(target).split('#').join('') + '"]')
- // DecodeURI for nonASCII hashes, they was encoded, but id was not encoded, it lead to not finding the tgt element by id.
- // And this is for IE: document.body.scrollTop
- // Handle decoded and non-decoded URIs since sometimes URLs automatically transform them (support for internation chars).
- var tgt = document.querySelector('[id="' + decodeURI(target).split('#').join('') + '"]') ||
- document.querySelector('[id="' + (target).split('#').join('') + '"]')
- var distance = typeof target === 'string'
- ? opt.offset + (
- target
- ? (tgt && tgt.getBoundingClientRect().top) || 0 // handle non-existent links better.
- : -(document.documentElement.scrollTop || document.body.scrollTop))
- : target
- var duration = typeof opt.duration === 'function'
- ? opt.duration(distance)
- : opt.duration
- var timeStart
- var timeElapsed
- requestAnimationFrame(function (time) { timeStart = time; loop(time) })
- function loop (time) {
- timeElapsed = time - timeStart
- window.scrollTo(0, opt.easing(timeElapsed, start, distance, duration))
- if (timeElapsed < duration) { requestAnimationFrame(loop) } else { end() }
- }
- function end () {
- window.scrollTo(0, start + distance)
- if (typeof opt.callback === 'function') { opt.callback() }
- }
- // Robert Penner's easeInOutQuad - http://robertpenner.com/easing/
- function easeInOutQuad (t, b, c, d) {
- t /= d / 2
- if (t < 1) return c / 2 * t * t + b
- t--
- return -c / 2 * (t * (t - 2) - 1) + b
- }
- }
- /***/ }),
- /***/ "./src/js/update-toc-scroll.js":
- /*!*************************************!*\
- !*** ./src/js/update-toc-scroll.js ***!
- \*************************************/
- /***/ ((module) => {
- /* eslint no-var: off */
- const SCROLL_LEEWAY = 30
- module.exports = function updateTocScroll (options) {
- var toc = options.tocElement || document.querySelector(options.tocSelector)
- if (toc && toc.scrollHeight > toc.clientHeight) {
- var activeItem = toc.querySelector('.' + options.activeListItemClass)
- if (activeItem) {
- // Determine container top and bottom
- var cTop = toc.scrollTop
- var cBottom = cTop + toc.clientHeight
- // Determine element top and bottom
- var eTop = activeItem.offsetTop
- var eBottom = eTop + activeItem.clientHeight
- // Check if out of view
- // Above scroll view
- if (eTop < cTop + options.tocScrollOffset) {
- toc.scrollTop -= (cTop - eTop) + options.tocScrollOffset
- // Below scroll view
- } else if (eBottom > cBottom - options.tocScrollOffset - SCROLL_LEEWAY) {
- toc.scrollTop += (eBottom - cBottom) + options.tocScrollOffset + (2 * SCROLL_LEEWAY)
- }
- }
- }
- }
- /***/ })
- /******/ });
- /************************************************************************/
- /******/ // The module cache
- /******/ var __webpack_module_cache__ = {};
- /******/
- /******/ // The require function
- /******/ function __webpack_require__(moduleId) {
- /******/ // Check if module is in cache
- /******/ var cachedModule = __webpack_module_cache__[moduleId];
- /******/ if (cachedModule !== undefined) {
- /******/ return cachedModule.exports;
- /******/ }
- /******/ // Create a new module (and put it into the cache)
- /******/ var module = __webpack_module_cache__[moduleId] = {
- /******/ // no module.id needed
- /******/ // no module.loaded needed
- /******/ exports: {}
- /******/ };
- /******/
- /******/ // Execute the module function
- /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
- /******/
- /******/ // Return the exports of the module
- /******/ return module.exports;
- /******/ }
- /******/
- /************************************************************************/
- /******/ /* webpack/runtime/global */
- /******/ (() => {
- /******/ __webpack_require__.g = (function() {
- /******/ if (typeof globalThis === 'object') return globalThis;
- /******/ try {
- /******/ return this || new Function('return this')();
- /******/ } catch (e) {
- /******/ if (typeof window === 'object') return window;
- /******/ }
- /******/ })();
- /******/ })();
- /******/
- /************************************************************************/
- /******/
- /******/ // startup
- /******/ // Load entry module and return exports
- /******/ // This entry module used 'module' so it can't be inlined
- /******/ var __webpack_exports__ = __webpack_require__("./src/js/index.js");
- /******/
- /******/ })()
- ;
- //# sourceMappingURL=main.js.map
|