added a few loading utilities
This commit is contained in:
		@@ -6,10 +6,6 @@
 | 
			
		||||
    <link href="../../modules/templates/blog.css" rel="stylesheet" />
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
    <section>
 | 
			
		||||
      <button class="burger">≡</button>
 | 
			
		||||
      <nav class="menu"></nav>
 | 
			
		||||
    </section>
 | 
			
		||||
    <main></main>
 | 
			
		||||
    <pre id="Source"></pre>
 | 
			
		||||
    <div id="Loading">
 | 
			
		||||
 
 | 
			
		||||
@@ -9,21 +9,16 @@ import { mode } from "../tickle/mode.mjs";
 | 
			
		||||
import { bootstrapRouter } from "../tickle/bootstrapRouter.mjs";
 | 
			
		||||
 | 
			
		||||
export const bootstrap = async () => {
 | 
			
		||||
  const [Menu, Body, Source, Burger] = [
 | 
			
		||||
    "nav",
 | 
			
		||||
  const [Body, Source] = [
 | 
			
		||||
    "main",
 | 
			
		||||
    "#Source",
 | 
			
		||||
    ".burger",
 | 
			
		||||
  ].map(getElementByCSSSelector);
 | 
			
		||||
 | 
			
		||||
  Burger.addEventListener("click", mode.menuOpen.toggle);
 | 
			
		||||
 | 
			
		||||
  mode.loading.on();
 | 
			
		||||
  const lines = await fetchText("files.txt");
 | 
			
		||||
  const links = parseFileList(lines);
 | 
			
		||||
  const firstHref = links[0].href;
 | 
			
		||||
  sortFileListLines(links);
 | 
			
		||||
  Menu.appendChild(createMenuEntriesFromFileList(links));
 | 
			
		||||
  Body.appendChild(createMenuEntriesFromFileList(links));
 | 
			
		||||
  
 | 
			
		||||
  bootstrapRouter(firstHref, (content, raw) => {
 | 
			
		||||
    Body.innerHTML = "";
 | 
			
		||||
 
 | 
			
		||||
@@ -10,8 +10,8 @@ import { mode } from "./mode.mjs";
 | 
			
		||||
/**
 | 
			
		||||
 * Sets up a listener for hashchange events.
 | 
			
		||||
 * Loads the provided default Href if none is set by the user
 | 
			
		||||
 * @param {string} defaultHref 
 | 
			
		||||
 * @param {(content: DocumentFragment, raw: string) => void} onPageLoaded 
 | 
			
		||||
 * @param {string} defaultHref
 | 
			
		||||
 * @param {(content: DocumentFragment, raw: string) => void} onPageLoaded
 | 
			
		||||
 */
 | 
			
		||||
export const bootstrapRouter = async (defaultHref, onPageLoaded) => {
 | 
			
		||||
  /**
 | 
			
		||||
@@ -27,15 +27,19 @@ export const bootstrapRouter = async (defaultHref, onPageLoaded) => {
 | 
			
		||||
    const { title, raw, content } = await fetchMarkdown(path);
 | 
			
		||||
    changeTitle(title);
 | 
			
		||||
    rewriteLocalUrls(content);
 | 
			
		||||
    onPageLoaded(content, raw)
 | 
			
		||||
    onPageLoaded(content, raw);
 | 
			
		||||
    mode.loading.off();
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  window.addEventListener("hashchange", onHashChange);
 | 
			
		||||
 | 
			
		||||
  if (hasNoHashUrl()) {
 | 
			
		||||
    window.location.hash = `#${defaultHref}`;
 | 
			
		||||
  } else {
 | 
			
		||||
    onHashChange();
 | 
			
		||||
  }
 | 
			
		||||
  const load = () => {
 | 
			
		||||
    if (hasNoHashUrl()) {
 | 
			
		||||
      window.location.hash = `#${defaultHref}`;
 | 
			
		||||
    } else {
 | 
			
		||||
      onHashChange();
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return load
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -2,12 +2,7 @@
 | 
			
		||||
 | 
			
		||||
import { fetchText } from "./fetchText.mjs";
 | 
			
		||||
import { waitIfLocalHost } from "./waitIfLocalHost.mjs";
 | 
			
		||||
import { generateDomFromString } from "./generateDomFromString.mjs";
 | 
			
		||||
import {getFirstTitleContent} from "./getFirstTitleContent.mjs";
 | 
			
		||||
// @ts-ignore
 | 
			
		||||
import { micromark } from "https://esm.sh/micromark@3?bundle";
 | 
			
		||||
// @ts-ignore
 | 
			
		||||
import {frontmatter, frontmatterHtml} from 'https://esm.sh/micromark-extension-frontmatter@1?bundle'
 | 
			
		||||
import { markupToDom } from "./markupToDom.mjs"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Loads and parses a markdown document. Makes use of micromark.
 | 
			
		||||
@@ -16,14 +11,6 @@ import {frontmatter, frontmatterHtml} from 'https://esm.sh/micromark-extension-f
 | 
			
		||||
export const fetchMarkdown = (path) =>
 | 
			
		||||
  fetchText(path)
 | 
			
		||||
    .then(waitIfLocalHost())
 | 
			
		||||
    .then((raw) => {
 | 
			
		||||
      const output = micromark(raw, {
 | 
			
		||||
        extensions: [frontmatter()],
 | 
			
		||||
        htmlExtensions: [frontmatterHtml()]
 | 
			
		||||
      })
 | 
			
		||||
      const content = generateDomFromString(output);
 | 
			
		||||
      const title = getFirstTitleContent(content) || path.replace(/\.\w{2, 4}$/, "");
 | 
			
		||||
      return { title, raw, content };
 | 
			
		||||
    });
 | 
			
		||||
    .then(raw => markupToDom(raw, path));
 | 
			
		||||
 | 
			
		||||
export default fetchMarkdown;
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,9 @@ import { html } from "./html.mjs";
 | 
			
		||||
import { isExternalUrl } from "./isExternalUrl.mjs";
 | 
			
		||||
import { isLocalHost } from "./isLocalHost.mjs";
 | 
			
		||||
import { isNotNull } from "./isNotNull.mjs";
 | 
			
		||||
import { markdownToMarkup } from "./markdownToMarkup.mjs";
 | 
			
		||||
import { markupToDom } from "./markupToDom.mjs";
 | 
			
		||||
import { memoize } from "./memoize.mjs";
 | 
			
		||||
import { not } from "./not.mjs";
 | 
			
		||||
import {
 | 
			
		||||
  onDocumentKeyUp,
 | 
			
		||||
@@ -56,6 +59,9 @@ export {
 | 
			
		||||
  isExternalUrl,
 | 
			
		||||
  isLocalHost,
 | 
			
		||||
  isNotNull,
 | 
			
		||||
  markdownToMarkup,
 | 
			
		||||
  markupToDom,
 | 
			
		||||
  memoize,
 | 
			
		||||
  not,
 | 
			
		||||
  onDocumentKeyUp,
 | 
			
		||||
  onDocumentKeyDown,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								modules/utils/markdownToMarkup.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								modules/utils/markdownToMarkup.mjs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
//@ts-check
 | 
			
		||||
 | 
			
		||||
//@ts-ignore
 | 
			
		||||
import { micromark } from "https://esm.sh/micromark@3?bundle";
 | 
			
		||||
//@ts-ignore
 | 
			
		||||
import {frontmatter, frontmatterHtml} from 'https://esm.sh/micromark-extension-frontmatter@1?bundle'
 | 
			
		||||
//@ts-ignore
 | 
			
		||||
import Yaml from 'https://esm.sh/yaml@2?bundle'
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Transforms a markup string into a valid markup.
 | 
			
		||||
 * If there's a YAML frontmatter, will parse it too
 | 
			
		||||
 * @param {string} markdownStr 
 | 
			
		||||
 * @returns 
 | 
			
		||||
 */
 | 
			
		||||
export const markdownToMarkup = (markdownStr) => {
 | 
			
		||||
  /** @type {string} */
 | 
			
		||||
  const markup = micromark(markdownStr, {
 | 
			
		||||
    extensions: [frontmatter()],
 | 
			
		||||
    htmlExtensions: [frontmatterHtml()]
 | 
			
		||||
  })
 | 
			
		||||
  const header = Yaml.parseAllDocuments(markdownStr)[0]
 | 
			
		||||
  /** @type {Record<string, unknown>} */
 | 
			
		||||
  const frontMatter = header ? header.toJS() : {}
 | 
			
		||||
  return { markup, frontMatter }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default markdownToMarkup
 | 
			
		||||
							
								
								
									
										20
									
								
								modules/utils/markupToDom.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								modules/utils/markupToDom.mjs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
//@ts-check
 | 
			
		||||
import { generateDomFromString } from "./generateDomFromString.mjs";
 | 
			
		||||
import { getFirstTitleContent } from "./getFirstTitleContent.mjs";
 | 
			
		||||
import { markdownToMarkup } from './markdownToMarkup.mjs';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Takes a markdown string and transforms it into dom that can be slotted in a
 | 
			
		||||
 * document.
 | 
			
		||||
 * Additionally, it parses the frontmatter, and attempts to extract a title
 | 
			
		||||
 * by finding either the first title in the doc, or the filename (if provided).
 | 
			
		||||
 * @param {string} markdownStr 
 | 
			
		||||
 * @param {string} [path] the file path
 | 
			
		||||
 */
 | 
			
		||||
export const markupToDom = (markdownStr, path = '') => {
 | 
			
		||||
  const { frontMatter, markup } = markdownToMarkup(markdownStr);
 | 
			
		||||
  const content = generateDomFromString(markup);
 | 
			
		||||
  const title = getFirstTitleContent(content) || path.replace(/\.\w{2, 4}$/, "");
 | 
			
		||||
  return { title, raw: markdownStr, content, frontMatter };
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										30
									
								
								modules/utils/memoize.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								modules/utils/memoize.mjs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
			
		||||
//@ts-check
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Caches the result of a function.
 | 
			
		||||
 * The cache is available as `.cache` in case there's a need to clear anything.
 | 
			
		||||
 * @template {(...args: any[]) => any} T
 | 
			
		||||
 * @param {T} functionToMemoize 
 | 
			
		||||
 * @returns 
 | 
			
		||||
 */
 | 
			
		||||
export const memoize = (functionToMemoize) => {
 | 
			
		||||
  /** @type {Map<Parameters<T>[0], ReturnType<T>>} */
 | 
			
		||||
  const cache = new Map()
 | 
			
		||||
  /**
 | 
			
		||||
   * 
 | 
			
		||||
   * @param  {Parameters<T>} args 
 | 
			
		||||
   * @returns {ReturnType<T>}
 | 
			
		||||
   */
 | 
			
		||||
  const memoized = (...args) => {
 | 
			
		||||
    const key = args[0]
 | 
			
		||||
    if(!cache.has(key)){
 | 
			
		||||
      cache.set(key, functionToMemoize(...args))
 | 
			
		||||
    }
 | 
			
		||||
    //@ts-ignore
 | 
			
		||||
    return cache.get(key)
 | 
			
		||||
  }
 | 
			
		||||
  memoized.map = cache
 | 
			
		||||
  return memoized
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default memoize
 | 
			
		||||
		Reference in New Issue
	
	Block a user