Skip to content

Commit

Permalink
chore: update
Browse files Browse the repository at this point in the history
  • Loading branch information
yzh990918 committed Oct 17, 2022
0 parents commit b051d5d
Show file tree
Hide file tree
Showing 85 changed files with 13,188 additions and 0 deletions.
Binary file added .DS_Store
Binary file not shown.
13 changes: 13 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# editorconfig.org
root = true

[*]
indent_size = 2
indent_style = space
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
5 changes: 5 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
dist
node_modules
.output
.nuxt
*.md
6 changes: 6 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": [
"@nuxtjs/eslint-config-typescript",
"@vbs"
]
}
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules
*.log*
.nuxt
.nitro
.cache
.output
.env
dist
.idea
images/*
!images/README.md
3 changes: 3 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ignore-workspace-root-check=true
shamefully-hoist=true
strict-peer-dependencies=false
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# VBS-PLUS

Project site for [vbs.plus](https://vps.plus)

## Features

- 🔎 Automated Schema.org
- 📚 Markdown read time calculation
- 👨‍💻 Code file name and language support
- 🧩 Automatic Server Side Icon Resolving (no FOUC), powered by iconify & unplugin-icons
- 🤖 Sitemap.xml and feed generation
- 🍞 Automatic breadcrumbs (with Schema.org)
- 🤝 Integrated with @nuxt/image, images served with [cloudinary](https://cloudinary.com)

## More Features

- Automatic routes based on content /w 404 handling
- Automatic navigation generation
- Easy content composables
- Fully typed content
- Split pages/posts for easier content organisation
- [line-md](https://github.com/cyberalien/line-md) icons by cyberalien

## Plus

- pnpm
- WindiCSS
- Eslint with @antfu/eslint-config
- SEO / i18n best practices
- Fathom analytics
- Vercel hosted

## Setup

Make sure to install the dependencies:

```bash
pnpm i
```

## Development Server

Start the development server on http://localhost:3000

```bash
pnpm dev
```
36 changes: 36 additions & 0 deletions app.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<script lang="ts" setup>
const siteMeta = useSiteMeta()
</script>

<template>
<Html :lang="siteMeta.lang" dir="ltr">
<Head>
<Meta property="og:image" :content="`${siteMeta.host}/cover.png`" />
<SchemaOrgPerson
:name="siteMeta.name"
image="https://res.cloudinary.com/dl6o1xpyq/image/upload/f_jpg,q_auto:best,dpr_auto,w_240,h_240/images/harlan-wilton"
:same-as="siteMeta.sameAs"
/>
<SchemaOrgWebSite
:name="siteMeta.name"
:image="siteMeta.image"
:description="siteMeta.description"
/>
<SchemaOrgWebPage />
</Head>
<Body class="text-gray-800 dark:text-gray-100 antialiased">
<Header />
<main class=" lg:(px-0) md:(max-w-700px pb-20 px-8) sm:(pb-16 px-6) mx-auto max-w-full px-4 py-7 pb-10 l">
<NuxtPage class="page-enter-active" />
</main>
<footer class="px-5 sm:px-7 md:px-10 text-center text-gray-400 text-sm my-5">
<div class="flex justify-center mb-3">
<SocialIcons />
</div>
<p class="mb-3">
© 2022-PRESENT {{ siteMeta.name }}. All rights reserved.
</p>
</footer>
</Body>
</Html>
</template>
41 changes: 41 additions & 0 deletions app/router.options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { RouterConfig } from '@nuxt/schema'

// https://router.vuejs.org/api/#routeroptions
export default <RouterConfig>{
scrollBehavior(to, from, savedPosition) {
const nuxtApp = useNuxtApp()

// If history back
if (savedPosition) {
// Handle Suspense resolution
return new Promise((resolve) => {
nuxtApp.hooks.hookOnce('page:finish', () => {
setTimeout(() => resolve(savedPosition), 50)
})
})
}
// Scroll to heading on click
if (to.hash) {
setTimeout(() => {
const heading = document.querySelector(to.hash) as any

return window.scrollTo({
top: heading.offsetTop,
behavior: 'smooth',
})
})
return
}

// route change
if (from.path !== to.path) {
window.scrollTo({
top: 0,
behavior: 'smooth',
})
return
}

return { top: 0 }
},
}
21 changes: 21 additions & 0 deletions components/ColorModeSwitch.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script setup lang="ts">
const colorMode = useColorMode()
const toggleMode = () => (colorMode.value === 'light' ? (colorMode.preference = 'dark') : (colorMode.preference = 'light'))
</script>

<template>
<button aria-label="Color Mode" :title="`Enable ${colorMode.value === 'dark' ? 'Light' : 'Dark'} Mode`" class="p-2 link inline-block hover:text-gray-700 dark:hover:text-gray-300 group" @click.prevent="toggleMode">
<div class="icon">
<ColorScheme placeholder="">
<template v-if="colorMode.value === 'dark'">
<i-line-md-moon class="icon icon--off" />
<i-line-md-moon-twotone class="icon icon--on" />
</template>
<template v-else>
<i-line-md-sunny-outline class="icon icon--off" />
<i-line-md-sunny-outline-loop class="icon icon--on" />
</template>
</ColorScheme>
</div>
</button>
</template>
48 changes: 48 additions & 0 deletions components/Header.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<script lang="ts" setup>
const { data: nav } = await useHeaderNav()
</script>

<template>
<header>
<div class="flex justify-between items-center max-w-8xl mx-auto mx-auto sm:px-8 px-4">
<Logo />
<div class="flex items-center">
<!-- Navigation -->
<nav aria-label="Main Menu" class="opacity-75">
<ul class="flex lg:(space-x-7 mr-15) sm:space-x-2 space-x-1 md:mr-7 items-center">
<li v-for="(link, key) in nav" :key="key">
<NuxtLink v-slot="{ isActive }" :to="link.path" class="!inline-flex items-center group" :title="`Visit ${link.title} Page`">
<div :class="isActive ? ['sm:bg-green-50', 'text-green-800', 'dark:(sm:bg-green-800/10 text-green-50)'] : []" class="md:(px-3 py-2) px-1 py-1 rounded">
<svg
v-if="link.icon"
v-bind="link.icon"
class="hidden sm:inline-block text mr-2 mb-1 transition opacity-75 group-hover:opacity-100"
:class="isActive ? 'opacity-100' : 'opacity-75'"
/>
{{ link.title }}
</div>
<Link :key="key" rel="prefetch" :href="link.path" />
</NuxtLink>
</li>
</ul>
</nav>
<div class="md:(space-x-2) space-x-1 text-gray-500 flex items-center">
<!-- Social icons & Color Mode -->
<SocialIcons class="hidden sm:flex md:(space-x-2) space-x-1 " />
<ColorModeSwitch />
</div>
</div>
</div>
</header>
</template>

<style>
header {
border-style: none;
backdrop-filter: blur(2px);
position: sticky;
top: 0;
width: 100%;
z-index: 50;
}
</style>
56 changes: 56 additions & 0 deletions components/Logo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<script lang="ts" setup>
const siteMeta = useSiteMeta()
const initials = siteMeta.name
.split(' ')
.map(word => word[0].toLowerCase())
.join('')
</script>

<template>
<nuxt-link to="/" class="flex items-center group unstyled py-4" title="Go Home">
<img
src="/evan-yang.png"
width="80"
height="80"
format="jpeg"
:alt="siteMeta.name"
provider="cloudinary"
style="width: 40px; height: 40px;"
class="rounded-lg h-10 w-10 mr-3 group-hover:(h-11 w-11) transition-all"
>
<div aria-label="Harlan Wilton Initials" class="hidden sm:block text-gray-700 dark:text-gray-200 relative transform top-2 group-hover:top-0">
<span class="block text-green-700 font-bold text-3xl logo">{{ initials }}</span>
<span class="block text-green-700 font-bold text-3xl logo">{{ initials }}</span>
</div>
</nuxt-link>
</template>

<style lang="scss">
.group:hover {
filter: drop-shadow(0 0 35px #11998e);
.logo {
background: linear-gradient(90deg, #11998e, #38ef7d);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
transform: translateX(0px) translateY(18px) skewX(-10deg);
}
.logo:nth-of-type(2) {
filter: drop-shadow(0 0 10px #38ef7d);
transform: translateX(0) translateY(-18px) skewX(-10deg);
}
}
.logo {
transform: skewX(-10deg);
font-weight: 400;
transition: 0.2s;
background: linear-gradient(90deg, rgba(#11998e, 0.3), rgba(#38ef7d, 0.3));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.logo:nth-of-type(2) {
background: linear-gradient(90deg, #38ef7d, #11998e);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
transform: translateX(-3px) translateY(-17px) skewX(-10deg);
}
</style>
22 changes: 22 additions & 0 deletions components/PageRenderer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script lang="ts" setup>
import type { PropType } from 'vue'
import type { Page } from '../types'
const props = defineProps({
page: Object as PropType<Page>,
})
const contentComponent = computed(() => props.page.prose !== false ? resolveComponent('Prose') : 'div')
const schema = computed(() => props.page.schema || {})
</script>

<template>
<div>
<SchemaOrgWebPage
v-bind="schema"
/>
<component :is="contentComponent">
<ContentRenderer :value="page" />
</component>
</div>
</template>
Loading

0 comments on commit b051d5d

Please sign in to comment.