<!DOCTYPE html>
<html>
  <head>
    <title>Tickle</title>
    <meta charset="UTF-8" />
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=Lobster&family=Nunito+Sans:ital,wght@0,400;0,700;1,400&display=swap"
      rel="stylesheet"
    />
    <style>
      :root {
        --accent: hotpink;
        --background: #fdfdfd;
        font-family: "Nunito Sans", sans-serif;
      }
      body,
      html {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
      }
      .trigger {
        display: none;
      }
      .left-nav > * {
        position: fixed;
        top: 0;
        left: 0;
      }
      .left-nav > .menu {
        padding: 1em;
        transform: translateX(-100%);
        display: flex;
        flex-direction: column;
        top: 0;
        bottom: 0;
        transition: all 0.3s ease-out;
        gap: 1em;
      }
      .left-nav > .menu a {
        text-decoration: none;
        background: var(--background);
        color: var(--accent);
        box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
        padding: 0.2em 0.4em;
      }
      .left-nav > .menu a:hover {
        background: var(--accent);
        color: var(--background);
      }
      .left-nav > .trigger:checked ~ .menu {
        transform: translateX(0);
        transition-duration: 0.1s;
      }
      .burger {
        width: 2em;
        height: 2em;
        display: flex;
        justify-content: center;
        align-content: center;
        text-align: center;
        vertical-align: middle;
        line-height: 2em;
        border-radius: 0.2em;
        box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
        transition: background 0.5s ease;
      }
      .left-nav > .trigger:checked ~ .burger {
        color: transparent;
      }

      .left-nav > .trigger:checked ~ .burger,
      #Loading {
        top: 0;
        right: 0;
        width: 100%;
        height: 100%;
        border-radius: 0;
        background: rgba(17, 17, 17, 0.2);
      }
      #Loading {
        position: absolute;
        text-align: center;
        align-items: center;
        justify-content: center;
        font-size: 8rem;
        color: var(--accent);
        opacity: 0;
        transition: opacity 0.3s ease-in, height 0s linear 0.3s;
        height: 0;
        display: flex;
        overflow: hidden;
      }
      .is-loading #Loading {
        opacity: 1;
        height: 100%;
        transition: opacity 1s ease-in, height 0 linear;
      }
      #Loading::after {
        content: "❤";
        animation: beat 1.2s infinite cubic-bezier(0.215, 0.61, 0.355, 1);
      }
      @keyframes beat {
        0% {
          transform: scale(0.95);
        }
        5% {
          transform: scale(1.1);
        }
        39% {
          transform: scale(0.85);
        }
        45% {
          transform: scale(1);
        }
        60% {
          transform: scale(0.95);
        }
        100% {
          transform: scale(0.9);
        }
      }
      #Body {
        padding: 3em;
        max-width: 52em;
        margin: 0 auto;
      }
      #Body h1,
      #Body h2,
      #Body h3,
      #Body h4 {
        color: var(--accent);
        font-family: "Lobster", serif;
      }
      #Body a {
        color: var(--background);
        background-color: var(--accent);
        text-decoration: none;
        padding: 0.1em 0.4em;
      }
    </style>
  </head>
  <body>
    <nav class="left-nav">
      <input id="main-nav" type="checkbox" class="trigger" />
      <label for="main-nav" class="burger">&#8801;</label>
      <div id="Menu" class="menu"></div>
    </nav>
    <header id="Menu"></header>
    <main id="Body"></main>
    <div id="Loading"></div>
    <script type="module">
      /**
       * markdown parser. Remove if you don't use markdown
       */
      // @ts-ignore
      import { micromark } from "https://esm.sh/micromark@3?bundle";

      /**
       * useful to check for transitions while developing styles, if the loading screen disappears too fast
       *
       */
      const wait = (val) => new Promise((ok) => setTimeout(ok, 1, val));

      /**
       * The elements we will need
       */
      const [Menu, Body, Loading] = ["Menu", "Body", "Loading"].map((id) =>
        document.getElementById(id)
      );

      /**
       * cache the original title to append it to the page title
       */
      const mainTitle = document.title;

      const startLoading = () => document.body.classList.add("is-loading");
      const stopLoading = () => document.body.classList.remove("is-loading");

      const getCurrentPage = () =>
        window.location.hash[1] === "/" ? window.location.hash.slice(2) : "";

      const onHashChange = (evt) => {
        const path = getCurrentPage();
        if (!path) {
          return false;
        }
        startLoading();
        return fetch(`./${path}`)
          .then((response) => response.text())
          .then(wait)
          .then((text) => {
            const [, title] = text.match(/^(#\s\w+)/) ||
              text.match(/(.*?)\n===+/m) || [, path];
            document.title = `${title} | ${mainTitle}`;
            Body.innerHTML = micromark(text);
            stopLoading();
          });
      };

      window.addEventListener("hashchange", onHashChange);

      /**
       * Loads the article list, parses it, creates the menu items
       */
      const start = () => {
        startLoading();
        fetch("./files.txt")
          .then((response) => response.text())
          .then((lines) => {
            Menu.innerHTML = lines
              .split(`\n`)
              .map((line, index) => {
                const today = new Date().toISOString().split("T")[0];
                const result = line.match(
                  /(?<name>.+)\.(?<ext>\w{2,3})(?:\s(?<date>[\d-]+)?(?<title>.+))?/
                );
                if (!result) {
                  console.log(`could not parse line ${index}: [${line}]`);
                  return null;
                }
                const {
                  groups: { name, ext, date = today, title = name },
                } = result;
                const href = `/${name}.${ext}`;
                if (!getCurrentPage()) {
                  window.location.hash = `#${href}`;
                }
                return { name, href, date, title };
              })
              .filter(Boolean)
              .sort(({ date: a }, { date: b }) => a - b)
              .map(
                ({ href, title }) => `<a data-link href="#${href}">${title}</a>`
              )
              .join(`\n`);

            onHashChange();
          });
      };

      start();
    </script>
  </body>
</html>