{"version":3,"sources":["gumshoe-5.1.2-patched.js","main.js"],"names":["root","factory","define","amd","exports","module","Gumshoe","global","window","this","emitEvent","type","elem","detail","settings","events","event","CustomEvent","bubbles","cancelable","dispatchEvent","getOffsetTop","location","offsetParent","offsetTop","sortContents","contents","sort","item1","item2","content","isInView","bottom","bounds","getBoundingClientRect","offset","parseFloat","parseInt","innerHeight","document","documentElement","clientHeight","top","isAtBottom","Math","ceil","pageYOffset","max","body","scrollHeight","offsetHeight","getActive","item","last","length","i","deactivate","items","li","nav","closest","classList","remove","navClass","contentClass","deactivateNested","link","defaults","nested","nestedClass","reflow","parentNode","activateNested","add","selector","options","navItems","current","timeout","publicAPIs","setup","querySelectorAll","Array","prototype","forEach","call","getElementById","decodeURIComponent","hash","substr","push","detect","active","scrollHandler","cancelAnimationFrame","requestAnimationFrame","resizeHandler","destroy","removeEventListener","merged","arguments","obj","key","hasOwnProperty","extend","addEventListener","tocScroll","header","scrollHandlerForHeader","floor","scrollHandlerForTOC","positionY","scrollTo","querySelector","setupScrollHandler","last_known_scroll_position","ticking","e","scrollY","scroll","setupScrollSpy","recursive","main"],"mappings":"CAQA,SAAAA,EAAAC,GACA,mBAAAC,QAAAA,OAAAC,IACAD,OAAA,GAAA,WACA,OAAAD,EAAAD,KAEA,iBAAAI,QACAC,OAAAD,QAAAH,EAAAD,GAEAA,EAAAM,QAAAL,EAAAD,GARA,CAWA,oBAAAO,OACAA,OACA,oBAAAC,OACAA,OACAC,KACA,SAAAD,gBAkDA,SAAAE,EAAAC,EAAAC,EAAAC,GAEAA,EAAAC,SAAAC,SAGAC,EAAA,IAAAC,YAAAN,EAAA,CACAO,SAAA,EACAC,YAAA,EACAN,OAAAA,IAIAD,EAAAQ,cAAAJ,IAQA,SAAAK,EAAAT,GACA,IAAAU,EAAA,EACA,GAAAV,EAAAW,aACA,KAAAX,GACAU,GAAAV,EAAAY,UACAZ,EAAAA,EAAAW,aAGA,OAAA,GAAAD,EAAAA,EAAA,EAOA,SAAAG,EAAAC,GACAA,GACAA,EAAAC,KAAA,SAAAC,EAAAC,GAGA,OAFAR,EAAAO,EAAAE,SACAT,EAAAQ,EAAAC,UACA,EACA,IA2CA,SAAAC,EAAAnB,EAAAE,EAAAkB,GAGA,OAFAC,EAAArB,EAAAsB,wBACAC,EAjCA,mBAFArB,EAmCAA,GAjCAqB,OACAC,WAAAtB,EAAAqB,UAIAC,WAAAtB,EAAAqB,QA6BAH,EAEAK,SAAAJ,EAAAD,OAAA,KACAxB,EAAA8B,aAAAC,SAAAC,gBAAAC,cAGAJ,SAAAJ,EAAAS,IAAA,KAAAP,EAOA,SAAAQ,IACA,OACAC,KAAAC,KAAArC,EAAA8B,YAAA9B,EAAAsC,cAnCAF,KAAAG,IACAR,SAAAS,KAAAC,aACAV,SAAAC,gBAAAS,aACAV,SAAAS,KAAAE,aACAX,SAAAC,gBAAAU,aACAX,SAAAS,KAAAP,aACAF,SAAAC,gBAAAC,cAqDA,SAAAU,EAAAzB,EAAAZ,GACA,IAZAsC,EAAAtC,EAYAuC,EAAA3B,EAAAA,EAAA4B,OAAA,GACA,GAbAF,EAaAC,EAbAvC,EAaAA,KAZA6B,MAAAZ,EAAAqB,EAAAtB,QAAAhB,GAAA,IAYA,OAAAuC,EACA,IAAA,IAAAE,EAAA7B,EAAA4B,OAAA,EAAA,GAAAC,EAAAA,IACA,GAAAxB,EAAAL,EAAA6B,GAAAzB,QAAAhB,GAAA,OAAAY,EAAA6B,GA6BA,SAAAC,EAAAC,EAAA3C,GAEA,IAGA4C,GAHAD,IAGAC,EAAAD,EAAAE,IAAAC,QAAA,SAIAF,EAAAG,UAAAC,OAAAhD,EAAAiD,UACAN,EAAA3B,QAAA+B,UAAAC,OAAAhD,EAAAkD,cAGAC,EAAAP,EAAA5C,GAGAJ,EAAA,oBAAAgD,EAAA,CACAQ,KAAAT,EAAAE,IACA7B,QAAA2B,EAAA3B,QACAhB,SAAAA,KA7NA,IAAAqD,EAAA,CAEAJ,SAAA,SACAC,aAAA,SAGAI,QAAA,EACAC,YAAA,SAGAlC,OAAA,EACAmC,QAAA,EAGAvD,QAAA,GAwKAkD,EAAA,SAAAN,EAAA7C,GAEAA,EAAAsD,QAAAT,EAAAY,cAGAb,EAAAC,EAAAY,WAAAX,QAAA,SAIAF,EAAAG,UAAAC,OAAAhD,EAAAuD,aAGAJ,EAAAP,EAAA5C,MAoCA0D,EAAA,SAAAb,EAAA7C,IAEAA,EAAAsD,SAGAV,EAAAC,EAAAY,WAAAX,QAAA,SAIAF,EAAAG,UAAAY,IAAA3D,EAAAuD,aAGAG,EAAAd,EAAA5C,KA8LA,OA1JA,SAAA4D,EAAAC,GAKA,IACAC,EAAAlD,EAAAmD,EAAAC,EAAAhE,EADAiE,EAAA,CAUAC,MAAA,WAEAJ,EAAArC,SAAA0C,iBAAAP,GAGAhD,EAAA,GAGAwD,MAAAC,UAAAC,QAAAC,KAAAT,EAAA,SAAAxB,GAEA,IAAAtB,EAAAS,SAAA+C,eACAC,mBAAAnC,EAAAoC,KAAAC,OAAA,KAEA3D,GAGAJ,EAAAgE,KAAA,CACA/B,IAAAP,EACAtB,QAAAA,MAKAL,EAAAC,KAMAqD,EAAAY,OAAA,WAEA,IA1EAlC,EAAA3C,EAKA4C,EAqEAkC,EAAAzC,EAAAzB,EAAAZ,GAGA8E,EASAf,GAAAe,EAAA9D,UAAA+C,EAAA/C,UAGA0B,EAAAqB,EAAA/D,GAzFAA,EA0FAA,IA1FA2C,EA0FAmC,KArFAlC,EAAAD,EAAAE,IAAAC,QAAA,SAIAF,EAAAG,UAAAY,IAAA3D,EAAAiD,UACAN,EAAA3B,QAAA+B,UAAAY,IAAA3D,EAAAkD,cAGAQ,EAAAd,EAAA5C,GAGAJ,EAAA,kBAAAgD,EAAA,CACAQ,KAAAT,EAAAE,IACA7B,QAAA2B,EAAA3B,QACAhB,SAAAA,KA0EA+D,EAAAe,GAfAf,IACArB,EAAAqB,EAAA/D,GACA+D,EAAA,OAoBA,SAAAgB,EAAA7E,GAEA8D,GACAtE,EAAAsF,qBAAAhB,GAIAA,EAAAtE,EAAAuF,sBAAAhB,EAAAY,QAOA,SAAAK,EAAAhF,GAEA8D,GACAtE,EAAAsF,qBAAAhB,GAIAA,EAAAtE,EAAAuF,sBAAA,WACAtE,EAAAC,GACAqD,EAAAY,WAOAZ,EAAAkB,QAAA,WAEApB,GACArB,EAAAqB,EAAA/D,GAIAN,EAAA0F,oBAAA,SAAAL,GAAA,GACA/E,EAAAwD,QACA9D,EAAA0F,oBAAA,SAAAF,GAAA,GAQAlF,EADAgE,EADAD,EADAD,EADAlD,EAAA,MAgCA,OApBAZ,EA3XA,WACA,IAAAqF,EAAA,GAOA,OANAjB,MAAAC,UAAAC,QAAAC,KAAAe,UAAA,SAAAC,GACA,IAAA,IAAAC,KAAAD,EAAA,CACA,IAAAA,EAAAE,eAAAD,GAAA,OACAH,EAAAG,GAAAD,EAAAC,MAGAH,EAmXAK,CAAArC,EAAAQ,GAAA,IAGAI,EAAAC,QAGAD,EAAAY,SAGAnF,EAAAiG,iBAAA,SAAAZ,GAAA,GACA/E,EAAAwD,QACA9D,EAAAiG,iBAAA,SAAAT,GAAA,GASAjB,KCrcA,IAAA2B,UAAA,KACAC,OAAA,KAEA,SAAAC,yBACA,GAAAhE,KAAAiE,MAAAF,OAAAzE,wBAAAQ,KACAiE,OAAA9C,UAAAY,IAAA,YAEAkC,OAAA9C,UAAAC,OAAA,YAIA,SAAAgD,oBAAAC,GACA,OAAAL,YAKA,GAAAK,EACAL,UAAAM,SAAA,EAAA,GAGApE,KAAAC,KAAAkE,IACAnE,KAAAiE,MAAAtE,SAAAC,gBAAAS,aAAAzC,OAAA8B,aAEAoE,UAAAM,SAAA,EAAAN,UAAAzD,cAGAV,SAAA0E,cAAA,oBAgBA,SAAApB,cAAAkB,GACAH,yBACAE,oBAAAC,GAMA,SAAAG,qBAEA,IAAAC,EACAC,GAAA,EAEA5G,OAAAiG,iBAAA,SAAA,SAAAY,GACAF,EAAA3G,OAAA8G,QAEAF,IACA5G,OAAAuF,sBAAA,WACAF,cAAAsB,GACAC,GAAA,IAGAA,GAAA,KAGA5G,OAAA+G,SAGA,SAAAC,iBACA,OAAAd,WAKA,IAAApG,QAAA,cAAA,CACAgE,QAAA,EACAmD,WAAA,EACA1D,SAAA,mBAIA,SAAAiB,QACAkC,qBACAM,iBAGA,SAAAE,OACAnF,SAAAS,KAAAuB,WAAAV,UAAAC,OAAA,SAEA6C,OAAApE,SAAA0E,cAAA,UACAP,UAAAnE,SAAA0E,cAAA,eAEAjC,QAGAzC,SAAAkE,iBAAA,mBAAAiB","file":"main.js","sourcesContent":["/*!\n * gumshoejs v5.1.2 (patched by @pradyunsg)\n * A simple, framework-agnostic scrollspy script.\n * (c) 2019 Chris Ferdinandi\n * MIT License\n * http://github.com/cferdinandi/gumshoe\n */\n\n(function (root, factory) {\n if (typeof define === \"function\" && define.amd) {\n define([], function () {\n return factory(root);\n });\n } else if (typeof exports === \"object\") {\n module.exports = factory(root);\n } else {\n root.Gumshoe = factory(root);\n }\n})(\n typeof global !== \"undefined\"\n ? global\n : typeof window !== \"undefined\"\n ? window\n : this,\n function (window) {\n \"use strict\";\n\n //\n // Defaults\n //\n\n var defaults = {\n // Active classes\n navClass: \"active\",\n contentClass: \"active\",\n\n // Nested navigation\n nested: false,\n nestedClass: \"active\",\n\n // Offset & reflow\n offset: 0,\n reflow: false,\n\n // Event support\n events: true,\n };\n\n //\n // Methods\n //\n\n /**\n * Merge two or more objects together.\n * @param {Object} objects The objects to merge together\n * @returns {Object} Merged values of defaults and options\n */\n var extend = function () {\n var merged = {};\n Array.prototype.forEach.call(arguments, function (obj) {\n for (var key in obj) {\n if (!obj.hasOwnProperty(key)) return;\n merged[key] = obj[key];\n }\n });\n return merged;\n };\n\n /**\n * Emit a custom event\n * @param {String} type The event type\n * @param {Node} elem The element to attach the event to\n * @param {Object} detail Any details to pass along with the event\n */\n var emitEvent = function (type, elem, detail) {\n // Make sure events are enabled\n if (!detail.settings.events) return;\n\n // Create a new event\n var event = new CustomEvent(type, {\n bubbles: true,\n cancelable: true,\n detail: detail,\n });\n\n // Dispatch the event\n elem.dispatchEvent(event);\n };\n\n /**\n * Get an element's distance from the top of the Document.\n * @param {Node} elem The element\n * @return {Number} Distance from the top in pixels\n */\n var getOffsetTop = function (elem) {\n var location = 0;\n if (elem.offsetParent) {\n while (elem) {\n location += elem.offsetTop;\n elem = elem.offsetParent;\n }\n }\n return location >= 0 ? location : 0;\n };\n\n /**\n * Sort content from first to last in the DOM\n * @param {Array} contents The content areas\n */\n var sortContents = function (contents) {\n if (contents) {\n contents.sort(function (item1, item2) {\n var offset1 = getOffsetTop(item1.content);\n var offset2 = getOffsetTop(item2.content);\n if (offset1 < offset2) return -1;\n return 1;\n });\n }\n };\n\n /**\n * Get the offset to use for calculating position\n * @param {Object} settings The settings for this instantiation\n * @return {Float} The number of pixels to offset the calculations\n */\n var getOffset = function (settings) {\n // if the offset is a function run it\n if (typeof settings.offset === \"function\") {\n return parseFloat(settings.offset());\n }\n\n // Otherwise, return it as-is\n return parseFloat(settings.offset);\n };\n\n /**\n * Get the document element's height\n * @private\n * @returns {Number}\n */\n var getDocumentHeight = function () {\n return Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight,\n document.body.offsetHeight,\n document.documentElement.offsetHeight,\n document.body.clientHeight,\n document.documentElement.clientHeight\n );\n };\n\n /**\n * Determine if an element is in view\n * @param {Node} elem The element\n * @param {Object} settings The settings for this instantiation\n * @param {Boolean} bottom If true, check if element is above bottom of viewport instead\n * @return {Boolean} Returns true if element is in the viewport\n */\n var isInView = function (elem, settings, bottom) {\n var bounds = elem.getBoundingClientRect();\n var offset = getOffset(settings);\n if (bottom) {\n return (\n parseInt(bounds.bottom, 10) <\n (window.innerHeight || document.documentElement.clientHeight)\n );\n }\n return parseInt(bounds.top, 10) <= offset;\n };\n\n /**\n * Check if at the bottom of the viewport\n * @return {Boolean} If true, page is at the bottom of the viewport\n */\n var isAtBottom = function () {\n if (\n Math.ceil(window.innerHeight + window.pageYOffset) >=\n getDocumentHeight()\n )\n return true;\n return false;\n };\n\n /**\n * Check if the last item should be used (even if not at the top of the page)\n * @param {Object} item The last item\n * @param {Object} settings The settings for this instantiation\n * @return {Boolean} If true, use the last item\n */\n var useLastItem = function (item, settings) {\n if (isAtBottom() && isInView(item.content, settings, true)) return true;\n return false;\n };\n\n /**\n * Get the active content\n * @param {Array} contents The content areas\n * @param {Object} settings The settings for this instantiation\n * @return {Object} The content area and matching navigation link\n */\n var getActive = function (contents, settings) {\n var last = contents[contents.length - 1];\n if (useLastItem(last, settings)) return last;\n for (var i = contents.length - 1; i >= 0; i--) {\n if (isInView(contents[i].content, settings)) return contents[i];\n }\n };\n\n /**\n * Deactivate parent navs in a nested navigation\n * @param {Node} nav The starting navigation element\n * @param {Object} settings The settings for this instantiation\n */\n var deactivateNested = function (nav, settings) {\n // If nesting isn't activated, bail\n if (!settings.nested || !nav.parentNode) return;\n\n // Get the parent navigation\n var li = nav.parentNode.closest(\"li\");\n if (!li) return;\n\n // Remove the active class\n li.classList.remove(settings.nestedClass);\n\n // Apply recursively to any parent navigation elements\n deactivateNested(li, settings);\n };\n\n /**\n * Deactivate a nav and content area\n * @param {Object} items The nav item and content to deactivate\n * @param {Object} settings The settings for this instantiation\n */\n var deactivate = function (items, settings) {\n // Make sure there are items to deactivate\n if (!items) return;\n\n // Get the parent list item\n var li = items.nav.closest(\"li\");\n if (!li) return;\n\n // Remove the active class from the nav and content\n li.classList.remove(settings.navClass);\n items.content.classList.remove(settings.contentClass);\n\n // Deactivate any parent navs in a nested navigation\n deactivateNested(li, settings);\n\n // Emit a custom event\n emitEvent(\"gumshoeDeactivate\", li, {\n link: items.nav,\n content: items.content,\n settings: settings,\n });\n };\n\n /**\n * Activate parent navs in a nested navigation\n * @param {Node} nav The starting navigation element\n * @param {Object} settings The settings for this instantiation\n */\n var activateNested = function (nav, settings) {\n // If nesting isn't activated, bail\n if (!settings.nested) return;\n\n // Get the parent navigation\n var li = nav.parentNode.closest(\"li\");\n if (!li) return;\n\n // Add the active class\n li.classList.add(settings.nestedClass);\n\n // Apply recursively to any parent navigation elements\n activateNested(li, settings);\n };\n\n /**\n * Activate a nav and content area\n * @param {Object} items The nav item and content to activate\n * @param {Object} settings The settings for this instantiation\n */\n var activate = function (items, settings) {\n // Make sure there are items to activate\n if (!items) return;\n\n // Get the parent list item\n var li = items.nav.closest(\"li\");\n if (!li) return;\n\n // Add the active class to the nav and content\n li.classList.add(settings.navClass);\n items.content.classList.add(settings.contentClass);\n\n // Activate any parent navs in a nested navigation\n activateNested(li, settings);\n\n // Emit a custom event\n emitEvent(\"gumshoeActivate\", li, {\n link: items.nav,\n content: items.content,\n settings: settings,\n });\n };\n\n /**\n * Create the Constructor object\n * @param {String} selector The selector to use for navigation items\n * @param {Object} options User options and settings\n */\n var Constructor = function (selector, options) {\n //\n // Variables\n //\n\n var publicAPIs = {};\n var navItems, contents, current, timeout, settings;\n\n //\n // Methods\n //\n\n /**\n * Set variables from DOM elements\n */\n publicAPIs.setup = function () {\n // Get all nav items\n navItems = document.querySelectorAll(selector);\n\n // Create contents array\n contents = [];\n\n // Loop through each item, get it's matching content, and push to the array\n Array.prototype.forEach.call(navItems, function (item) {\n // Get the content for the nav item\n var content = document.getElementById(\n decodeURIComponent(item.hash.substr(1))\n );\n if (!content) return;\n\n // Push to the contents array\n contents.push({\n nav: item,\n content: content,\n });\n });\n\n // Sort contents by the order they appear in the DOM\n sortContents(contents);\n };\n\n /**\n * Detect which content is currently active\n */\n publicAPIs.detect = function () {\n // Get the active content\n var active = getActive(contents, settings);\n\n // if there's no active content, deactivate and bail\n if (!active) {\n if (current) {\n deactivate(current, settings);\n current = null;\n }\n return;\n }\n\n // If the active content is the one currently active, do nothing\n if (current && active.content === current.content) return;\n\n // Deactivate the current content and activate the new content\n deactivate(current, settings);\n activate(active, settings);\n\n // Update the currently active content\n current = active;\n };\n\n /**\n * Detect the active content on scroll\n * Debounced for performance\n */\n var scrollHandler = function (event) {\n // If there's a timer, cancel it\n if (timeout) {\n window.cancelAnimationFrame(timeout);\n }\n\n // Setup debounce callback\n timeout = window.requestAnimationFrame(publicAPIs.detect);\n };\n\n /**\n * Update content sorting on resize\n * Debounced for performance\n */\n var resizeHandler = function (event) {\n // If there's a timer, cancel it\n if (timeout) {\n window.cancelAnimationFrame(timeout);\n }\n\n // Setup debounce callback\n timeout = window.requestAnimationFrame(function () {\n sortContents(contents);\n publicAPIs.detect();\n });\n };\n\n /**\n * Destroy the current instantiation\n */\n publicAPIs.destroy = function () {\n // Undo DOM changes\n if (current) {\n deactivate(current, settings);\n }\n\n // Remove event listeners\n window.removeEventListener(\"scroll\", scrollHandler, false);\n if (settings.reflow) {\n window.removeEventListener(\"resize\", resizeHandler, false);\n }\n\n // Reset variables\n contents = null;\n navItems = null;\n current = null;\n timeout = null;\n settings = null;\n };\n\n /**\n * Initialize the current instantiation\n */\n var init = function () {\n // Merge user options into defaults\n settings = extend(defaults, options || {});\n\n // Setup variables based on the current DOM\n publicAPIs.setup();\n\n // Find the currently active content\n publicAPIs.detect();\n\n // Setup event listeners\n window.addEventListener(\"scroll\", scrollHandler, false);\n if (settings.reflow) {\n window.addEventListener(\"resize\", resizeHandler, false);\n }\n };\n\n //\n // Initialize and return the public APIs\n //\n\n init();\n return publicAPIs;\n };\n\n //\n // Return the Constructor\n //\n\n return Constructor;\n }\n);\n","////////////////////////////////////////////////////////////////////////////////\n// Scroll Handling\n////////////////////////////////////////////////////////////////////////////////\nvar tocScroll = null;\nvar header = null;\n\nfunction scrollHandlerForHeader() {\n if (Math.floor(header.getBoundingClientRect().top) == 0) {\n header.classList.add(\"scrolled\");\n } else {\n header.classList.remove(\"scrolled\");\n }\n}\n\nfunction scrollHandlerForTOC(positionY) {\n if (tocScroll === null) {\n return;\n }\n\n // top of page.\n if (positionY == 0) {\n tocScroll.scrollTo(0, 0);\n } else if (\n // bottom of page.\n Math.ceil(positionY) >=\n Math.floor(document.documentElement.scrollHeight - window.innerHeight)\n ) {\n tocScroll.scrollTo(0, tocScroll.scrollHeight);\n } else {\n // somewhere in the middle.\n const current = document.querySelector(\".scroll-current\");\n if (current == null) {\n return;\n }\n\n // https://github.com/pypa/pip/issues/9159 This breaks scroll behaviours.\n // // scroll the currently \"active\" heading in toc, into view.\n // const rect = current.getBoundingClientRect();\n // if (0 > rect.top) {\n // current.scrollIntoView(true); // the argument is \"alignTop\"\n // } else if (rect.bottom > window.innerHeight) {\n // current.scrollIntoView(false);\n // }\n }\n}\n\nfunction scrollHandler(positionY) {\n scrollHandlerForHeader();\n scrollHandlerForTOC(positionY);\n}\n\n////////////////////////////////////////////////////////////////////////////////\n// Setup\n////////////////////////////////////////////////////////////////////////////////\nfunction setupScrollHandler() {\n // Taken from https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event\n var last_known_scroll_position = 0;\n var ticking = false;\n\n window.addEventListener(\"scroll\", function (e) {\n last_known_scroll_position = window.scrollY;\n\n if (!ticking) {\n window.requestAnimationFrame(function () {\n scrollHandler(last_known_scroll_position);\n ticking = false;\n });\n\n ticking = true;\n }\n });\n window.scroll();\n}\n\nfunction setupScrollSpy() {\n if (tocScroll === null) {\n return;\n }\n\n // Scrollspy -- highlight table on contents, based on scroll\n var spy = new Gumshoe(\".toc-tree a\", {\n reflow: true,\n recursive: true,\n navClass: \"scroll-current\",\n });\n}\n\nfunction setup() {\n setupScrollHandler();\n setupScrollSpy();\n}\n\nfunction main() {\n document.body.parentNode.classList.remove(\"no-js\");\n\n header = document.querySelector(\"header\");\n tocScroll = document.querySelector(\".toc-scroll\");\n\n setup();\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", main);\n"]}