diff --git a/index.html b/index.html index 063d3ba..7fd136c 100644 --- a/index.html +++ b/index.html @@ -196,9 +196,6 @@

- + diff --git a/modules/changeTitle.mjs b/modules/changeTitle.mjs index 6897652..6127015 100644 --- a/modules/changeTitle.mjs +++ b/modules/changeTitle.mjs @@ -1,5 +1,12 @@ +//@ts-check + /** - * Changes the document's title + * Changes the document's title. Instead of passing the main title, you can also + * change the functions `title` member: + * ```js + * changeTitle.title = "My Site" + * changeTitle("Home") // produces "Home | My Site" + * ``` * @param {string} title * @param {string} mainTitle * @returns diff --git a/modules/fetchMarkdown.mjs b/modules/fetchMarkdown.mjs index 131bebf..0dafc0e 100644 --- a/modules/fetchMarkdown.mjs +++ b/modules/fetchMarkdown.mjs @@ -22,3 +22,5 @@ export const fetchMarkdown = (path) => : path.replace(/\.\w{2, 4}$/, ""); return { title, raw, content }; }); + +export default fetchMarkdown; diff --git a/modules/index.mjs b/modules/index.mjs index 6dd8f3e..b87da6c 100644 --- a/modules/index.mjs +++ b/modules/index.mjs @@ -1,7 +1,20 @@ +//@ts-check + +import { changeTitle } from "./changeTitle.mjs"; +import { documentMode } from "./documentMode.mjs"; +import { fetchMarkdown } from "./fetchMarkdown.mjs"; import { fetchText } from "./fetchText.mjs"; import { generateDomFromString } from "./generateDomFromString.mjs"; +import { getCurrentHashUrl } from "./getCurrentHashUrl.mjs"; +import { getElementById } from "./getElementById.mjs"; import { isExternalUrl } from "./isExternalUrl.mjs"; import { isLocalHost } from "./isLocalHost.mjs"; +import { isNotNull } from "./isNotNull.mjs"; +import { + onDocumentKeyUp, + onDocumentKeyDown, + onDocumentKey, +} from "./onDocumentKey.mjs"; import { parseFileList } from "./parseFileList.mjs"; import { querySelectorDoc, @@ -9,7 +22,30 @@ import { querySelectorAll, } from "./querySelectorAll.mjs"; import { rewriteLocalUrls } from "./rewriteLocalUrls.mjs"; +import * as templateBlog from "./templateBlogUtils.mjs"; import { wait } from "./wait.mjs"; import { waitIfLocalHost } from "./waitIfLocalHost.mjs"; -export { isExternalUrl, isLocalHost, rewriteLocalUrls, wait, waitIfLocalHost }; +export { + changeTitle, + documentMode, + fetchMarkdown, + fetchText, + generateDomFromString, + getCurrentHashUrl, + getElementById, + isExternalUrl, + isLocalHost, + isNotNull, + onDocumentKeyUp, + onDocumentKeyDown, + onDocumentKey, + parseFileList, + querySelectorDoc, + querySelectorParent, + querySelectorAll, + rewriteLocalUrls, + templateBlog, + wait, + waitIfLocalHost, +}; diff --git a/modules/onDocumentKey.mjs b/modules/onDocumentKey.mjs index 951dd56..43f8d9b 100644 --- a/modules/onDocumentKey.mjs +++ b/modules/onDocumentKey.mjs @@ -1,3 +1,5 @@ +//@ts-check + /** * * @param {string} keyToListen @@ -9,3 +11,33 @@ export const onDocumentKeyUp = (keyToListen, callback) => { ({ key }) => key === keyToListen && callback() ); }; + +/** + * + * @param {string} keyToListen + * @param {()=>void} callback + */ +export const onDocumentKeyDown = (keyToListen, callback) => { + document.addEventListener( + "keydown", + ({ key }) => key === keyToListen && callback() + ); +}; + +/** + * + * @param {string} keyToListen + * @param {(down:boolean)=>void} callback + */ +export const onDocumentKey = (keyToListen, callback) => { + document.addEventListener( + "keyup", + ({ key }) => key === keyToListen && callback(false) + ); + document.addEventListener( + "keydown", + ({ key }) => key === keyToListen && callback(true) + ); +}; + +export default onDocumentKey; diff --git a/modules/templateBlog.mjs b/modules/templateBlog.mjs index 2dbef40..ecfb49d 100644 --- a/modules/templateBlog.mjs +++ b/modules/templateBlog.mjs @@ -1,107 +1,4 @@ //@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(); -}; - -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 }) => `${title}`) - .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; +import blog from "./templateBlogUtils.mjs"; +blog(); diff --git a/modules/templateBlogUtils.mjs b/modules/templateBlogUtils.mjs new file mode 100644 index 0000000..b527f4a --- /dev/null +++ b/modules/templateBlogUtils.mjs @@ -0,0 +1,107 @@ +//@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 }) => `${title}`) + .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;