From f1f7b48b223fe53d2a4a72903421d157b112a31e Mon Sep 17 00:00:00 2001
From: thepaperpilot <thepaperpilot@gmail.com>
Date: Mon, 28 Feb 2022 21:30:17 -0600
Subject: [PATCH] Added logo to homepage

---
 .vitepress/theme/Layout.vue            |  36 +++++
 .vitepress/theme/Profectus.vue         | 195 +++++++++++++++++++++++++
 .vitepress/theme/home/HomeFeatures.vue | 143 ++++++++++++++++++
 .vitepress/theme/home/HomeFooter.vue   |  50 +++++++
 .vitepress/theme/home/HomeHero.vue     | 161 ++++++++++++++++++++
 .vitepress/theme/home/NavLink.vue      | 100 +++++++++++++
 .vitepress/theme/index.js              |  10 +-
 7 files changed, 691 insertions(+), 4 deletions(-)
 create mode 100644 .vitepress/theme/Layout.vue
 create mode 100644 .vitepress/theme/Profectus.vue
 create mode 100644 .vitepress/theme/home/HomeFeatures.vue
 create mode 100644 .vitepress/theme/home/HomeFooter.vue
 create mode 100644 .vitepress/theme/home/HomeHero.vue
 create mode 100644 .vitepress/theme/home/NavLink.vue

diff --git a/.vitepress/theme/Layout.vue b/.vitepress/theme/Layout.vue
new file mode 100644
index 00000000..6c83ff18
--- /dev/null
+++ b/.vitepress/theme/Layout.vue
@@ -0,0 +1,36 @@
+<template>
+  <Layout>
+    <template #home>
+      <main class="home" aria-labelledby="main-title">
+        <Profectus style="height: 30vmin; margin: auto; display: block" />
+        <HomeHero />
+        <HomeFeatures />
+        <div class="home-content">
+          <Content />
+        </div>
+        <HomeFooter />
+      </main>
+    </template>
+  </Layout>
+</template>
+
+<script setup>
+import DefaultTheme from 'vitepress/theme';
+import Profectus from './Profectus.vue';
+// I want Profectus above the hero text, so I effectively need to recreate the Home class now
+import HomeHero from './home/HomeHero.vue';
+import HomeFeatures from './home/HomeFeatures.vue';
+import HomeFooter from './home/HomeFooter.vue';
+const { Layout } = DefaultTheme;
+</script>
+
+<style scoped>
+.home {
+  padding-top: var(--header-height);
+}
+.home-content {
+  max-width: 960px;
+  margin: 0px auto;
+  padding: 0 1.5rem;
+}
+</style>
diff --git a/.vitepress/theme/Profectus.vue b/.vitepress/theme/Profectus.vue
new file mode 100644
index 00000000..3a7700bd
--- /dev/null
+++ b/.vitepress/theme/Profectus.vue
@@ -0,0 +1,195 @@
+<template>
+    <transition appear>
+        <svg
+            id="eaRe02fYmMp1"
+            xmlns="http://www.w3.org/2000/svg"
+            xmlns:xlink="http://www.w3.org/1999/xlink"
+            viewBox="0 0 228 521"
+            shape-rendering="geometricPrecision"
+            text-rendering="geometricPrecision"
+        >
+            <g id="P">
+                <path
+                    d="m 101,512.877 c -17.547386,-5.3519 -50.794681,-10.26296 -80,0 10.737201,-217.43031 5.7244,-300.999 0,-464.9995 0,0 46.6144,-37.1164 80,-42.00002 33.386,-4.883633 86.025,10.45942 120,50.00002 5,30 -4.353,106.6565 -44,156.0005 -34.149,42.5 -130,38.48 -130,92.999 0,102 54,208 54,208 z"
+                    style="
+                        display: inline;
+                        fill: none;
+                        stroke: rgb(163, 190, 140);
+                        stroke-width: 10;
+                        stroke-linecap: round;
+                        stroke-miterlimit: 16;
+                    "
+                    id="trunk"
+                    class="svg-elem-1"
+                ></path>
+                <path
+                    d="M 221,55.8775 C 209.023,126.453 185.39,166.835 158.997,191.5 93.783098,252.444 11.718998,217.436 46.999998,304.877"
+                    style="
+                        display: inline;
+                        fill: none;
+                        stroke: rgb(163, 190, 140);
+                        stroke-width: 5;
+                        stroke-linecap: round;
+                        stroke-miterlimit: 16;
+                    "
+                    id="vine2"
+                    class="svg-elem-2"
+                ></path>
+                <path
+                    d="m 194.5,188 c -11.225,4.447 -19.066,5.134 -35.503,3.5"
+                    style="
+                        display: inline;
+                        fill: none;
+                        stroke: rgb(163, 190, 140);
+                        stroke-width: 5;
+                        stroke-linecap: round;
+                        stroke-miterlimit: 16;
+                    "
+                    id="short_vine4"
+                    class="svg-elem-3"
+                ></path>
+                <path
+                    d="M 73.499996,246.5 C 111.145,245.626 127.011,238.775 156.5,228"
+                    style="
+                        display: inline;
+                        fill: none;
+                        stroke: rgb(163, 190, 140);
+                        stroke-width: 5;
+                        stroke-linecap: round;
+                        stroke-miterlimit: 16;
+                    "
+                    id="short_vine3"
+                    class="svg-elem-4"
+                ></path>
+                <path
+                    d="M 221,55.8775 C 169.5,17.8262 86.0943,44.9468 47,107 c -4.743,7.528 -7.1041,15.373 -8.326,24 -3.5282,24.91 2.4426,56.34 -12.0011,105.5"
+                    style="
+                        display: inline;
+                        fill: none;
+                        stroke: rgb(163, 190, 140);
+                        stroke-width: 5;
+                        stroke-linecap: round;
+                        stroke-miterlimit: 16;
+                    "
+                    id="vine1"
+                    class="svg-elem-5"
+                ></path>
+                <path
+                    d="M 21,47.8775 38.674,131"
+                    style="
+                        display: inline;
+                        fill: none;
+                        stroke: rgb(163, 190, 140);
+                        stroke-width: 5;
+                        stroke-linecap: round;
+                        stroke-miterlimit: 16;
+                    "
+                    id="short_vine2"
+                    class="svg-elem-6"
+                ></path>
+                <path
+                    d="m 3,326.5 c 13.1783,22.208 16.4863,42.834 21.6997,81"
+                    style="
+                        display: inline;
+                        fill: none;
+                        stroke: rgb(163, 190, 140);
+                        stroke-width: 5;
+                        stroke-linecap: round;
+                        stroke-miterlimit: 16;
+                    "
+                    id="short_vine1"
+                    class="svg-elem-7"
+                ></path>
+            </g>
+        </svg>
+    </transition>
+</template>
+
+<style scoped>
+svg {
+    background: #2e3440;
+}
+
+/***************************************************
+ * Generated by SVG Artista on 1/7/2022, 4:39:47 PM
+ * MIT license (https://opensource.org/licenses/MIT)
+ * W. https://svgartista.net
+ **************************************************/
+
+svg .svg-elem-1 {
+    stroke-dashoffset: 2648.758056640625px;
+    stroke-dasharray: 1324.3790283203125px;
+    transition: stroke-dashoffset 1s cubic-bezier(0.47, 0, 0.745, 0.715) 0s;
+}
+
+svg.v-enter-from .svg-elem-1,
+svg.v-leave-to .svg-elem-1 {
+    stroke-dashoffset: 1324.3790283203125px;
+}
+
+svg .svg-elem-2 {
+    stroke-dashoffset: 680.4000854492188px;
+    stroke-dasharray: 340.2000427246094px;
+    transition: stroke-dashoffset 1s ease-out 0.4s;
+}
+
+svg.v-enter-from .svg-elem-2,
+svg.v-leave-to .svg-elem-2 {
+    stroke-dashoffset: 340.2000427246094px;
+}
+
+svg .svg-elem-3 {
+    stroke-dashoffset: 76.21031951904297px;
+    stroke-dasharray: 38.105159759521484px;
+    transition: stroke-dashoffset 1s ease-out 0.8s;
+}
+
+svg.v-enter-from .svg-elem-3,
+svg.v-leave-to .svg-elem-3 {
+    stroke-dashoffset: 38.105159759521484px;
+}
+
+svg .svg-elem-4 {
+    stroke-dashoffset: 175.18072509765625px;
+    stroke-dasharray: 87.59036254882812px;
+    transition: stroke-dashoffset 1s cubic-bezier(0.47, 0, 0.745, 0.715) 0.36s;
+}
+
+svg.v-enter-from .svg-elem-4,
+svg.v-leave-to .svg-elem-4 {
+    stroke-dashoffset: 87.59036254882812px;
+}
+
+svg .svg-elem-5 {
+    stroke-dashoffset: 671.9447021484375px;
+    stroke-dasharray: 335.97235107421875px;
+    transition: stroke-dashoffset 1s ease-out 0.8s;
+}
+
+svg.v-enter-from .svg-elem-5,
+svg.v-leave-to .svg-elem-5 {
+    stroke-dashoffset: 335.97235107421875px;
+}
+
+svg .svg-elem-6 {
+    stroke-dashoffset: 173.96141052246094px;
+    stroke-dasharray: 86.98070526123047px;
+    transition: stroke-dashoffset 1s ease-out 1s;
+}
+
+svg.v-enter-from .svg-elem-6,
+svg.v-leave-to .svg-elem-6 {
+    stroke-dashoffset: 86.98070526123047px;
+}
+
+svg .svg-elem-7 {
+    stroke-dashoffset: 172.99151611328125px;
+    stroke-dasharray: 86.49575805664062px;
+    transition: stroke-dashoffset 1s ease-out 0.85s;
+}
+
+svg.v-enter-from .svg-elem-7,
+svg.v-leave-to .svg-elem-7 {
+    stroke-dashoffset: 86.49575805664062px;
+}
+</style>
diff --git a/.vitepress/theme/home/HomeFeatures.vue b/.vitepress/theme/home/HomeFeatures.vue
new file mode 100644
index 00000000..d33b772f
--- /dev/null
+++ b/.vitepress/theme/home/HomeFeatures.vue
@@ -0,0 +1,143 @@
+<script setup lang="ts">
+import { computed } from 'vue'
+import { useData } from 'vitepress'
+
+const { frontmatter } = useData()
+
+const hasFeatures = computed(() => {
+  return frontmatter.value.features && frontmatter.value.features.length > 0
+})
+
+interface Feature {
+  title?: string
+  details?: string
+}
+
+const features = computed<Feature[]>(() => {
+  return frontmatter.value.features ? frontmatter.value.features : []
+})
+</script>
+
+<template>
+  <div v-if="hasFeatures" class="home-features">
+    <div class="wrapper">
+      <div class="container">
+        <div class="features">
+          <section
+            v-for="(feature, index) in features"
+            :key="index"
+            class="feature"
+          >
+            <h2 class="title" v-if="feature.title">{{ feature.title }}</h2>
+            <p class="details" v-if="feature.details">{{ feature.details }}</p>
+          </section>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style scoped>
+.home-features {
+  margin: 0 auto;
+  padding: 2.5rem 0 2.75rem;
+  max-width: 960px;
+}
+
+.home-hero + .home-features {
+  padding-top: 0;
+}
+
+@media (min-width: 420px) {
+  .home-features {
+    padding: 3.25rem 0 3.5rem;
+  }
+
+  .home-hero + .home-features {
+    padding-top: 0;
+  }
+}
+
+@media (min-width: 720px) {
+  .home-features {
+    padding-right: 1.5rem;
+    padding-left: 1.5rem;
+  }
+}
+
+.wrapper {
+  padding: 0 1.5rem;
+}
+
+.home-hero + .home-features .wrapper {
+  border-top: 1px solid var(--c-divider);
+  padding-top: 2.5rem;
+}
+
+@media (min-width: 420px) {
+  .home-hero + .home-features .wrapper {
+    padding-top: 3.25rem;
+  }
+}
+
+@media (min-width: 720px) {
+  .wrapper {
+    padding-right: 0;
+    padding-left: 0;
+  }
+}
+
+.container {
+  margin: 0 auto;
+  max-width: 392px;
+}
+
+@media (min-width: 720px) {
+  .container {
+    max-width: 960px;
+  }
+}
+
+.features {
+  display: flex;
+  flex-wrap: wrap;
+  margin: -20px -24px;
+}
+
+.feature {
+  flex-shrink: 0;
+  padding: 20px 24px;
+  width: 100%;
+}
+
+@media (min-width: 720px) {
+  .feature {
+    width: calc(100% / 3);
+  }
+}
+
+.title {
+  margin: 0;
+  border-bottom: 0;
+  line-height: 1.4;
+  font-size: 1.25rem;
+  font-weight: 500;
+}
+
+@media (min-width: 420px) {
+  .title {
+    font-size: 1.4rem;
+  }
+}
+
+.details {
+  margin: 0;
+  line-height: 1.6;
+  font-size: 1rem;
+  color: var(--c-text-light);
+}
+
+.title + .details {
+  padding-top: 0.25rem;
+}
+</style>
\ No newline at end of file
diff --git a/.vitepress/theme/home/HomeFooter.vue b/.vitepress/theme/home/HomeFooter.vue
new file mode 100644
index 00000000..8492e59a
--- /dev/null
+++ b/.vitepress/theme/home/HomeFooter.vue
@@ -0,0 +1,50 @@
+<script setup lang="ts">
+import { useData } from 'vitepress'
+
+const { frontmatter } = useData()
+</script>
+
+<template>
+  <footer v-if="frontmatter.footer" class="footer">
+    <div class="container">
+      <p class="text">{{ frontmatter.footer }}</p>
+    </div>
+  </footer>
+</template>
+
+<style scoped>
+.footer {
+  margin: 0 auto;
+  max-width: 960px;
+}
+
+@media (min-width: 720px) {
+  .footer {
+    padding: 0 1.5rem;
+  }
+}
+
+.container {
+  padding: 2rem 1.5rem 2.25rem;
+}
+
+.home-hero + .footer .container,
+.home-features + .footer .container,
+.home-content + .footer .container {
+  border-top: 1px solid var(--c-divider);
+}
+
+@media (min-width: 420px) {
+  .container {
+    padding: 3rem 1.5rem 3.25rem;
+  }
+}
+
+.text {
+  margin: 0;
+  text-align: center;
+  line-height: 1.4;
+  font-size: 0.9rem;
+  color: var(--c-text-light);
+}
+</style>
\ No newline at end of file
diff --git a/.vitepress/theme/home/HomeHero.vue b/.vitepress/theme/home/HomeHero.vue
new file mode 100644
index 00000000..b404165d
--- /dev/null
+++ b/.vitepress/theme/home/HomeHero.vue
@@ -0,0 +1,161 @@
+<script setup lang="ts">
+import { computed } from 'vue'
+import { useData, withBase } from 'vitepress'
+import NavLink from './NavLink.vue'
+
+const { site, frontmatter } = useData()
+
+const showHero = computed(() => {
+  const { heroImage, heroText, tagline, actionLink, actionText } =
+    frontmatter.value
+  return heroImage || heroText || tagline || (actionLink && actionText)
+})
+
+const heroText = computed(() => frontmatter.value.heroText || site.value.title)
+const tagline = computed(
+  () => frontmatter.value.tagline || site.value.description
+)
+</script>
+
+<template>
+  <header v-if="showHero" class="home-hero">
+    <figure v-if="frontmatter.heroImage" class="figure">
+      <img
+        class="image"
+        :src="withBase(frontmatter.heroImage)"
+        :alt="frontmatter.heroAlt"
+      />
+    </figure>
+
+    <h1 v-if="heroText" id="main-title" class="title">{{ heroText }}</h1>
+    <p v-if="tagline" class="tagline">{{ tagline }}</p>
+
+    <NavLink
+      v-if="frontmatter.actionLink && frontmatter.actionText"
+      :item="{ link: frontmatter.actionLink, text: frontmatter.actionText }"
+      class="action"
+    />
+
+    <NavLink
+      v-if="frontmatter.altActionLink && frontmatter.altActionText"
+      :item="{
+        link: frontmatter.altActionLink,
+        text: frontmatter.altActionText
+      }"
+      class="action alt"
+    />
+  </header>
+</template>
+
+<style scoped>
+.home-hero {
+  margin: 2.5rem 0 2.75rem;
+  padding: 0 1.5rem;
+  text-align: center;
+}
+
+@media (min-width: 420px) {
+  .home-hero {
+    margin: 3.5rem 0;
+  }
+}
+
+@media (min-width: 720px) {
+  .home-hero {
+    margin: 4rem 0 4.25rem;
+  }
+}
+
+.figure {
+  padding: 0 1.5rem;
+}
+
+.image {
+  display: block;
+  margin: 0 auto;
+  width: auto;
+  max-width: 100%;
+  max-height: 280px;
+}
+
+.title {
+  margin-top: 1.5rem;
+  font-size: 2rem;
+}
+
+@media (min-width: 420px) {
+  .title {
+    font-size: 3rem;
+  }
+}
+
+@media (min-width: 720px) {
+  .title {
+    margin-top: 2rem;
+  }
+}
+
+.tagline {
+  margin: 0;
+  margin-top: 0.25rem;
+  line-height: 1.3;
+  font-size: 1.2rem;
+  color: var(--c-text-light);
+}
+
+@media (min-width: 420px) {
+  .tagline {
+    line-height: 1.2;
+    font-size: 1.6rem;
+  }
+}
+
+.action {
+  margin-top: 1.5rem;
+  display: inline-block;
+}
+
+.action.alt {
+  margin-left: 1.5rem;
+}
+
+@media (min-width: 420px) {
+  .action {
+    margin-top: 2rem;
+    display: inline-block;
+  }
+}
+
+.action :deep(.item) {
+  display: inline-block;
+  border-radius: 6px;
+  padding: 0 20px;
+  line-height: 44px;
+  font-size: 1rem;
+  font-weight: 500;
+  color: var(--c-bg);
+  background-color: var(--c-brand);
+  border: 2px solid var(--c-brand);
+  transition: background-color 0.1s ease;
+}
+
+.action.alt :deep(.item) {
+  background-color: var(--c-bg);
+  color: var(--c-brand);
+}
+
+.action :deep(.item:hover) {
+  text-decoration: none;
+  color: var(--c-bg);
+  background-color: var(--c-brand-light);
+}
+
+@media (min-width: 420px) {
+  .action :deep(.item) {
+    padding: 0 24px;
+    line-height: 52px;
+    font-size: 1.2rem;
+    font-weight: 500;
+  }
+}
+</style>
\ No newline at end of file
diff --git a/.vitepress/theme/home/NavLink.vue b/.vitepress/theme/home/NavLink.vue
new file mode 100644
index 00000000..ff265974
--- /dev/null
+++ b/.vitepress/theme/home/NavLink.vue
@@ -0,0 +1,100 @@
+<script setup lang="ts">
+import { computed, toRefs } from 'vue'
+import { useRoute, withBase } from 'vitepress'
+import { useNavLink } from '../composables/navLink'
+import OutboundLink from './icons/OutboundLink.vue'
+
+const props = defineProps<{
+  item: {
+    text: string
+    target?: string
+    rel?: string
+    ariaLabel?: string
+    activeMatch?: string
+    link: string
+  }
+}>()
+
+const propsRefs = toRefs(props)
+
+const route = useRoute()
+const linkProps = computed(() => {
+  const routePath = normalizePath(`/${route.data.relativePath}`)
+
+  let active = false
+  if (propsRefs.item.value.activeMatch) {
+    active = new RegExp(propsRefs.item.value.activeMatch).test(routePath)
+  } else {
+    const itemPath = normalizePath(propsRefs.item.value.link)
+    active =
+      itemPath === '/'
+        ? itemPath === routePath
+        : routePath.startsWith(itemPath)
+  }
+
+  return {
+    class: {
+      active
+    },
+    href: withBase(propsRefs.item.value.link),
+    target: propsRefs.item.value.target || null,
+    rel: propsRefs.item.value.rel || null,
+    'aria-label': propsRefs.item.value.ariaLabel
+  }
+})
+
+function normalizePath(path: string): string {
+  return path
+    .replace(/#.*$/, '')
+    .replace(/\?.*$/, '')
+    .replace(/\.(html|md)$/, '')
+    .replace(/\/index$/, '/')
+}
+</script>
+
+<template>
+  <div class="nav-link">
+    <a class="item" v-bind="linkProps">
+      {{ item.text }}
+    </a>
+  </div>
+</template>
+
+<style scoped>
+.item {
+  display: block;
+  padding: 0 1.5rem;
+  line-height: 36px;
+  font-size: 1rem;
+  font-weight: 600;
+  color: var(--c-text);
+  white-space: nowrap;
+}
+
+.item:hover,
+.item.active {
+  text-decoration: none;
+  color: var(--c-brand);
+}
+
+.item.external:hover {
+  border-bottom-color: transparent;
+  color: var(--c-text);
+}
+
+@media (min-width: 720px) {
+  .item {
+    border-bottom: 2px solid transparent;
+    padding: 0;
+    line-height: 24px;
+    font-size: 0.9rem;
+    font-weight: 500;
+  }
+
+  .item:hover,
+  .item.active {
+    border-bottom-color: var(--c-brand);
+    color: var(--c-text);
+  }
+}
+</style>
\ No newline at end of file
diff --git a/.vitepress/theme/index.js b/.vitepress/theme/index.js
index 42a715a8..7e1b50a8 100644
--- a/.vitepress/theme/index.js
+++ b/.vitepress/theme/index.js
@@ -1,6 +1,8 @@
-import DefaultTheme from 'vitepress/theme'
-import './vars.css'
+import DefaultTheme from 'vitepress/theme';
+import Layout from './Layout.vue';
+import './vars.css';
 
 export default {
-  ...DefaultTheme
-}
+  ...DefaultTheme,
+  Layout
+};