/** * Build the filetree * @param {HTMLElement} parent Root element of the filetree * @param {{name: string, is_dir: boolean, children: any[]}} data FileNode * @param {string} location Current location, used for links creation */ const buildFileTree = (parent, data, location) => { const ul = document.createElement("ul"); data.forEach((item) => { const li = document.createElement("li"); li.classList.add(item.is_dir ? "directory" : "file"); if (item.is_dir) { // Directory li.textContent = item.name; li.classList.add("collapsed"); // Toggle collapsing on click li.addEventListener("click", function (e) { if (e.target === li) { li.classList.toggle("collapsed"); } }); } else { // File const url = window.location.href.split("?")[0]; const a = document.createElement("a"); a.text = item.name; a.href = `${url}?q=${location}${item.name}`; li.appendChild(a); } ul.appendChild(li); if (item.children && item.children.length > 0) { buildFileTree( li, item.children, item.is_dir ? location + `${item.name}/` : location ); } }); parent.appendChild(ul); }; /** * Uncollapse elements from the deepest element * @param {HTMLLIElement} element Element to uncollapse */ const uncollapse = (element) => { if (element) { element.classList.remove("collapsed"); uncollapse(element.parentElement.closest("li")); } }; /** * Find the deepest opened directory * @param {string[]} path Current path we are looking at, init with fullpath * @param {NodeListOf} options Options we have, init with list root * @returns */ const deepestNodeOpened = (path, options) => { // Iterate over possible options for (let i = 0; i < options.length; ++i) { // If the directory and the current path match if (decodeURI(path[0]) === options[i].firstChild.nodeValue) { if (path.length === 1) { // We found it return options[i]; } // Continue the search return deepestNodeOpened( path.slice(1), options[i].querySelector("ul").childNodes ); } } }; window.addEventListener("load", () => { // Build the filetree const fileTreeElement = document.getElementsByTagName("aside")[0]; const dataElement = fileTreeElement.getElementsByTagName("span")[0]; buildFileTree( fileTreeElement, JSON.parse(dataElement.getAttribute("data-json")).children, "" ); dataElement.remove(); // Open nested openeded directories const infoURL = window.location.href.split("?"); if (infoURL.length > 1) { const fullpath = infoURL[1].substring(2); const path = fullpath.substring(0, fullpath.lastIndexOf("/")); const last_openeded = deepestNodeOpened( path.split("/"), fileTreeElement.querySelector("ul").childNodes ); uncollapse(last_openeded); } });