import "../css/normalize.css"; import "milligram/dist/milligram.min.css"; import "../css/common.css"; import "../css/nav.css"; import "../css/overrides.css"; /** * Converts the given string to an HTML element. * * @param string the string to convert to an HTML element * @param query the type of element to return * @returns {HTMLElement} the HTML element described by the given string */ const stringToHtml = function (string, query) { return new DOMParser().parseFromString(string, "text/html").body.querySelector(query); } /** * Alias for `document.querySelector`. * * @param q {string} the query string * @returns {HTMLElement} the element identified by the query string */ export const $ = q => document.querySelector(q); /** * Runs the given function once the page is loaded. * * This function can be used multiple times. It does not overwrite existing callbacks for the page load event. * * @param fun {function(...*): *} the function to run */ export const doAfterLoad = function (fun) { const oldOnLoad = window.onload || (() => { }); window.onload = (() => { oldOnLoad(); fun(); }); }; /** * Creates a navigation element for navigating through the website. * * Fetches entries asynchronously from the website's API. * * @param [highlightPath] {String} the path to highlight together with its parents * @returns {HTMLElement} a base navigation element that will eventually be filled with contents */ export const nav = function (highlightPath = "") { const base = stringToHtml( `
`, "ul" ); fetch("https://fwdekker.com/api/nav/") .then(it => it.json()) .then(json => { json.entries.forEach(entry => base.appendChild(stringToHtml(unpackEntry(entry, "/", highlightPath), "li"))) }) .catch(e => { console.error("Failed to fetch navigation elements", e); return []; }); const nav = stringToHtml(``, "nav"); nav.appendChild(base); return nav; }; /** * Unpacks a navigation entry returned from the navigation API into an HTML element. * * @param entry {Object} the entry to unpack * @param [path] {number} the current path traversed, found by joining the names of the entries with `/`s; always starts * and ends with a `/` * @param [highlightPath] {String} the path to highlight together with its parents * @returns {string} the navigation list entry as HTML, described by its children */ const unpackEntry = function (entry, path = "/", highlightPath = "") { const shouldHighlight = highlightPath.startsWith(`${path + entry.name}/`); const isExternalLink = !entry.link.startsWith("https://fwdekker.com/") && entry.link !== "#"; const formattedName = (isExternalLink ? "⎋ " : "") + entry.name; if (entry.entries.length === 0) return `${description}
` : "") + `