Init
This commit is contained in:
15
src/App.vue
Normal file
15
src/App.vue
Normal file
@@ -0,0 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
// https://github.com/vueuse/head
|
||||
// you can use this to manipulate the document head in any components,
|
||||
// they will be rendered correctly in the html results with vite-ssg
|
||||
useHead({
|
||||
title: 'Flycro',
|
||||
meta: [
|
||||
{ name: 'description', content: 'Just another Username in the vast sea of the web. ' },
|
||||
],
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<router-view />
|
||||
</template>
|
||||
217
src/auto-imports.d.ts
vendored
Normal file
217
src/auto-imports.d.ts
vendored
Normal file
@@ -0,0 +1,217 @@
|
||||
// Generated by 'unplugin-auto-import'
|
||||
// We suggest you to commit this file into source control
|
||||
declare global {
|
||||
const afterAll: typeof import('vitest')['afterAll']
|
||||
const afterEach: typeof import('vitest')['afterEach']
|
||||
const assert: typeof import('vitest')['assert']
|
||||
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
|
||||
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
|
||||
const beforeAll: typeof import('vitest')['beforeAll']
|
||||
const beforeEach: typeof import('vitest')['beforeEach']
|
||||
const biSyncRef: typeof import('@vueuse/core')['biSyncRef']
|
||||
const chai: typeof import('vitest')['chai']
|
||||
const computed: typeof import('vue')['computed']
|
||||
const computedInject: typeof import('@vueuse/core')['computedInject']
|
||||
const controlledComputed: typeof import('@vueuse/core')['controlledComputed']
|
||||
const controlledRef: typeof import('@vueuse/core')['controlledRef']
|
||||
const createApp: typeof import('vue')['createApp']
|
||||
const createEventHook: typeof import('@vueuse/core')['createEventHook']
|
||||
const createGlobalState: typeof import('@vueuse/core')['createGlobalState']
|
||||
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
|
||||
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
|
||||
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
|
||||
const customRef: typeof import('vue')['customRef']
|
||||
const debouncedRef: typeof import('@vueuse/core')['debouncedRef']
|
||||
const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
|
||||
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
|
||||
const defineComponent: typeof import('vue')['defineComponent']
|
||||
const describe: typeof import('vitest')['describe']
|
||||
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
|
||||
const effectScope: typeof import('vue')['effectScope']
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const expect: typeof import('vitest')['expect']
|
||||
const extendRef: typeof import('@vueuse/core')['extendRef']
|
||||
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
|
||||
const getCurrentScope: typeof import('vue')['getCurrentScope']
|
||||
const h: typeof import('vue')['h']
|
||||
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
|
||||
const inject: typeof import('vue')['inject']
|
||||
const isDefined: typeof import('@vueuse/core')['isDefined']
|
||||
const isReadonly: typeof import('vue')['isReadonly']
|
||||
const isRef: typeof import('vue')['isRef']
|
||||
const it: typeof import('vitest')['it']
|
||||
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
|
||||
const markRaw: typeof import('vue')['markRaw']
|
||||
const nextTick: typeof import('vue')['nextTick']
|
||||
const onActivated: typeof import('vue')['onActivated']
|
||||
const onBeforeMount: typeof import('vue')['onBeforeMount']
|
||||
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
|
||||
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
|
||||
const onClickOutside: typeof import('@vueuse/core')['onClickOutside']
|
||||
const onDeactivated: typeof import('vue')['onDeactivated']
|
||||
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
|
||||
const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke']
|
||||
const onMounted: typeof import('vue')['onMounted']
|
||||
const onRenderTracked: typeof import('vue')['onRenderTracked']
|
||||
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
|
||||
const onScopeDispose: typeof import('vue')['onScopeDispose']
|
||||
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
|
||||
const onStartTyping: typeof import('@vueuse/core')['onStartTyping']
|
||||
const onUnmounted: typeof import('vue')['onUnmounted']
|
||||
const onUpdated: typeof import('vue')['onUpdated']
|
||||
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
|
||||
const provide: typeof import('vue')['provide']
|
||||
const reactify: typeof import('@vueuse/core')['reactify']
|
||||
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
|
||||
const reactive: typeof import('vue')['reactive']
|
||||
const reactivePick: typeof import('@vueuse/core')['reactivePick']
|
||||
const readonly: typeof import('vue')['readonly']
|
||||
const ref: typeof import('vue')['ref']
|
||||
const refDefault: typeof import('@vueuse/core')['refDefault']
|
||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||
const shallowReactive: typeof import('vue')['shallowReactive']
|
||||
const shallowReadonly: typeof import('vue')['shallowReadonly']
|
||||
const shallowRef: typeof import('vue')['shallowRef']
|
||||
const suite: typeof import('vitest')['suite']
|
||||
const syncRef: typeof import('@vueuse/core')['syncRef']
|
||||
const templateRef: typeof import('@vueuse/core')['templateRef']
|
||||
const test: typeof import('vitest')['test']
|
||||
const throttledRef: typeof import('@vueuse/core')['throttledRef']
|
||||
const throttledWatch: typeof import('@vueuse/core')['throttledWatch']
|
||||
const toRaw: typeof import('vue')['toRaw']
|
||||
const toReactive: typeof import('@vueuse/core')['toReactive']
|
||||
const toRef: typeof import('vue')['toRef']
|
||||
const toRefs: typeof import('vue')['toRefs']
|
||||
const triggerRef: typeof import('vue')['triggerRef']
|
||||
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
|
||||
const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted']
|
||||
const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose']
|
||||
const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted']
|
||||
const unref: typeof import('vue')['unref']
|
||||
const unrefElement: typeof import('@vueuse/core')['unrefElement']
|
||||
const until: typeof import('@vueuse/core')['until']
|
||||
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
|
||||
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
|
||||
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
|
||||
const useAttrs: typeof import('vue')['useAttrs']
|
||||
const useBase64: typeof import('@vueuse/core')['useBase64']
|
||||
const useBattery: typeof import('@vueuse/core')['useBattery']
|
||||
const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints']
|
||||
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
|
||||
const useClamp: typeof import('@vueuse/core')['useClamp']
|
||||
const useClipboard: typeof import('@vueuse/core')['useClipboard']
|
||||
const useColorMode: typeof import('@vueuse/core')['useColorMode']
|
||||
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
|
||||
const useCounter: typeof import('@vueuse/core')['useCounter']
|
||||
const useCssModule: typeof import('vue')['useCssModule']
|
||||
const useCssVar: typeof import('@vueuse/core')['useCssVar']
|
||||
const useCycleList: typeof import('@vueuse/core')['useCycleList']
|
||||
const useDark: typeof import('@vueuse/core')['useDark']
|
||||
const useDebounce: typeof import('@vueuse/core')['useDebounce']
|
||||
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
|
||||
const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn']
|
||||
const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion']
|
||||
const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation']
|
||||
const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio']
|
||||
const useDevicesList: typeof import('@vueuse/core')['useDevicesList']
|
||||
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
|
||||
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
|
||||
const useDraggable: typeof import('@vueuse/core')['useDraggable']
|
||||
const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
|
||||
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
|
||||
const useElementHover: typeof import('@vueuse/core')['useElementHover']
|
||||
const useElementSize: typeof import('@vueuse/core')['useElementSize']
|
||||
const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility']
|
||||
const useEventBus: typeof import('@vueuse/core')['useEventBus']
|
||||
const useEventListener: typeof import('@vueuse/core')['useEventListener']
|
||||
const useEventSource: typeof import('@vueuse/core')['useEventSource']
|
||||
const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper']
|
||||
const useFavicon: typeof import('@vueuse/core')['useFavicon']
|
||||
const useFetch: typeof import('@vueuse/core')['useFetch']
|
||||
const useFocus: typeof import('@vueuse/core')['useFocus']
|
||||
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
|
||||
const useFps: typeof import('@vueuse/core')['useFps']
|
||||
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
|
||||
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
|
||||
const useHead: typeof import('@vueuse/head')['useHead']
|
||||
const useI18n: typeof import('vue-i18n')['useI18n']
|
||||
const useIdle: typeof import('@vueuse/core')['useIdle']
|
||||
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
|
||||
const useInterval: typeof import('@vueuse/core')['useInterval']
|
||||
const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn']
|
||||
const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier']
|
||||
const useLastChanged: typeof import('@vueuse/core')['useLastChanged']
|
||||
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
|
||||
const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys']
|
||||
const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory']
|
||||
const useMediaControls: typeof import('@vueuse/core')['useMediaControls']
|
||||
const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery']
|
||||
const useMemory: typeof import('@vueuse/core')['useMemory']
|
||||
const useMounted: typeof import('@vueuse/core')['useMounted']
|
||||
const useMouse: typeof import('@vueuse/core')['useMouse']
|
||||
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
|
||||
const useMousePressed: typeof import('@vueuse/core')['useMousePressed']
|
||||
const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver']
|
||||
const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage']
|
||||
const useNetwork: typeof import('@vueuse/core')['useNetwork']
|
||||
const useNow: typeof import('@vueuse/core')['useNow']
|
||||
const useOnline: typeof import('@vueuse/core')['useOnline']
|
||||
const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
|
||||
const useParallax: typeof import('@vueuse/core')['useParallax']
|
||||
const usePermission: typeof import('@vueuse/core')['usePermission']
|
||||
const usePointer: typeof import('@vueuse/core')['usePointer']
|
||||
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
|
||||
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
|
||||
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
|
||||
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
|
||||
const useRafFn: typeof import('@vueuse/core')['useRafFn']
|
||||
const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
|
||||
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
|
||||
const useRoute: typeof import('vue-router')['useRoute']
|
||||
const useRouter: typeof import('vue-router')['useRouter']
|
||||
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
|
||||
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
|
||||
const useScroll: typeof import('@vueuse/core')['useScroll']
|
||||
const useScrollLock: typeof import('@vueuse/core')['useScrollLock']
|
||||
const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage']
|
||||
const useShare: typeof import('@vueuse/core')['useShare']
|
||||
const useSlots: typeof import('vue')['useSlots']
|
||||
const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition']
|
||||
const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis']
|
||||
const useStorage: typeof import('@vueuse/core')['useStorage']
|
||||
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
|
||||
const useSwipe: typeof import('@vueuse/core')['useSwipe']
|
||||
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
|
||||
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
|
||||
const useThrottle: typeof import('@vueuse/core')['useThrottle']
|
||||
const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory']
|
||||
const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn']
|
||||
const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo']
|
||||
const useTimeout: typeof import('@vueuse/core')['useTimeout']
|
||||
const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn']
|
||||
const useTimestamp: typeof import('@vueuse/core')['useTimestamp']
|
||||
const useTitle: typeof import('@vueuse/core')['useTitle']
|
||||
const useToggle: typeof import('@vueuse/core')['useToggle']
|
||||
const useTransition: typeof import('@vueuse/core')['useTransition']
|
||||
const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
|
||||
const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
|
||||
const useVirtualList: typeof import('@vueuse/core')['useVirtualList']
|
||||
const useVModel: typeof import('@vueuse/core')['useVModel']
|
||||
const useVModels: typeof import('@vueuse/core')['useVModels']
|
||||
const useWakeLock: typeof import('@vueuse/core')['useWakeLock']
|
||||
const useWebSocket: typeof import('@vueuse/core')['useWebSocket']
|
||||
const useWebWorker: typeof import('@vueuse/core')['useWebWorker']
|
||||
const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn']
|
||||
const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus']
|
||||
const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll']
|
||||
const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
|
||||
const vi: typeof import('vitest')['vi']
|
||||
const vitest: typeof import('vitest')['vitest']
|
||||
const watch: typeof import('vue')['watch']
|
||||
const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
|
||||
const watchEffect: typeof import('vue')['watchEffect']
|
||||
const watchOnce: typeof import('@vueuse/core')['watchOnce']
|
||||
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
|
||||
const whenever: typeof import('@vueuse/core')['whenever']
|
||||
}
|
||||
export {}
|
||||
29
src/components.d.ts
vendored
Normal file
29
src/components.d.ts
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
// generated by unplugin-vue-components
|
||||
// We suggest you to commit this file into source control
|
||||
// Read more: https://github.com/vuejs/vue-next/pull/3399
|
||||
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
AkarIconsMoonFill: typeof import('~icons/akar-icons/moon-fill')['default']
|
||||
BiDiscord: typeof import('~icons/bi/discord')['default']
|
||||
BiGearFill: typeof import('~icons/bi/gear-fill')['default']
|
||||
BiGithub: typeof import('~icons/bi/github')['default']
|
||||
BiInstagram: typeof import('~icons/bi/instagram')['default']
|
||||
BiTwitter: typeof import('~icons/bi/twitter')['default']
|
||||
CarbonCampsite: typeof import('~icons/carbon/campsite')['default']
|
||||
CarbonDicomOverlay: typeof import('~icons/carbon/dicom-overlay')['default']
|
||||
CarbonLanguage: typeof import('~icons/carbon/language')['default']
|
||||
CarbonLogoGithub: typeof import('~icons/carbon/logo-github')['default']
|
||||
CarbonMoon: typeof import('~icons/carbon/moon')['default']
|
||||
CarbonSun: typeof import('~icons/carbon/sun')['default']
|
||||
ClarityNoteSolid: typeof import('~icons/clarity/note-solid')['default']
|
||||
Counter: typeof import('./components/Counter.vue')['default']
|
||||
EntypoMail: typeof import('~icons/entypo/mail')['default']
|
||||
Footer: typeof import('./components/Footer.vue')['default']
|
||||
IonBulb: typeof import('~icons/ion/bulb')['default']
|
||||
Navbar: typeof import('./components/Navbar.vue')['default']
|
||||
README: typeof import('./components/README.md')['default']
|
||||
}
|
||||
}
|
||||
|
||||
export { }
|
||||
19
src/components/Counter.vue
Normal file
19
src/components/Counter.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
initial: number
|
||||
}>()
|
||||
|
||||
const { count, inc, dec } = useCounter(props.initial)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
{{ count }}
|
||||
<button class="inc" @click="inc()">
|
||||
+
|
||||
</button>
|
||||
<button class="dec" @click="dec()">
|
||||
-
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
36
src/components/Footer.vue
Normal file
36
src/components/Footer.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<script setup lang="ts">
|
||||
import { isDark, toggleDark } from '~/composables'
|
||||
|
||||
const { t, availableLocales, locale } = useI18n()
|
||||
|
||||
const toggleLocales = () => {
|
||||
// change to some real logic
|
||||
const locales = availableLocales
|
||||
locale.value = locales[(locales.indexOf(locale.value) + 1) % locales.length]
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="text-xl mt-6">
|
||||
<router-link class="icon-btn mx-2" to="/" :title="t('button.home')">
|
||||
<carbon-campsite />
|
||||
</router-link>
|
||||
|
||||
<button class="icon-btn mx-2 !outline-none" :title="t('button.toggle_dark')" @click="toggleDark()">
|
||||
<carbon-moon v-if="isDark" />
|
||||
<carbon-sun v-else />
|
||||
</button>
|
||||
|
||||
<a class="icon-btn mx-2" :title="t('button.toggle_langs')" @click="toggleLocales">
|
||||
<carbon-language />
|
||||
</a>
|
||||
|
||||
<router-link class="icon-btn mx-2" to="/about" :title="t('button.about')">
|
||||
<carbon-dicom-overlay />
|
||||
</router-link>
|
||||
|
||||
<a class="icon-btn mx-2" rel="noreferrer" href="https://github.com/antfu/vitesse" target="_blank" title="GitHub">
|
||||
<carbon-logo-github />
|
||||
</a>
|
||||
</nav>
|
||||
</template>
|
||||
222
src/components/Navbar.vue
Normal file
222
src/components/Navbar.vue
Normal file
@@ -0,0 +1,222 @@
|
||||
<template>
|
||||
<div class="h-28 bg-light-100 flex flex-row content-center dark:bg-dark-900">
|
||||
<div class="w-1/5 m-auto flex">
|
||||
<a href="/">
|
||||
<svg
|
||||
id="logo"
|
||||
class="w-64 h-20"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 790.8 303.3"
|
||||
xml:space="preserve"
|
||||
>
|
||||
<g id="logo-group">
|
||||
<g id="logo-path-group">
|
||||
<g>
|
||||
<path
|
||||
id="logo-f"
|
||||
ref="logoF"
|
||||
class="fill-none stroke-fly-600 dark:stroke-fly-500 stroke-width-5"
|
||||
d="M20.2,263.9c0.1-1,0.2-2.1,0.5-3.1c2.5-10.2,10.6-17,17.3-24.5c4.5-5,8.6-10.4,10.1-17.1
|
||||
c1.3-5.5,0.4-10.7-3.2-15c-6.5-8-10.8-17.1-10.1-27.7c1.5-20.5,19.4-35.9,22.3-56.3c0.7-5.3,0.1-10.7,0-16
|
||||
c-0.2-7.8,0.9-15.7,4.6-22.7c3.2-6.1,8.6-11.2,15.2-13c7.2-1.9,14.9,0.3,21.9,2.9c4.9,1.8,9.7,4.5,14.9,5.3
|
||||
c5.6,0.9,11.2-1.1,16.2-3.5c3.4-1.6,6.6-3.3,9.8-5.2c1.2-0.7,8.1-4.5,6.8,0c-3.5,11.8-10.8,22.2-21.4,28.7
|
||||
c-3.8,2.3-8.1,4.1-12.6,4.2c-4.7,0.2-9.3-1.4-14-2c-12.6-1.3-22.6,12.2-23.2,23.8c-0.7,12.2,17.5,8.6,24.5,6.5
|
||||
c7-2.2,13.6-5.4,19.6-9.5c3.1-2,7.1-5.3,11-5.1c3.5,0.1,6.4,2.4,9.3,4.2c2.7,1.7,6.3,1.2,8.9,3c5.4,3.7-1.9,14.6-4.8,18.1
|
||||
c-4.5,5.4-11,8.8-18.1,8.5c-5.7-0.2-11.1-2.6-16.7-3.6c-12.7-2.2-40.4,7.8-35.9,24.7c1.2,4.6,4.1,8.4,6.2,12.6
|
||||
c3.8,7.5,4.8,16.1,2.9,24.2c-2.1,8-7.2,12.4-13.4,17.1c-6.6,5-12.9,10.6-17.6,17.5c-5.1,7.6-7.9,16.4-10.2,25.1
|
||||
c-1.2,4.7-2.1,11.3-8.5,11.1c-4.7-0.4-8.9-3.1-11.2-7.2C20.4,268.2,20,266,20.2,263.9z"
|
||||
/>
|
||||
<path
|
||||
id="logo-l"
|
||||
ref="logoL"
|
||||
class="fill-none stroke-fly-600 dark:stroke-fly-500 stroke-width-5"
|
||||
d="M150.5,253.5c0.8-8.1,4.1-15.8,8.2-22.9c3.8-6.7,8.4-12.8,12.7-19.1c3.8-5.6,7.6-11.4,9.5-18
|
||||
c2-7.1,2.7-14.8,3.8-22c1.2-8-0.9-15.6-3.6-22.9c-2.1-5.7-5.3-11-7.2-16.8c-1.9-5.8-2.7-11.9-2.4-18c0.3-7,1.9-13.9,3.6-20.7
|
||||
c1-4.7,2.4-9.2,4.3-13.6c1.4-2.9,3.2-5.5,5.3-7.9c1.8-2.2,3.8-5.5,7.1-4.7c1.2,0.3,2.4,0.9,3.4,1.8c6.6,5.3,8.4,13.9,5.9,21.7
|
||||
c-2.8,8.7-9.7,15.9-11.6,24.8c-1.2,5.8-0.2,11.8,1.2,17.6c1.1,4.8,2.8,9.4,5.1,13.6c1.3,2,2.7,4,4.3,5.8c1.4,2.1,2.6,4.4,3.5,6.8
|
||||
c2.1,5.4,1.2,10.1,0.2,15.6c-0.6,3.5-1.3,7-2.3,10.5c-0.9,3.2-2.6,6-4.3,8.9c-5.2,8.9-10.9,16.7-11.2,27.5
|
||||
c-0.1,4.4,1.2,8.3,5.3,10.5c3.9,2.3,8.8,2,12.5-0.6c3.2-2.1,5.1-5.1,6.9-8.2c2.9-5.2,7.5-9.3,13.1-11.7c2.8-1.2,5.9-1.5,8.9-0.8
|
||||
c4.1,0.7,8.7,1,9.2,6.1c0.5,4.6-1.6,8.4-2.7,12.6c-1.1,4.4-3.3,8.4-6.4,11.6c-4.3,4.4-10.3,6.8-16.2,8c-5.9,1.2-12.2,1.4-17.2,5
|
||||
c-5.5,3.9-7.8,11-13.9,14.2c-8,4.1-19.9,7.4-28.6,3.7c-1.5-0.6-2.9-1.6-4-2.8c-0.9-1.3-1.5-2.7-1.8-4.2
|
||||
C150.3,261.2,150,257.3,150.5,253.5z"
|
||||
/>
|
||||
<path
|
||||
id="logo-y"
|
||||
ref="logoY"
|
||||
class="fill-none stroke-fly-600 dark:stroke-fly-500 stroke-width-5"
|
||||
d="M275.5,141.1c0.4,0.9,0.6,1.9,0.6,2.9c0.5,6.2-0.8,12.5-0.6,18.7c0,0.4,0,0.7,0,1.1
|
||||
c0.3,5.6,1.3,11.1,4.8,15.9c3.1,4.2,6.4,8.3,8.2,13.5c1.9,5.6,3.2,11.6,2.5,17.5c-0.7,5.8-3.5,11-6,16.2c-2.3,4.8-4,9.8-3.4,15.1
|
||||
c0.5,4.8,2.4,9.2,5.6,12.8c2.6,2.7,6.4,3.7,10,2.9c3.9-1.1,5.7-4.3,7.7-7.5c2.3-3.8,4.4-7.7,6.2-11.7c2.4-5.3,4.7-11,5.7-16.8
|
||||
c1-5.8,0.6-11.5,0.3-17.2c-0.3-6.2-0.7-12.6-2.2-18.7c-1.5-6.3-4.6-12.2-6.7-18.4c-1.9-5.7-4.4-11.1-2.6-17.7
|
||||
c1.5-5.8,4.8-10.1,8.8-13.9c4.3-4.1,7.2-8.5,8.2-14.4c1.1-5.7,0.7-11.6-1.3-17c-1.1-3.2-2-6.3-1.5-9.8c1-6.8,4.3-12.6,7.3-18.5
|
||||
c2.3-4.6,4.7-9.2,6.6-14c1.1-2.7-0.3-5.9-1.9-8.1c-2.6-3.6-8.5-5.1-12.3-2.5c-2.8,1.8-5.2,6.3-5.8,9.5c-0.6,3.6,0.5,7.1-1,10.6
|
||||
c-1.4,3.5-4,6.1-6.5,8.7c-1.9,1.8-3.6,3.6-5.1,5.6c-1.4,2-2.5,4.2-3.4,6.5c-2.1,4.7-2.8,9.8-2.2,14.9c0.4,2.5,1.2,5,1.4,7.5
|
||||
c0.4,3-0.5,6.1-2.6,8.4c-0.8,1-1.9,1.6-3.2,1.9c-1,0.2-2.1,0-3-0.6c-1.4-1-1.6-3-1.5-4.8c0.2-4.6,1.3-10.5-2.4-14
|
||||
c-4-3.7-8.4-6.9-12.5-10.4c-2.7-2.3-5.8-4.9-4.8-8.6c1.2-5.4,1.1-11-0.4-16.3c-0.4-1.7-1.2-3.3-2.4-4.6c-4.3-4.3-11.1-4.3-16-1.2
|
||||
c-4.9,3.1-7.3,9.6-7.1,15.2c0.2,4.4,2.4,6.6,5.4,9.5c2.2,2.1,4.5,3.9,7,5.6c2.8,1.9,4.6,4.9,5.2,8.2c0.8,4.8-1,9.1-1.7,13.7
|
||||
c-0.6,4.3-0.7,8.2,1.2,12.1c2,4.2,6.6,10.2,11.8,9.9c1.2-0.2,2.4-0.1,3.5,0.3C274.5,139.4,275.2,140.2,275.5,141.1z"
|
||||
/>
|
||||
<path
|
||||
id="logo-c"
|
||||
ref="logoC"
|
||||
class="fill-none stroke-fly-600 dark:stroke-fly-500 stroke-width-5"
|
||||
d="M386.6,156.2c-1.1,5.2-1.6,10.5-0.2,15.7c1.1,4.5,3.7,8.5,6.1,12.4c2.3,3.9,5,7.6,8,10.9
|
||||
c5.6,5.9,15.3,10.7,23.5,10.6c3.4,0,6.8-0.9,10.2-1.1c4.8-0.3,9.5,1.6,12.7,5.3c3.8,4.3,2.3,10.1-0.6,14.4c-1.8,2.6-4,5-5.4,7.9
|
||||
c-1.8,3.6-2.3,7.8-1.5,11.7c0.4,1.8,1.3,3.2,0.9,5c-0.9,4.4-6.3,5.4-10.1,5.5c-5.9,0.2-11.6-1.3-16.8-4.1
|
||||
c-7.1-4.1-10.8-10.9-12.4-18.8c-0.8-4.2-2.6-8.2-5.2-11.7c-7.2-9.6-19.5-12.9-27.6-21.5c-4.2-4.5-7-10-8.2-16
|
||||
c-2.4-12,2.6-24.8,8.1-35.2c4.1-7.7,8.2-15.7,9.2-24.5c1.1-9.4-1.6-18.9-1.1-28.4c0.1-2.2,0.4-4.3,0.8-6.5
|
||||
c1.9-10.7,7.4-20.7,16.6-26.9c2.6-1.7,5.6-3.2,8.7-3.2c2.6,0.1,5.1,0.9,7.3,2.3c4.1,2.6,9.1,3.4,13.8,2.3
|
||||
c5.5-1.1,10.8-3.2,16-5.1c6.8-2.5,13.9-4.7,21.1-3.9c4.5,0.5,9.3,2.5,10.4,7.3c0.4,2.3,0.2,4.6-0.7,6.7c-1.4,4-3.8,7.4-6.3,10.8
|
||||
c-1.6,2.2-3.3,4.4-4.9,6.6c-0.6,0.9-1.4,1.7-2.3,2.3c-1.2,0.6-2.7,0.7-3.9,0.1c-4.8-1.8-10.2-1.5-15.1-0.1
|
||||
c-4.9,1.6-9.5,3.8-13.8,6.6c-5.6,3.5-11,7.3-15.3,12.1c-3.8,4.2-6.7,9.2-10.1,13.8c-3.1,4.3-4.6,9.5-6.1,14.6l-3.6,12.9
|
||||
C388.1,150.2,387.2,153.2,386.6,156.2z"
|
||||
/>
|
||||
<path
|
||||
id="logo-r"
|
||||
ref="logoR"
|
||||
class="fill-none stroke-fly-600 dark:stroke-fly-500 stroke-width-5"
|
||||
d="M540.7,270c0.3-1.2,0.5-2.5,0.4-3.8c-0.1-3.8,0.6-7.5,2-11.1c3-8,9.7-13.3,14.1-20.4
|
||||
c4.1-6.7,5.6-14.7,5.9-22.6c0.2-6.7-0.4-13.4-0.7-20c-0.2-6.3-1.2-12.6-3-18.7c-1.7-5.8-5.8-9.9-8.2-15.3
|
||||
c-3.7-8.3-7.3-20.8-0.2-28.1c2.4-2.4,5.3-4.2,8.6-5.3c4.5-1.6,9.2-2.2,13.9-1.6c1.8,0.1,3.6,0.7,5.2,1.6
|
||||
c5.1,3.1,3.3,11.9,2.8,16.8c-0.7,7-2.1,13.9-2.9,20.9c-0.6,5.9,2.9,12.5,8.6,14.8c3.2,1.3,7,0.6,10.1-1c4.2-2.2,9.2-6.5,10.5-11.2
|
||||
c0.5-2.1,0.7-4.2,0.6-6.4c-0.1-6.1-0.8-12.2-2.2-18.1c-1.3-5.6-4.8-10.4-6.1-16c-1.4-6.2,0-12.6,1.6-18.8c1.3-5,2.9-10,4.8-14.8
|
||||
c1.1-2.5,2.2-5.1,2-7.8c-0.3-3.6-3-6.6-6.2-8.1c-19.2-9.2-33.7,12.9-40.3,27.6c0,0.1,0,0.1-0.1,0.2c-1.6,4-5.3,6.8-9.6,7.1
|
||||
c-7.3,0.7-7.8-9.7-8-14.6c-0.1-3.7,1.5-6.5,2.7-9.9c1.1-3,2.1-6.1,2.8-9.2c1.4-6.3,2.4-14-1.1-19.8c-1.7-2.8-4.4-4.8-7.5-5.7
|
||||
c-11.9-3.8-22.4,3.7-28.5,13.5c-5.7,9.2-3.1,22.4,5.9,28.6c1.4,0.8,2.7,1.8,3.8,2.9c1.7,2.2,1.7,5.2,1.2,8
|
||||
c-1.2,6.8-4.5,12.8-8,18.5c-3.2,5.2-7.9,9.8-9.7,15.7c-1.8,5.9-0.9,13.3,0,19.3c0.5,4,1.7,8,3.5,11.6c2,3.8,5.4,6.6,8.5,9.5
|
||||
c0.9,0.8,1.7,1.6,2.5,2.5c3.6,3.8,5.9,8.6,6.8,13.7c1,6.2-1,11.2-3.7,16.6c-2.5,5-4.8,10.2-6.9,15.4c-2.9,7.4-5.4,15.1-5.1,23
|
||||
c0.2,7.9,3.7,16.1,10.5,20.3c3.1,1.8,6.6,3,10.2,3.5c1.6,0.4,3.3,0.4,5,0.1C538.9,273,540.2,271.7,540.7,270z"
|
||||
/>
|
||||
<path
|
||||
id="logo-o"
|
||||
ref="logoO"
|
||||
class="fill-none stroke-fly-600 dark:stroke-fly-500 stroke-width-5"
|
||||
d="M755.5,91.5c-0.3-6-2.3-11.7-7.1-15.9c-3.6-3.1-8.3-4.2-12.5-6.3c-8.7-4.3-13.3-12.1-19.4-19.1
|
||||
c-5.6-6.4-13.3-12.4-21.7-14.4c-3.4-0.7-7-1-10.5-0.7c-19.7,1-43.6,14.3-41.8,37c0.4,4.8,1.7,9.5,2.6,14.3
|
||||
c2.7,14.4,1.7,29.2-3,43c-4.6,13.5-7.8,29.1-6.5,43.4c0.7,8.3,2.6,16.5,3.1,24.8c0.7,13-2.5,25.6-1.6,38.5
|
||||
c0.2,4.3,1,8.5,2.3,12.6c2.2,6.4,5.6,12.3,10.2,17.3c2.6,2.8,5.4,5.3,9.1,6.8c14.6,5.8,34.9,9.1,49.8,2.6
|
||||
c16.8-7.4,20.7-26.1,23.2-42.4c2.9-18.5,16.1-34.3,16.1-53.2c0-17.5-4.2-33.7-0.1-51.1c1.8-7.5,4.5-14.7,6.2-22.2
|
||||
C755.1,101.5,755.6,96.5,755.5,91.5z M735.7,115.9c-0.3,0.7-0.6,1.4-1,2.1c-3.2,6.5-7.5,12.5-10.7,19c-3.6,7.5-5.7,15.9-4.9,24.2
|
||||
c0.8,8.3,4.3,16,6,24.1c3.5,16.9-1.4,35.1-12.3,48.4c-10.8,13.1-27.3,19.4-43,11c-2.7-1.4-5.4-2.9-7.2-5.3
|
||||
c-1.9-2.5-2.6-5.8-2.8-8.9c-0.6-12.6,9.4-24.3,4.4-36.7c-1.9-4.8-5.5-8.7-8-13.2c-5.2-9.1-6-20.1-2.3-29.9
|
||||
c2.8-7.4,8.1-13.6,12.3-20.4s7.4-14.9,5.4-22.6c-2.1-8.4-9.8-14.4-12.4-22.6c-3.5-10.9,3.5-23.3,13.8-28.5
|
||||
c7.2-3.6,16.9-3.9,22.7,1.7c6.3,6,5.4,16,15.1,18.3c8.5,2,18.2,3.8,23.9,11.1C740.9,95.5,739.6,106.7,735.7,115.9L735.7,115.9z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<div class="flex justify-end w-full m-5 align-middle self-center">
|
||||
<router-link class="text-gray-400 mx-4 hover:text-gray-900 dark:hover:text-light-100 <sm:mx-1" to="/posts">
|
||||
<clarity-note-solid class="md:hidden" /><span class="<md:hidden">Blog</span>
|
||||
</router-link>
|
||||
<router-link class="text-gray-400 mx-4 hover:text-gray-900 dark:hover:text-light-100 <sm:mx-1" to="/projects">
|
||||
<bi-gear-fill class="md:hidden" /><span class="<md:hidden">Projects</span>
|
||||
</router-link>
|
||||
<a class="text-gray-400 mx-4 hover:text-gray-900 dark:hover:text-light-100 <sm:hidden <sm:mx-1" href="https://twitter.com/Flycro74" target="_blank" rel="noopener noreferrer">
|
||||
<bi-twitter />
|
||||
</a>
|
||||
<a class="text-gray-400 mx-4 hover:text-gray-900 dark:hover:text-light-100 <sm:mx-1" href="https://github.com/Flycro" target="_blank" rel="noopener noreferrer">
|
||||
<bi-github />
|
||||
</a>
|
||||
<a class="text-gray-400 mx-4 hover:text-gray-900 dark:hover:text-light-100 <sm:mx-1" href="https://www.instagram.com/flycro/" target="_blank" rel="noopener noreferrer">
|
||||
<bi-instagram />
|
||||
</a>
|
||||
<a class="text-gray-400 mx-4 hover:text-gray-900 dark:hover:text-light-100 <sm:hidden <sm:mx-1" href="https://discordapp.com/users/431506802635440128" target="_blank" rel="noopener noreferrer">
|
||||
<bi-discord />
|
||||
</a>
|
||||
<a class="text-gray-400 mx-4 hover:text-gray-900 dark:hover:text-light-100 <sm:mx-1" href="mailto:hi@flycro.me" target="_blank" rel="noopener noreferrer">
|
||||
<entypo-mail />
|
||||
</a>
|
||||
<a class="text-gray-400 mx-4 my-auto hover:text-gray-900 dark:hover:text-light-100 <sm:mx-1" title="toogle-dark-mode" @click="toggleDark()">
|
||||
<akar-icons-moon-fill v-if="isDark" />
|
||||
<ion-bulb v-else />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { isDark, toggleDark } from '~/composables'
|
||||
|
||||
const animatedLogo = useSessionStorage('animated-logo', false)
|
||||
const logoF = ref<HTMLDivElement>()
|
||||
const logoL = ref<HTMLDivElement>()
|
||||
const logoY = ref<HTMLDivElement>()
|
||||
const logoC = ref<HTMLDivElement>()
|
||||
const logoR = ref<HTMLDivElement>()
|
||||
const logoO = ref<HTMLDivElement>()
|
||||
onMounted(() => {
|
||||
if (animatedLogo.value === false) {
|
||||
logoF?.value?.classList.add('gENfTICK_0')
|
||||
logoL?.value?.classList.add('gENfTICK_1')
|
||||
logoY?.value?.classList.add('gENfTICK_2')
|
||||
logoC?.value?.classList.add('gENfTICK_3')
|
||||
logoR?.value?.classList.add('gENfTICK_4')
|
||||
logoO?.value?.classList.add('gENfTICK_5')
|
||||
animatedLogo.value = true
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
.router-link-active{
|
||||
@apply text-gray-900 dark:text-light-100 dark:hover:text-light-100
|
||||
}
|
||||
.st0 {
|
||||
@apply stroke-fly-600 dark:stroke-fly-500
|
||||
fill: none;
|
||||
stroke-width: 5;
|
||||
stroke-miterlimit: 10;
|
||||
}
|
||||
.gENfTICK_0 {
|
||||
stroke-dasharray: 739 741;
|
||||
stroke-dashoffset: 740;
|
||||
animation: gENfTICK_draw 1500ms linear 0ms forwards;
|
||||
}
|
||||
.gENfTICK_1 {
|
||||
stroke-dasharray: 612 614;
|
||||
stroke-dashoffset: 613;
|
||||
animation: gENfTICK_draw 1500ms linear 0ms forwards;
|
||||
}
|
||||
.gENfTICK_2 {
|
||||
stroke-dasharray: 636 638;
|
||||
stroke-dashoffset: 637;
|
||||
animation: gENfTICK_draw 1500ms linear 0ms forwards;
|
||||
}
|
||||
.gENfTICK_3 {
|
||||
stroke-dasharray: 583 585;
|
||||
stroke-dashoffset: 584;
|
||||
animation: gENfTICK_draw 1500ms linear 0ms forwards;
|
||||
}
|
||||
.gENfTICK_4 {
|
||||
stroke-dasharray: 1106 1108;
|
||||
stroke-dashoffset: 1107;
|
||||
animation: gENfTICK_draw 1500ms linear 0ms forwards;
|
||||
}
|
||||
.gENfTICK_5 {
|
||||
stroke-dasharray: 780 782;
|
||||
stroke-dashoffset: 781;
|
||||
animation: gENfTICK_draw 1500ms linear 0ms forwards;
|
||||
}
|
||||
@keyframes gENfTICK_draw {
|
||||
100% {
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
}
|
||||
@keyframes gENfTICK_fade {
|
||||
0% {
|
||||
stroke-opacity: 1;
|
||||
}
|
||||
93.54838709677419% {
|
||||
stroke-opacity: 1;
|
||||
}
|
||||
100% {
|
||||
stroke-opacity: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
10
src/components/README.md
Normal file
10
src/components/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
## Components
|
||||
|
||||
Components in this dir will be auto-registered and on-demand, powered by [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components).
|
||||
|
||||
|
||||
### Icons
|
||||
|
||||
You can use icons from almost any icon sets by the power of [Iconify](https://iconify.design/).
|
||||
|
||||
It will only bundle the icons you use. Check out [`unplugin-icons`](https://github.com/antfu/unplugin-icons) for more details.
|
||||
3
src/composables/dark.ts
Normal file
3
src/composables/dark.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
// these APIs are auto-imported from @vueuse/core
|
||||
export const isDark = useDark()
|
||||
export const toggleDark = useToggle(isDark)
|
||||
1
src/composables/index.ts
Normal file
1
src/composables/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './dark'
|
||||
24
src/layouts/404.vue
Normal file
24
src/layouts/404.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<script setup lang="ts">
|
||||
const router = useRouter()
|
||||
const { t } = useI18n()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Navbar />
|
||||
<main class="px-4 py-10 text-center text-fly-600 dark:text-gray-200">
|
||||
<div>
|
||||
<p class="text-4xl">
|
||||
<carbon-warning class="inline-block" />
|
||||
</p>
|
||||
</div>
|
||||
<router-view />
|
||||
<div>
|
||||
<button
|
||||
class="btn m-3 text-sm mt-8"
|
||||
@click="router.go(-2)"
|
||||
>
|
||||
{{ t('button.back') }}
|
||||
</button>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
14
src/layouts/README.md
Normal file
14
src/layouts/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
## Layouts
|
||||
|
||||
Vue components in this dir are used as layouts.
|
||||
|
||||
By default, `default.vue` will be used unless an alternative is specified in the route meta.
|
||||
|
||||
With [`vite-plugin-pages`](https://github.com/hannoeru/vite-plugin-pages) and [`vite-plugin-vue-layouts`](https://github.com/JohnCampionJr/vite-plugin-vue-layouts), you can specify the layout in the page's SFCs like this:
|
||||
|
||||
```html
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: home
|
||||
</route>
|
||||
```
|
||||
10
src/layouts/default.vue
Normal file
10
src/layouts/default.vue
Normal file
@@ -0,0 +1,10 @@
|
||||
<template>
|
||||
<Navbar />
|
||||
<main class="px-4 py-10 text-gray-700 dark:text-gray-200">
|
||||
<router-view />
|
||||
<Footer class="text-center" />
|
||||
<div class="mt-5 mx-auto text-center opacity-25 text-sm">
|
||||
[Default Layout]
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
6
src/layouts/home.vue
Normal file
6
src/layouts/home.vue
Normal file
@@ -0,0 +1,6 @@
|
||||
<template>
|
||||
<Navbar />
|
||||
<main class="px-4 py-10 text-center text-gray-700 dark:text-gray-200">
|
||||
<router-view />
|
||||
</main>
|
||||
</template>
|
||||
8
src/layouts/posts.vue
Normal file
8
src/layouts/posts.vue
Normal file
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<Navbar />
|
||||
<main class="px-4 py-10 text-left text-gray-700 dark:text-gray-200">
|
||||
<article class="prose m-auto">
|
||||
<router-view />
|
||||
</article>
|
||||
</main>
|
||||
</template>
|
||||
8
src/layouts/projects.vue
Normal file
8
src/layouts/projects.vue
Normal file
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<Navbar />
|
||||
<main class="px-4 py-10 text-left text-gray-700 dark:text-gray-200">
|
||||
<article class="prose m-auto">
|
||||
<router-view />
|
||||
</article>
|
||||
</main>
|
||||
</template>
|
||||
27
src/main.ts
Normal file
27
src/main.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
// register vue composition api globally
|
||||
import { ViteSSG } from 'vite-ssg'
|
||||
import generatedRoutes from 'virtual:generated-pages'
|
||||
import { setupLayouts } from 'virtual:generated-layouts'
|
||||
import App from './App.vue'
|
||||
|
||||
// windicss layers
|
||||
import 'virtual:windi-base.css'
|
||||
import 'virtual:windi-components.css'
|
||||
// your custom styles here
|
||||
import './styles/main.css'
|
||||
// windicss utilities should be the last style import
|
||||
import 'virtual:windi-utilities.css'
|
||||
// windicss devtools support (dev only)
|
||||
import 'virtual:windi-devtools'
|
||||
|
||||
const routes = setupLayouts(generatedRoutes)
|
||||
|
||||
// https://github.com/antfu/vite-ssg
|
||||
export const createApp = ViteSSG(
|
||||
App,
|
||||
{ routes, base: import.meta.env.BASE_URL },
|
||||
(ctx) => {
|
||||
// install all modules under `modules/`
|
||||
Object.values(import.meta.globEager('./modules/*.ts')).map(i => i.install?.(ctx))
|
||||
},
|
||||
)
|
||||
11
src/modules/README.md
Normal file
11
src/modules/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## Modules
|
||||
|
||||
A custom user module system. Place a `.ts` file with the following template, it will be installed automatically.
|
||||
|
||||
```ts
|
||||
import { UserModule } from '~/types'
|
||||
|
||||
export const install: UserModule = ({ app, router, isClient }) => {
|
||||
// do something
|
||||
}
|
||||
```
|
||||
25
src/modules/i18n.ts
Normal file
25
src/modules/i18n.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { createI18n } from 'vue-i18n'
|
||||
import type { UserModule } from '~/types'
|
||||
|
||||
// Import i18n resources
|
||||
// https://vitejs.dev/guide/features.html#glob-import
|
||||
//
|
||||
// Don't need this? Try vitesse-lite: https://github.com/antfu/vitesse-lite
|
||||
const messages = Object.fromEntries(
|
||||
Object.entries(
|
||||
import.meta.globEager('../../locales/*.y(a)?ml'))
|
||||
.map(([key, value]) => {
|
||||
const yaml = key.endsWith('.yaml')
|
||||
return [key.slice(14, yaml ? -5 : -4), value.default]
|
||||
}),
|
||||
)
|
||||
|
||||
export const install: UserModule = ({ app }) => {
|
||||
const i18n = createI18n({
|
||||
legacy: false,
|
||||
locale: 'en',
|
||||
messages,
|
||||
})
|
||||
|
||||
app.use(i18n)
|
||||
}
|
||||
9
src/modules/nprogress.ts
Normal file
9
src/modules/nprogress.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import NProgress from 'nprogress'
|
||||
import type { UserModule } from '~/types'
|
||||
|
||||
export const install: UserModule = ({ isClient, router }) => {
|
||||
if (isClient) {
|
||||
router.beforeEach(() => { NProgress.start() })
|
||||
router.afterEach(() => { NProgress.done() })
|
||||
}
|
||||
}
|
||||
17
src/modules/pinia.ts
Normal file
17
src/modules/pinia.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { createPinia } from 'pinia'
|
||||
import type { UserModule } from '~/types'
|
||||
|
||||
// Setup Pinia
|
||||
// https://pinia.esm.dev/
|
||||
export const install: UserModule = ({ isClient, initialState, app }) => {
|
||||
const pinia = createPinia()
|
||||
app.use(pinia)
|
||||
// Refer to
|
||||
// https://github.com/antfu/vite-ssg/blob/main/README.md#state-serialization
|
||||
// for other serialization strategies.
|
||||
if (isClient)
|
||||
pinia.state.value = (initialState.pinia) || {}
|
||||
|
||||
else
|
||||
initialState.pinia = pinia.state.value
|
||||
}
|
||||
12
src/modules/pwa.ts
Normal file
12
src/modules/pwa.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type { UserModule } from '~/types'
|
||||
|
||||
// https://github.com/antfu/vite-plugin-pwa#automatic-reload-when-new-content-available
|
||||
export const install: UserModule = ({ isClient, router }) => {
|
||||
if (!isClient)
|
||||
return
|
||||
|
||||
router.isReady().then(async() => {
|
||||
const { registerSW } = await import('virtual:pwa-register')
|
||||
registerSW({ immediate: true })
|
||||
})
|
||||
}
|
||||
20
src/pages/README.md
Normal file
20
src/pages/README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
## File-based Routing
|
||||
|
||||
Routes will be auto-generated for Vue files in this dir with the same file structure.
|
||||
Check out [`vite-plugin-pages`](https://github.com/hannoeru/vite-plugin-pages) for more details.
|
||||
|
||||
### Path Aliasing
|
||||
|
||||
`~/` is aliased to `./src/` folder.
|
||||
|
||||
For example, instead of having
|
||||
|
||||
```ts
|
||||
import { isDark } from '../../../../composables'
|
||||
```
|
||||
|
||||
now, you can use
|
||||
|
||||
```ts
|
||||
import { isDark } from '~/composables'
|
||||
```
|
||||
14
src/pages/[...all].vue
Normal file
14
src/pages/[...all].vue
Normal file
@@ -0,0 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
const { t } = useI18n()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
{{ t('not-found') }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: 404
|
||||
</route>
|
||||
23
src/pages/about.md
Normal file
23
src/pages/about.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: About
|
||||
---
|
||||
|
||||
<div class="text-center">
|
||||
<!-- You can use Vue components inside markdown -->
|
||||
<carbon-dicom-overlay class="text-4xl -mb-6 m-auto" />
|
||||
<h3>About</h3>
|
||||
</div>
|
||||
|
||||
[Vitesse](https://github.com/antfu/vitesse) is an opinionated [Vite](https://github.com/vitejs/vite) starter template made by [@antfu](https://github.com/antfu) for mocking apps swiftly. With **file-based routing**, **components auto importing**, **markdown support**, I18n, PWA and uses **WindiCSS** for UI.
|
||||
|
||||
```js
|
||||
// syntax highlighting example
|
||||
function vitesse() {
|
||||
const foo = 'bar'
|
||||
console.log(foo)
|
||||
}
|
||||
```
|
||||
|
||||
Check out the [GitHub repo](https://github.com/antfu/vitesse) for more details.
|
||||
|
||||
|
||||
37
src/pages/index.vue
Normal file
37
src/pages/index.vue
Normal file
@@ -0,0 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1 class="text-7xl my-4">
|
||||
Hi there,<br> I'm <span class="font-bold text-fly-600 dark:text-fly-500">Flycro</span>
|
||||
</h1>
|
||||
<p class="text-4xl my-9">
|
||||
Just another Username in the vast sea of the web.
|
||||
</p>
|
||||
<p class="mt-8 text-xl">
|
||||
My interests fluctuate over a wide span of topics, but I'm most interested in web development, design, and tabletop gaming.
|
||||
</p>
|
||||
<p class="text-xl mt-4">
|
||||
However, perfecting my skills is a long journey. I'm currently working on a few projects and still have a lot to learn.
|
||||
<br>
|
||||
I'm not ready to share my work just yet, but I'm open to discussing new projects and opportunities.
|
||||
<br>
|
||||
But nontheless, I will write about my journey here.
|
||||
</p>
|
||||
<p class="text-xl mt-4">
|
||||
No matter what I pour my heart, mind and soul into, the goal is to find a way communicate my thoughts and feelings with you.
|
||||
</p>
|
||||
<p class="text-xl mt-4">
|
||||
This is a place where I share my thoughts, ideas, projects and what inspires me. I hope you enjoy it.
|
||||
</p>
|
||||
|
||||
<div class="py-4" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: home
|
||||
</route>
|
||||
48
src/pages/posts/[slug].vue
Normal file
48
src/pages/posts/[slug].vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<route>
|
||||
{
|
||||
meta:{
|
||||
layout: 'posts'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<div v-if="post && Object.keys(post.currentPost).length !== 0">
|
||||
<Motion
|
||||
:initial="{ opacity: 0 }"
|
||||
:animate="{ opacity: 1}"
|
||||
:transition="{ duration: 0.5, easing: 'ease-in-out' }"
|
||||
>
|
||||
<div class="text-3xl my-2">
|
||||
<span class="font-bold text-fly-600 dark:text-fly-500">|</span>
|
||||
<span class="align-middle mx-2">{{ post.currentPost.title }}</span>
|
||||
</div>
|
||||
<div v-html="post.currentPost.body" />
|
||||
</Motion>
|
||||
</div>
|
||||
<router-link class="no-underline dark:hover:text-fly-500" :to="`/posts/`">
|
||||
Back to Posts
|
||||
</router-link>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Motion } from 'motion/vue'
|
||||
import { usePostStore } from '~/stores/post'
|
||||
|
||||
const post = usePostStore()
|
||||
|
||||
const props = defineProps<{ slug: string }>()
|
||||
post.getCurrentPostBySlug(props.slug)
|
||||
|
||||
useHead({
|
||||
title: computed(() => `${post.currentPost.title} – Flycro`),
|
||||
meta: [
|
||||
{ name: 'description', content: 'Posts about thoughts, projects and what inspires me.' },
|
||||
],
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
78
src/pages/posts/index.vue
Normal file
78
src/pages/posts/index.vue
Normal file
@@ -0,0 +1,78 @@
|
||||
<route>
|
||||
{
|
||||
meta:{
|
||||
layout: 'posts'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1>Blog</h1>
|
||||
<div>
|
||||
<ul v-if="post.postList && post.loading === false" key="test" class="list-none">
|
||||
<Motion
|
||||
:initial="{ opacity: 0 }"
|
||||
:animate="{ opacity: 1}"
|
||||
:transition="{ duration: 0.5, easing: 'ease-in-out' }"
|
||||
>
|
||||
<router-link v-for="p in post.postList" :key="p.slug" class="no-underline dark:hover:text-fly-500" :to="`/posts/${p.slug}`">
|
||||
<li>
|
||||
<div class="text-xl">
|
||||
{{ p.title }}
|
||||
</div>
|
||||
<div class="flex justify-start flex-row">
|
||||
<div class="text-xs">
|
||||
{{ convertDate(p.date_created) }}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</router-link>
|
||||
</Motion>
|
||||
</ul>
|
||||
|
||||
<Motion
|
||||
:initial="{ opacity: 0 }"
|
||||
:animate="{ opacity: 1}"
|
||||
:transition="{ duration: 0.5, easing: 'ease-in-out' }"
|
||||
>
|
||||
<div v-if="post.loading === false && post.postList.length === 0" class="text-xl">
|
||||
No Posts found
|
||||
</div>
|
||||
</Motion>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Motion } from 'motion/vue'
|
||||
import type { Ref } from 'vue'
|
||||
import dayjs from 'dayjs'
|
||||
import { usePostStore } from '~/stores/post'
|
||||
|
||||
useHead({
|
||||
title: 'Blog – Flycro',
|
||||
meta: [
|
||||
{ name: 'description', content: 'Posts about thoughts, projects and what inspires me.' },
|
||||
],
|
||||
})
|
||||
|
||||
const post = usePostStore()
|
||||
const show = ref(false)
|
||||
|
||||
function convertDate(date: string): string {
|
||||
return dayjs(date).format('DD. MMMM YYYY')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
post.fetchPosts()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
article.prose.m-auto div div ul.list-none a.no-underline
|
||||
{
|
||||
@apply no-underline
|
||||
}
|
||||
</style>
|
||||
48
src/pages/projects/index.vue
Normal file
48
src/pages/projects/index.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<route>
|
||||
{
|
||||
meta:{
|
||||
layout: 'projects'
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1>Projects</h1>
|
||||
<p>Nothing to see here yet.</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Motion } from 'motion/vue'
|
||||
import type { Ref } from 'vue'
|
||||
|
||||
import dayjs from 'dayjs'
|
||||
import { usePostStore } from '~/stores/post'
|
||||
|
||||
useHead({
|
||||
title: computed(() => 'Projects – Flycro'),
|
||||
meta: [
|
||||
{ name: 'description', content: 'Some of my projects that I am happy to share with you.' },
|
||||
],
|
||||
})
|
||||
|
||||
const post = usePostStore()
|
||||
const show = ref(false)
|
||||
|
||||
function convertDate(date: string): string {
|
||||
return dayjs(date).format('DD. MMMM YYYY')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
post.fetchPosts()
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
article.prose.m-auto div div ul.list-none a.no-underline
|
||||
{
|
||||
@apply no-underline
|
||||
}
|
||||
</style>
|
||||
15
src/shims.d.ts
vendored
Normal file
15
src/shims.d.ts
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
declare interface Window {
|
||||
// extend the window
|
||||
}
|
||||
|
||||
// with vite-plugin-md, markdowns can be treat as Vue components
|
||||
declare module '*.md' {
|
||||
import type { ComponentOptions } from 'vue'
|
||||
const component: ComponentOptions
|
||||
export default component
|
||||
}
|
||||
|
||||
declare module '*.vue' {
|
||||
import Vue from 'vue'
|
||||
export default Vue
|
||||
}
|
||||
80
src/stores/post.ts
Normal file
80
src/stores/post.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import { acceptHMRUpdate, defineStore } from 'pinia'
|
||||
import type { Ref } from 'vue'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
import Prism from 'markdown-it-prism'
|
||||
import LinkAttributes from 'markdown-it-link-attributes'
|
||||
import type { Error, Post } from '~/types'
|
||||
|
||||
export const usePostStore = defineStore('post', () => {
|
||||
const postList = ref([]) as Ref<Post[]>
|
||||
const currentPost = ref({}) as Ref<Post>
|
||||
const errors = ref([]) as Ref<Error[]>
|
||||
const loading = ref(false) as Ref<boolean>
|
||||
const initialLoad = ref(false) as Ref<boolean>
|
||||
const router = useRouter()
|
||||
|
||||
async function fetchPosts() {
|
||||
postList.value = []
|
||||
loading.value = true
|
||||
const result = await fetch('https://api.flycro.me/items/Post')
|
||||
if (!result.ok) errors.value.push({ message: 'Failed to fetch posts' })
|
||||
const data = await result.json()
|
||||
data.data.forEach((item) => {
|
||||
postList.value.push({
|
||||
title: item.title,
|
||||
slug: item.slug,
|
||||
body: item.body,
|
||||
tags: item.tags,
|
||||
user_created: item.user_created,
|
||||
date_created: item.date_created,
|
||||
status: item.status,
|
||||
})
|
||||
})
|
||||
loading.value = false
|
||||
initialLoad.value = true
|
||||
}
|
||||
|
||||
async function getCurrentPostBySlug(slug: string) {
|
||||
if (postList.value.length === 0) await fetchPosts()
|
||||
const post = postList.value.find(item => item.slug === slug)
|
||||
if (post) {
|
||||
currentPost.value = post
|
||||
const md = new MarkdownIt()
|
||||
md.use(Prism)
|
||||
md.use(LinkAttributes, {
|
||||
pattern: /^https?:\/\//,
|
||||
attrs: {
|
||||
target: '_blank',
|
||||
rel: 'noopener',
|
||||
},
|
||||
})
|
||||
currentPost.value.body = md.render(currentPost.value.body)
|
||||
}
|
||||
if (currentPost.value && Object.keys(currentPost.value).length === 0 && initialLoad.value) router.push('/404')
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the current name of the user and saves the one that was used
|
||||
* before.
|
||||
*
|
||||
* @param name - new name to set
|
||||
*/
|
||||
/* function setNewName(name: string) {
|
||||
if (savedName.value)
|
||||
previousNames.value.add(savedName.value)
|
||||
|
||||
savedName.value = name
|
||||
} */
|
||||
|
||||
return {
|
||||
fetchPosts,
|
||||
getCurrentPostBySlug,
|
||||
loading,
|
||||
initialLoad,
|
||||
postList,
|
||||
currentPost,
|
||||
}
|
||||
})
|
||||
|
||||
if (import.meta.hot)
|
||||
import.meta.hot.accept(acceptHMRUpdate(usePostStore, import.meta.hot))
|
||||
219
src/styles/main.css
Normal file
219
src/styles/main.css
Normal file
@@ -0,0 +1,219 @@
|
||||
@import './markdown.css';
|
||||
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html{
|
||||
@apply bg-gray-100;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
background: #121212;
|
||||
}
|
||||
|
||||
#nprogress {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#nprogress .bar {
|
||||
@apply bg-fly-500 opacity-75;
|
||||
|
||||
position: fixed;
|
||||
z-index: 1031;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
@apply px-4 py-1 rounded inline-block
|
||||
bg-fly-600 text-white cursor-pointer
|
||||
hover:bg-fly-700
|
||||
disabled:cursor-default disabled:bg-gray-600 disabled:opacity-50;
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
@apply inline-block cursor-pointer select-none
|
||||
opacity-75 transition duration-200 ease-in-out
|
||||
hover:opacity-100 hover:text-fly-600;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.fade-enter-active, .fade-leave-active {
|
||||
transition: opacity .5s;
|
||||
}
|
||||
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.list-enter-active,
|
||||
.list-leave-active {
|
||||
transition: all 1s ease;
|
||||
}
|
||||
.list-enter-from,
|
||||
.list-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
|
||||
/* titillium-web-200 - latin */
|
||||
@font-face {
|
||||
font-family: 'Titillium Web';
|
||||
font-style: normal;
|
||||
font-weight: 200;
|
||||
src: url('/assets/fonts/titillium-web-v10-latin-200.eot'); /* IE9 Compat Modes */
|
||||
src: local(''),
|
||||
url('/assets/fonts/titillium-web-v10-latin-200.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('/assets/fonts/titillium-web-v10-latin-200.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-200.woff') format('woff'), /* Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-200.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('/assets/fonts/titillium-web-v10-latin-200.svg#TitilliumWeb') format('svg'); /* Legacy iOS */
|
||||
}
|
||||
|
||||
/* titillium-web-200italic - latin */
|
||||
@font-face {
|
||||
font-family: 'Titillium Web';
|
||||
font-style: italic;
|
||||
font-weight: 200;
|
||||
src: url('/assets/fonts/titillium-web-v10-latin-200italic.eot'); /* IE9 Compat Modes */
|
||||
src: local(''),
|
||||
url('/assets/fonts/titillium-web-v10-latin-200italic.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('/assets/fonts/titillium-web-v10-latin-200italic.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-200italic.woff') format('woff'), /* Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-200italic.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('/assets/fonts/titillium-web-v10-latin-200italic.svg#TitilliumWeb') format('svg'); /* Legacy iOS */
|
||||
}
|
||||
|
||||
/* titillium-web-300 - latin */
|
||||
@font-face {
|
||||
font-family: 'Titillium Web';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: url('/assets/fonts/titillium-web-v10-latin-300.eot'); /* IE9 Compat Modes */
|
||||
src: local(''),
|
||||
url('/assets/fonts/titillium-web-v10-latin-300.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('/assets/fonts/titillium-web-v10-latin-300.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-300.woff') format('woff'), /* Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-300.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('/assets/fonts/titillium-web-v10-latin-300.svg#TitilliumWeb') format('svg'); /* Legacy iOS */
|
||||
}
|
||||
|
||||
/* titillium-web-300italic - latin */
|
||||
@font-face {
|
||||
font-family: 'Titillium Web';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
src: url('/assets/fonts/titillium-web-v10-latin-300italic.eot'); /* IE9 Compat Modes */
|
||||
src: local(''),
|
||||
url('/assets/fonts/titillium-web-v10-latin-300italic.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('/assets/fonts/titillium-web-v10-latin-300italic.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-300italic.woff') format('woff'), /* Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-300italic.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('/assets/fonts/titillium-web-v10-latin-300italic.svg#TitilliumWeb') format('svg'); /* Legacy iOS */
|
||||
}
|
||||
|
||||
/* titillium-web-regular - latin */
|
||||
@font-face {
|
||||
font-family: 'Titillium Web';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url('/assets/fonts/titillium-web-v10-latin-regular.eot'); /* IE9 Compat Modes */
|
||||
src: local(''),
|
||||
url('/assets/fonts/titillium-web-v10-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('/assets/fonts/titillium-web-v10-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-regular.woff') format('woff'), /* Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('/assets/fonts/titillium-web-v10-latin-regular.svg#TitilliumWeb') format('svg'); /* Legacy iOS */
|
||||
}
|
||||
|
||||
/* titillium-web-italic - latin */
|
||||
@font-face {
|
||||
font-family: 'Titillium Web';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: url('/assets/fonts/titillium-web-v10-latin-italic.eot'); /* IE9 Compat Modes */
|
||||
src: local(''),
|
||||
url('/assets/fonts/titillium-web-v10-latin-italic.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('/assets/fonts/titillium-web-v10-latin-italic.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-italic.woff') format('woff'), /* Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-italic.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('/assets/fonts/titillium-web-v10-latin-italic.svg#TitilliumWeb') format('svg'); /* Legacy iOS */
|
||||
}
|
||||
|
||||
/* titillium-web-600 - latin */
|
||||
@font-face {
|
||||
font-family: 'Titillium Web';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: url('/assets/fonts/titillium-web-v10-latin-600.eot'); /* IE9 Compat Modes */
|
||||
src: local(''),
|
||||
url('/assets/fonts/titillium-web-v10-latin-600.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('/assets/fonts/titillium-web-v10-latin-600.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-600.woff') format('woff'), /* Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-600.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('/assets/fonts/titillium-web-v10-latin-600.svg#TitilliumWeb') format('svg'); /* Legacy iOS */
|
||||
}
|
||||
|
||||
/* titillium-web-600italic - latin */
|
||||
@font-face {
|
||||
font-family: 'Titillium Web';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
src: url('/assets/fonts/titillium-web-v10-latin-600italic.eot'); /* IE9 Compat Modes */
|
||||
src: local(''),
|
||||
url('/assets/fonts/titillium-web-v10-latin-600italic.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('/assets/fonts/titillium-web-v10-latin-600italic.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-600italic.woff') format('woff'), /* Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-600italic.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('/assets/fonts/titillium-web-v10-latin-600italic.svg#TitilliumWeb') format('svg'); /* Legacy iOS */
|
||||
}
|
||||
|
||||
/* titillium-web-700 - latin */
|
||||
@font-face {
|
||||
font-family: 'Titillium Web';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: url('/assets/fonts/titillium-web-v10-latin-700.eot'); /* IE9 Compat Modes */
|
||||
src: local(''),
|
||||
url('/assets/fonts/titillium-web-v10-latin-700.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('/assets/fonts/titillium-web-v10-latin-700.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-700.woff') format('woff'), /* Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-700.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('/assets/fonts/titillium-web-v10-latin-700.svg#TitilliumWeb') format('svg'); /* Legacy iOS */
|
||||
}
|
||||
|
||||
/* titillium-web-700italic - latin */
|
||||
@font-face {
|
||||
font-family: 'Titillium Web';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: url('/assets/fonts/titillium-web-v10-latin-700italic.eot'); /* IE9 Compat Modes */
|
||||
src: local(''),
|
||||
url('/assets/fonts/titillium-web-v10-latin-700italic.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('/assets/fonts/titillium-web-v10-latin-700italic.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-700italic.woff') format('woff'), /* Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-700italic.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('/assets/fonts/titillium-web-v10-latin-700italic.svg#TitilliumWeb') format('svg'); /* Legacy iOS */
|
||||
}
|
||||
|
||||
/* titillium-web-900 - latin */
|
||||
@font-face {
|
||||
font-family: 'Titillium Web';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
src: url('/assets/fonts/titillium-web-v10-latin-900.eot'); /* IE9 Compat Modes */
|
||||
src: local(''),
|
||||
url('/assets/fonts/titillium-web-v10-latin-900.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('/assets/fonts/titillium-web-v10-latin-900.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-900.woff') format('woff'), /* Modern Browsers */
|
||||
url('/assets/fonts/titillium-web-v10-latin-900.ttf') format('truetype'), /* Safari, Android, iOS */
|
||||
url('/assets/fonts/titillium-web-v10-latin-900.svg#TitilliumWeb') format('svg'); /* Legacy iOS */
|
||||
}
|
||||
|
||||
58
src/styles/markdown.css
Normal file
58
src/styles/markdown.css
Normal file
@@ -0,0 +1,58 @@
|
||||
/* https://github.com/antfu/prism-theme-vars */
|
||||
@import 'prism-theme-vars/base.css';
|
||||
|
||||
.prose {
|
||||
--prism-font-family: 'Titillium Web', monospace;
|
||||
}
|
||||
|
||||
.prose img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
html:not(.dark) .prose {
|
||||
--prism-foreground: #393a34;
|
||||
--prism-background: #fbfbfb;
|
||||
--prism-comment: #a0ada0;
|
||||
--prism-string: #b56959;
|
||||
--prism-literal: #2f8a89;
|
||||
--prism-number: #296aa3;
|
||||
--prism-keyword: #1c6b48;
|
||||
--prism-function: #6c7834;
|
||||
--prism-boolean: #1c6b48;
|
||||
--prism-constant: #a65e2b;
|
||||
--prism-deleted: #a14f55;
|
||||
--prism-class: #2993a3;
|
||||
--prism-builtin: #ab5959;
|
||||
--prism-property: #b58451;
|
||||
--prism-namespace: #b05a78;
|
||||
--prism-punctuation: #8e8f8b;
|
||||
--prism-decorator: #bd8f8f;
|
||||
--prism-regex: #ab5e3f;
|
||||
--prism-json-property: #698c96;
|
||||
}
|
||||
|
||||
html.dark .prose {
|
||||
--prism-foreground: #d4cfbf;
|
||||
--prism-background: #151515;
|
||||
--prism-comment: #758575;
|
||||
--prism-string: #d48372;
|
||||
--prism-literal: #429988;
|
||||
--prism-keyword: #4d9375;
|
||||
--prism-boolean: #1c6b48;
|
||||
--prism-number: #6394bf;
|
||||
--prism-variable: #c2b36e;
|
||||
--prism-function: #a1b567;
|
||||
--prism-deleted: #a14f55;
|
||||
--prism-class: #54b1bf;
|
||||
--prism-builtin: #e0a569;
|
||||
--prism-property: #dd8e6e;
|
||||
--prism-namespace: #db889a;
|
||||
--prism-punctuation: #858585;
|
||||
--prism-decorator: #bd8f8f;
|
||||
--prism-regex: #ab5e3f;
|
||||
--prism-json-property: #6b8b9e;
|
||||
--prism-line-number: #888888;
|
||||
--prism-line-number-gutter: #eeeeee;
|
||||
--prism-line-highlight-background: #444444;
|
||||
--prism-selection-background: #444444;
|
||||
}
|
||||
17
src/types.ts
Normal file
17
src/types.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import type { ViteSSGContext } from 'vite-ssg'
|
||||
|
||||
export type UserModule = (ctx: ViteSSGContext) => void
|
||||
|
||||
export interface Post {
|
||||
title: string
|
||||
slug: string
|
||||
body: string
|
||||
tags: string[]
|
||||
user_created: string
|
||||
date_created: string
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface Error {
|
||||
message: string
|
||||
}
|
||||
Reference in New Issue
Block a user