From fe29beb57f737a8ebc954a26cc7b58347bbbeb5f Mon Sep 17 00:00:00 2001 From: SPT-dev Date: Thu, 2 Mar 2023 21:10:38 -0500 Subject: [PATCH] Updated Docs class code and JSDocs --- docs/assets/js/docs.js | 91 ++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 35 deletions(-) diff --git a/docs/assets/js/docs.js b/docs/assets/js/docs.js index a3c957f..130c866 100644 --- a/docs/assets/js/docs.js +++ b/docs/assets/js/docs.js @@ -1,10 +1,4 @@ -/** - * TODO: override the marker.js renderer for urls - * to enable proper anchor support. - * - * Probably just need to check if the text starts - * with a # or not to cover most cases. - */ +// TODO: Override the marker.js renderer for urls to enable proper anchor support. class Docs { /** @@ -33,26 +27,30 @@ class Docs { this.onExec(); } + /** + * Called on instanciation by the constructor. + */ async onExec() { - // Get routes. this.routesData = await this.fetchRoutes(); - // Generate nav based on routes. - this.generateNav(this.routesData, document.querySelector('aside')); + this.updateRoutes(this.routesData); + + this.generateNav(this.routes, document.querySelector('aside')); - // Add listener for hash change. window.addEventListener('hashchange', () => this.handleLocation(window.location)); - + // Check for initial condition. if (window.location.hash) { + // There is a hash in the address bar, load the view. this.handleLocation(window.location); } else if (typeof this.defaultViewPath !== 'undefined') { - // TODO: Do it. + // TODO: Load a default view. console.log('Missing Feature !\nShould load the default view'); } } /** + * Fetch the json file containing the routes. * @returns {Array.} The array containing the routes. */ async fetchRoutes() { @@ -63,22 +61,43 @@ class Docs { } /** - * @param {Array.} routes - * @param {HTMLElement} target + * Update the routes. + * @param {Array.} routesData */ - generateNav(routesData, target) { - /** @type {Array.} */ + updateRoutes(routesData) { const routes = []; - const nav = document.createElement('nav'); routesData.forEach(routeData => { if ('routes' in routeData) { - routes.push(new RoutingNode(routeData['name'], routeData['hidden'], routeData['routes'])); + const node = new RoutingNode( + routeData['name'], + routeData['hidden'], + routeData['routes'] + ); + + routes.push(node); } else { - routes.push(new Route(routeData['name'], routeData['hidden'], routeData['filepath'])); + const route = new Route( + routeData['name'], + routeData['hidden'], + routeData['filepath'] + ); + + routes.push(route); } }); + this.routes = routes; + } + + /** + * Generate the side nav HTML based on routing data. + * @param {Array.} routes + * @param {HTMLElement} target + */ + generateNav(routes, target) { + const nav = document.createElement('nav'); + routes.forEach(routingItem => { if (routingItem['hidden'] === false || typeof routingItem['hidden'] === 'undefined') { const el = routingItem.buildSelf(); @@ -86,35 +105,33 @@ class Docs { if (typeof el !== 'undefined') { nav.appendChild(el); } - } else { - console.log(`skipped ${routingItem.name}`); } }); target.appendChild(nav); - - this.routes = routes; } /** + * Handle if the view needs to be changed or to move to in-page anchor + * base on the location data. * @param {Location} location */ handleLocation(location) { - let hashes = location.hash.split('#'); - + const hashes = location.hash.split('#'); hashes.splice(0, 1); - console.log(hashes); - if (typeof this.currentRoute === 'undefined' || this.currentRoute.filepath !== hashes[0]) { + // TODO: add check in case of no matching routes. const route = this.findMatchingRoute(hashes[0], this.routes); - // Scroll back to top. + this.currentRoute = route; + + // Scroll back to top of the content outlet. document.querySelector('#router-outlet').scrollTop = 0; - this.currentRoute = route; this.displayRoute(route); + // Changing classes based on the new active route. const activeLinks = document.querySelectorAll('a.active'); const newActiveLinks = document.querySelectorAll(`a[href='#${hashes[0]}']`); @@ -124,12 +141,11 @@ class Docs { newActiveLinks.forEach(newLink => newLink.classList.add('active')); - // TODO: update active route in the page's navbar - if (hashes.length > 1) { this.handleLocation(window.location); } } else { + // Page don't need to be changed, just move to anchor. const el = document.querySelector(`#${hashes[1]}`); el.scrollIntoView({ @@ -140,16 +156,16 @@ class Docs { } /** + * Recursively search for a matching route based on a filepath. * @param {string} filepath The filepath to search. * @returns {Route} The matching route. */ findMatchingRoute(filepath, routes) { - console.log('filepath:', filepath); - + // TODO: Break the loops in a more elegant way. let match = undefined; for (let routingItem of routes) { - // If the routingItem is a route and have what we are looking for. + // If the routingItem is a Route and have what we are looking for. if (routingItem.hasOwnProperty('filepath') && routingItem['filepath'] === filepath) { match = routingItem; break; @@ -172,6 +188,7 @@ class Docs { } /** + * Load and displays a route's content. * @param {Route} route The route to load. */ async displayRoute(route) { @@ -183,6 +200,10 @@ class Docs { Prism.highlightAll(); // edited } + /** + * Utilitary function to remove any content inside an HTML element + * @param {HTMLElement} element + */ removeChildren(element) { let count = element.childNodes.length;