testing moving the functionality into small modules #5
@@ -196,9 +196,6 @@
 | 
			
		||||
    <div id="Loading">
 | 
			
		||||
      <p>❤</p>
 | 
			
		||||
    </div>
 | 
			
		||||
    <script type="module">
 | 
			
		||||
      import blog from "./modules/templateBlog.mjs";
 | 
			
		||||
      blog();
 | 
			
		||||
    </script>
 | 
			
		||||
    <script type="module" src="./modules/templateBlog.mjs"></script>
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -22,3 +22,5 @@ export const fetchMarkdown = (path) =>
 | 
			
		||||
        : path.replace(/\.\w{2, 4}$/, "");
 | 
			
		||||
      return { title, raw, content };
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
export default fetchMarkdown;
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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 }) => `<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;
 | 
			
		||||
import blog from "./templateBlogUtils.mjs";
 | 
			
		||||
blog();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										107
									
								
								modules/templateBlogUtils.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								modules/templateBlogUtils.mjs
									
									
									
									
									
										Normal file
									
								
							@@ -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 }) => `<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;
 | 
			
		||||
		Reference in New Issue
	
	Block a user