diff --git a/examples/musings/index.html b/examples/musings/index.html
index d93719e..43c2079 100644
--- a/examples/musings/index.html
+++ b/examples/musings/index.html
@@ -6,10 +6,6 @@
-
diff --git a/modules/templates/blog.mjs b/modules/templates/blog.mjs
index 75c5b87..ecac531 100644
--- a/modules/templates/blog.mjs
+++ b/modules/templates/blog.mjs
@@ -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 = "";
diff --git a/modules/tickle/bootstrapRouter.mjs b/modules/tickle/bootstrapRouter.mjs
index 2ec9d72..6dbbc68 100644
--- a/modules/tickle/bootstrapRouter.mjs
+++ b/modules/tickle/bootstrapRouter.mjs
@@ -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
};
diff --git a/modules/utils/fetchMarkdown.mjs b/modules/utils/fetchMarkdown.mjs
index 0405aac..0f4275c 100644
--- a/modules/utils/fetchMarkdown.mjs
+++ b/modules/utils/fetchMarkdown.mjs
@@ -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;
diff --git a/modules/utils/index.mjs b/modules/utils/index.mjs
index d7d9346..47a8d5f 100644
--- a/modules/utils/index.mjs
+++ b/modules/utils/index.mjs
@@ -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,
diff --git a/modules/utils/markdownToMarkup.mjs b/modules/utils/markdownToMarkup.mjs
new file mode 100644
index 0000000..41c8b09
--- /dev/null
+++ b/modules/utils/markdownToMarkup.mjs
@@ -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
} */
+ const frontMatter = header ? header.toJS() : {}
+ return { markup, frontMatter }
+}
+
+export default markdownToMarkup
\ No newline at end of file
diff --git a/modules/utils/markupToDom.mjs b/modules/utils/markupToDom.mjs
new file mode 100644
index 0000000..c206bcb
--- /dev/null
+++ b/modules/utils/markupToDom.mjs
@@ -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 };
+};
diff --git a/modules/utils/memoize.mjs b/modules/utils/memoize.mjs
new file mode 100644
index 0000000..2fc84ce
--- /dev/null
+++ b/modules/utils/memoize.mjs
@@ -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[0], ReturnType>} */
+ const cache = new Map()
+ /**
+ *
+ * @param {Parameters} args
+ * @returns {ReturnType}
+ */
+ 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
\ No newline at end of file