tickle/modules/templateBlogUtils.mjs

108 lines
2.9 KiB
JavaScript

//@ts-check
import { changeTitle } from "./changeTitle.mjs";
import { getCurrentHashUrl } from "./getCurrentHashUrl.mjs";
import { fetchMarkdown } from "./fetchMarkdown.mjs";
import { fetchText } from "./fetchText.mjs";
import { parseFileList } from "./parseFileList.mjs";
import { documentMode } from "./documentMode.mjs";
import { getElementById } from "./getElementById.mjs";
import { onDocumentKeyUp } from "./onDocumentKey.mjs";
/*****************************************************************
*
* Creating references to the important stuff
*
****************************************************************/
/**
* The elements we will need
*/
const [Menu, Body, Source, Burger] = ["Menu", "Body", "Source", "Burger"].map(
getElementById
);
const loadingMode = documentMode("loading");
const sourceEnableMode = documentMode("source-enabled");
const menuOpenMode = documentMode("menu-open");
/*****************************************************************
*
* Router
*
* Things related to main navigation and to loading pages
*
****************************************************************/
/**
* Listens to hashchange event, and attempts to read the url.
* @param {HashChangeEvent} [_evt]
*/
export const onHashChange = async (_evt) => {
const { path, params } = getCurrentHashUrl();
if (!path) {
return false;
}
loadingMode.on();
const { title, raw, content } = await fetchMarkdown(path);
changeTitle(title);
Body.innerHTML = "";
Source.innerHTML = raw;
Body.appendChild(content);
loadingMode.off();
};
export const loadFileList = () => {
loadingMode.on();
fetchText("./files.txt").then(fillMenuFromFileList);
};
/**
* Called when the file list is obtained (presumably through loading)
* parses the file list, then fills the side navigation
* If there's no page loaded, it also loads the first page in the list
* (the list gets sorted by date, but the first line is the one that gets used)
* @param {string} lines
*/
export const fillMenuFromFileList = (lines) => {
const links = parseFileList(lines).sort(
({ date_unix: a }, { date_unix: b }) => a - b
);
if (links.length < 1) {
return;
}
Menu.innerHTML = links
.map(({ href, title }) => `<a data-link href="#${href}">${title}</a>`)
.join(`\n`);
if (!getCurrentHashUrl().path) {
// @ts-ignore
const href = links.find(({ index }) => index === 0).href;
window.location.hash = `#${href}`;
} else {
onHashChange();
}
};
/*****************************************************************
*
* Bootstrapping
*
* this is where things actually happen
*
****************************************************************/
/**
* Loads the article list, parses it, creates the menu items
*/
export const bootstrap = () => {
Burger.addEventListener("click", menuOpenMode.toggle);
window.addEventListener("hashchange", onHashChange);
loadFileList();
onDocumentKeyUp("?", sourceEnableMode.toggle);
};
export default bootstrap;