Set up Nuxt config and routing shell
Agent-Logs-Url: https://github.com/hykilpikonna/corner/sessions/5ad4b623-9a6b-480e-80fa-d83eee774f01 Co-authored-by: hykilpikonna <22280294+hykilpikonna@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
1f385afee0
commit
12c0dc46bf
+3
-1
@@ -1,7 +1,9 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
/.nuxt
|
||||
/.output
|
||||
/.nitro
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
|
||||
```sh
|
||||
# Project setup
|
||||
yarn install
|
||||
npm install
|
||||
|
||||
# Compiles and hot-reloads for development
|
||||
yarn serve
|
||||
npm run dev
|
||||
|
||||
# Generate static site
|
||||
npm run generate
|
||||
```
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||
<meta content="width=device-width,initial-scale=1.0" name="viewport">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/icons/favicon-16x16.png">
|
||||
<title>Home</title>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js" integrity="sha512-uto9mlQzrs59VwILcLiRYeLKPPbS/bT71da/OEBYEwcdNUk8jYIy+D176RYoop1Da+f9mvkYrmj5MCLZWEtQuA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
|
||||
<style>
|
||||
/* Load this last */
|
||||
#nav * {
|
||||
transition: all .25s ease
|
||||
}
|
||||
</style>
|
||||
</html>
|
||||
@@ -0,0 +1,30 @@
|
||||
export default defineNuxtConfig({
|
||||
srcDir: 'src/',
|
||||
ssr: true,
|
||||
modules: ['@unocss/nuxt'],
|
||||
css: ['@fortawesome/fontawesome-free/css/all.min.css'],
|
||||
app: {
|
||||
head: {
|
||||
script: [
|
||||
{
|
||||
src: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js',
|
||||
integrity: 'sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==',
|
||||
crossorigin: 'anonymous',
|
||||
referrerpolicy: 'no-referrer'
|
||||
},
|
||||
{
|
||||
src: 'https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js',
|
||||
integrity: 'sha512-uto9mlQzrs59VwILcLiRYeLKPPbS/bT71da/OEBYEwcdNUk8jYIy+D176RYoop1Da+f9mvkYrmj5MCLZWEtQuA==',
|
||||
crossorigin: 'anonymous',
|
||||
referrerpolicy: 'no-referrer'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
nitro: {
|
||||
prerender: {
|
||||
crawlLinks: true,
|
||||
routes: ['/', '/about', '/life', '/blog', '/photo', '/others', '/kitchen-menu', '/friends', '/projects']
|
||||
}
|
||||
}
|
||||
})
|
||||
+34
-36
@@ -1,38 +1,36 @@
|
||||
{
|
||||
"name": "home-page",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"serve": "vite",
|
||||
"build": "vue-tsc --noEmit && vite build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.6.0",
|
||||
"animsition": "^4.0.2",
|
||||
"core-js": "^3.37.1",
|
||||
"emoji-regex": "^10.3.0",
|
||||
"linkify-urls": "^4.1.0",
|
||||
"lxgw-wenkai-webfont": "^1.7.0",
|
||||
"marked": "^4.3.0",
|
||||
"moment": "^2.30.1",
|
||||
"tg-blog": "^1.1.7",
|
||||
"vue": "^3.4.35",
|
||||
"vue-i18n": "^11.1.12",
|
||||
"vue-router": "^4.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jquery": "^3.5.30",
|
||||
"@types/jqueryui": "^1.12.23",
|
||||
"@types/marked": "^4.3.2",
|
||||
"@types/node": "^24.9.1",
|
||||
"@vitejs/plugin-vue": "^6.0.1",
|
||||
"eslint": "^9.8.0",
|
||||
"sass": "^1.77.8",
|
||||
"tslib": "^2.6.3",
|
||||
"typescript": "^5.5.4",
|
||||
"unocss": "^66.5.4",
|
||||
"vite": "^7.1.12",
|
||||
"vue-tsc": "3.1.1"
|
||||
}
|
||||
"name": "home-page",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "nuxt dev",
|
||||
"build": "nuxt build",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"typecheck": "nuxt typecheck"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.6.0",
|
||||
"animsition": "^4.0.2",
|
||||
"emoji-regex": "^10.3.0",
|
||||
"linkify-urls": "^4.1.0",
|
||||
"lxgw-wenkai-webfont": "^1.7.0",
|
||||
"marked": "^4.3.0",
|
||||
"moment": "^2.30.1",
|
||||
"tg-blog": "^1.1.7",
|
||||
"vue-i18n": "^11.1.12",
|
||||
"nuxt": "^4.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jquery": "^3.5.30",
|
||||
"@types/jqueryui": "^1.12.23",
|
||||
"@types/marked": "^4.3.2",
|
||||
"@types/node": "^24.9.1",
|
||||
"eslint": "^9.8.0",
|
||||
"sass": "^1.77.8",
|
||||
"tslib": "^2.6.3",
|
||||
"typescript": "^5.5.4",
|
||||
"unocss": "^66.5.4",
|
||||
"@unocss/nuxt": "^66.6.8"
|
||||
}
|
||||
}
|
||||
|
||||
-266
@@ -1,266 +0,0 @@
|
||||
<template>
|
||||
<div id="nav" class="fbox-v"
|
||||
:class="(currentRoute) + ' ' + (menuOpen ? 'open' : '')"
|
||||
v-if="currentRoute !== 'colorpicker'">
|
||||
<div id="menu" @click="showMenu"><i class="fas fa-bars"></i></div>
|
||||
|
||||
<div id="items" class="fbox-v">
|
||||
<router-link class="router-link" :ref="setNavRef('others')" to="/others">{{ $t('nav.others') }}</router-link>
|
||||
<div class="dot">·</div>
|
||||
<router-link class="router-link" :ref="setNavRef('photo')" to="/photo">{{ $t('nav.photo') }}</router-link>
|
||||
<div class="dot">·</div>
|
||||
<router-link class="router-link" :ref="setNavRef('blog')" to="/blog">{{ $t('nav.blog') }}</router-link>
|
||||
<div class="dot">·</div>
|
||||
<router-link class="router-link" :ref="setNavRef('life')" to="/life">{{ $t('nav.life') }}</router-link>
|
||||
<div class="dot">·</div>
|
||||
<router-link class="router-link" :ref="setNavRef('about')" to="/about">{{ $t('nav.about') }}</router-link>
|
||||
<div class="dot">·</div>
|
||||
<router-link class="router-link" :ref="setNavRef('home')" to="/">
|
||||
<svg focusable="false" data-prefix="fal" data-icon="house-night" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" class="svg-inline--fa fa-house-night fa-w-20"><path fill="currentColor" d="M112,224a111.5,111.5,0,0,0,87-41.45,20.51,20.51,0,0,0-19.75-33.08A59.2,59.2,0,0,1,138.84,39.85a20.3,20.3,0,0,0,10.07-21.27,20.26,20.26,0,0,0-16.47-16.7A136,136,0,0,0,112,0a112,112,0,0,0,0,224ZM97.78,33.27a91.21,91.21,0,0,0,54.47,147.9A80,80,0,1,1,97.78,33.27Zm97.15,35.51,39.72,16.56,16.56,39.72a5.33,5.33,0,0,0,9.55,0l16.56-39.72L317,68.78a5.33,5.33,0,0,0,0-9.54L277.32,42.68,260.76,3a5.33,5.33,0,0,0-9.55,0L234.65,42.68,194.93,59.24a5.34,5.34,0,0,0,0,9.54ZM157,379.24l-39.72-16.57L100.76,323a5.34,5.34,0,0,0-9.55,0L74.65,362.67,34.93,379.24a5.34,5.34,0,0,0,0,9.54l39.72,16.56,16.56,39.72a5.33,5.33,0,0,0,9.55,0l16.56-39.72L157,388.78a5.33,5.33,0,0,0,0-9.54Zm179-101.9v85.33A21.39,21.39,0,0,0,357.36,384h85.31A21.39,21.39,0,0,0,464,362.67V277.34A21.4,21.4,0,0,0,442.67,256H357.36A21.4,21.4,0,0,0,336,277.34ZM368,288H432v64H368Zm266.49,8L576,244.75V144a16,16,0,0,0-32,0v72.75L410.53,100a16,16,0,0,0-21.07,0l-224,196a16,16,0,0,0,21.07,24.09L224,287.28V464a48.05,48.05,0,0,0,48,48H528a48.06,48.06,0,0,0,48-48V287.28l37.46,32.78A16,16,0,0,0,634.53,296ZM544,464a16,16,0,0,1-16,16H272a16,16,0,0,1-16-16V264a15.94,15.94,0,0,0-.81-4L400,133.27l144,126Z" class=""></path></svg></router-link>
|
||||
</div>
|
||||
|
||||
<div id="nav-bookmark" ref="bookmark" :style="bookmarkCss"></div>
|
||||
<div id="nav-background"></div>
|
||||
|
||||
<img id="meru" src="/meru_256px.png" alt="">
|
||||
</div>
|
||||
|
||||
<router-view/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {nextTick, onMounted, onUnmounted, ref, ComponentPublicInstance} from 'vue';
|
||||
import router from "@/scripts/router";
|
||||
import {RouteLocationNormalized, RouteLocationRaw, useRoute} from "vue-router";
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const currentRoute = ref('')
|
||||
const bookmarkCss = ref('')
|
||||
const lastTop = ref(0)
|
||||
const menuOpen = ref(false)
|
||||
const bookmarkUpdateIntervalId = ref<number | null>(null)
|
||||
const removeAfterEach = ref<(() => void) | null>(null)
|
||||
|
||||
const navRefs = ref<Record<string, Element | ComponentPublicInstance | null>>({})
|
||||
|
||||
const showMenu = (): void => {
|
||||
menuOpen.value = !menuOpen.value
|
||||
|
||||
if (menuOpen.value) setTimeout(() => menuOpen.value = false, 2000)
|
||||
}
|
||||
|
||||
const setNavRef = (name: string) => (el: Element | ComponentPublicInstance | null) => {
|
||||
navRefs.value[name] = el
|
||||
}
|
||||
|
||||
const resolveNavElement = (target: Element | ComponentPublicInstance | null | undefined): Element | null => {
|
||||
if (!target) return null
|
||||
if (target instanceof Element) return target
|
||||
return (target.$el as Element | undefined) ?? null
|
||||
}
|
||||
|
||||
const calculateBookmarkCss = (): void => {
|
||||
const currentLink = resolveNavElement(navRefs.value[currentRoute.value])
|
||||
if (!currentLink) return
|
||||
|
||||
const box = currentLink.getBoundingClientRect()
|
||||
if (box.top === lastTop.value) return
|
||||
lastTop.value = box.top
|
||||
|
||||
const h = box.bottom - box.top
|
||||
const width = Math.round(h / 2) + 8
|
||||
|
||||
bookmarkCss.value = `top: ${box.top - 8}px;` +
|
||||
`border-width: ${width}px 20px ${width}px 50px;`
|
||||
}
|
||||
|
||||
const getRouteBookmark = (to: RouteLocationNormalized): string => {
|
||||
return ((to.meta?.navBookmark ?? to.name) as string).toLowerCase()
|
||||
}
|
||||
|
||||
const updateBookmark = (to: RouteLocationNormalized): void => {
|
||||
nextTick(() => {
|
||||
if (to.name == 'Blog' && Object.keys(to.query).length != 0) return
|
||||
document.title = to.meta.title ? `Aza - ${to.meta.title}` : 'Aza - Home';
|
||||
})
|
||||
|
||||
console.log('AfterEach called', to)
|
||||
currentRoute.value = getRouteBookmark(to)
|
||||
|
||||
calculateBookmarkCss()
|
||||
menuOpen.value = false
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
console.log('Mounted called', route)
|
||||
removeAfterEach.value = router.afterEach(updateBookmark)
|
||||
if (route.name) {
|
||||
currentRoute.value = getRouteBookmark(route as unknown as RouteLocationNormalized)
|
||||
}
|
||||
|
||||
window.addEventListener('resize', calculateBookmarkCss, true)
|
||||
bookmarkUpdateIntervalId.value = window.setInterval(calculateBookmarkCss, 1000)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
removeAfterEach.value?.()
|
||||
window.removeEventListener('resize', calculateBookmarkCss, true)
|
||||
if (bookmarkUpdateIntervalId.value !== null) {
|
||||
window.clearInterval(bookmarkUpdateIntervalId.value)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="sass">
|
||||
@use "css/global"
|
||||
@use "css/animations"
|
||||
|
||||
#nav
|
||||
position: fixed
|
||||
left: 0
|
||||
height: 100%
|
||||
font-size: 1.4em
|
||||
align-items: flex-start
|
||||
|
||||
z-index: 100
|
||||
pointer-events: none
|
||||
|
||||
#menu
|
||||
padding: 5px 10px
|
||||
margin: 15px 10px
|
||||
background-color: rgba(255, 255, 255, 0.49)
|
||||
border-radius: 10px
|
||||
text-shadow: -1px -1px 1px rgba(255,255,255,.1), 1px 1px 1px rgba(0,0,0,.5)
|
||||
filter: drop-shadow(0 0 30px rgb(255, 255, 255))
|
||||
|
||||
z-index: 100
|
||||
pointer-events: auto
|
||||
|
||||
opacity: 0
|
||||
|
||||
#nav-bookmark
|
||||
position: absolute
|
||||
left: 0
|
||||
width: 20px
|
||||
height: 0
|
||||
z-index: 5
|
||||
--bookmark-color: rgb(255, 225, 230)
|
||||
border-color: var(--bookmark-color) transparent var(--bookmark-color) var(--bookmark-color)
|
||||
border-style: solid
|
||||
border-width: 20px
|
||||
|
||||
#items
|
||||
justify-content: flex-end
|
||||
z-index: 10
|
||||
|
||||
.router-link
|
||||
color: rgba(128, 112, 92, 0.71)
|
||||
position: relative
|
||||
|
||||
z-index: 100
|
||||
pointer-events: auto
|
||||
|
||||
.dot
|
||||
content: '·'
|
||||
margin: 20px 0
|
||||
user-select: none
|
||||
|
||||
.router-link, .dot
|
||||
text-decoration: none
|
||||
writing-mode: vertical-rl
|
||||
text-orientation: sideways
|
||||
transform: scale(-1)
|
||||
padding-right: 20px
|
||||
|
||||
#nav-background
|
||||
position: absolute
|
||||
height: 100%
|
||||
width: 100px
|
||||
left: 0
|
||||
$nav-bg-color: #f9f2e0
|
||||
//$nav-bg-color: rgb(255, 230, 214)
|
||||
border-left: 20px solid $nav-bg-color
|
||||
background: linear-gradient(to right, $nav-bg-color, transparent)
|
||||
|
||||
z-index: 4
|
||||
pointer-events: none
|
||||
|
||||
#meru
|
||||
height: 160px
|
||||
|
||||
z-index: 100
|
||||
pointer-events: auto
|
||||
|
||||
svg
|
||||
display: inline-block
|
||||
height: 1em
|
||||
transform: rotate(180deg)
|
||||
*
|
||||
box-sizing: inherit
|
||||
|
||||
// Tablet layout
|
||||
@media screen and (max-width: 800px)
|
||||
#nav #menu
|
||||
opacity: 1
|
||||
|
||||
#nav.home
|
||||
#menu, #nav-background
|
||||
opacity: 0
|
||||
|
||||
#nav:not(.home).open
|
||||
#items, #nav-bookmark, #nav-background, #meru
|
||||
opacity: 1
|
||||
animation: fade-in-left .5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both
|
||||
|
||||
#nav:not(.home)
|
||||
#items, #nav-bookmark, #nav-background, #meru
|
||||
opacity: 0
|
||||
animation: fade-out-left 1s 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both
|
||||
|
||||
// Phone layout
|
||||
@media screen and (max-width: 500px), (max-height: 660px)
|
||||
#app
|
||||
font-size: 14px
|
||||
|
||||
#nav
|
||||
#nav-bookmark
|
||||
width: 10px
|
||||
|
||||
#meru
|
||||
height: 120px
|
||||
|
||||
// Smaller phone layout
|
||||
@media screen and (max-width: 370px)
|
||||
#nav #menu
|
||||
opacity: unset
|
||||
|
||||
#nav.home
|
||||
#menu, #nav-background
|
||||
opacity: unset
|
||||
|
||||
#nav.open
|
||||
#items, #nav-bookmark, #nav-background, #meru
|
||||
opacity: 1
|
||||
animation: fade-in-left .5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both
|
||||
|
||||
#nav
|
||||
#items, #nav-bookmark, #nav-background, #meru
|
||||
opacity: 0
|
||||
animation: fade-out-left 1s 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both
|
||||
|
||||
// Phone Height
|
||||
@media screen and (max-height: 600px)
|
||||
#nav
|
||||
.dot
|
||||
margin: 10px 0
|
||||
|
||||
// Phone Height
|
||||
@media screen and (max-height: 500px)
|
||||
#nav
|
||||
.router-link
|
||||
margin-bottom: 10px
|
||||
|
||||
.dot
|
||||
display: none
|
||||
</style>
|
||||
+273
@@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<div id="nav" class="fbox-v" :class="`${currentRoute} ${menuOpen ? 'open' : ''}`" v-if="currentRoute !== 'colorpicker'">
|
||||
<div id="menu" @click="showMenu"><i class="fas fa-bars"></i></div>
|
||||
|
||||
<div id="items" class="fbox-v">
|
||||
<NuxtLink class="router-link" :ref="setNavRef('others')" to="/others">{{ $t('nav.others') }}</NuxtLink>
|
||||
<div class="dot">·</div>
|
||||
<NuxtLink class="router-link" :ref="setNavRef('photo')" to="/photo">{{ $t('nav.photo') }}</NuxtLink>
|
||||
<div class="dot">·</div>
|
||||
<NuxtLink class="router-link" :ref="setNavRef('blog')" to="/blog">{{ $t('nav.blog') }}</NuxtLink>
|
||||
<div class="dot">·</div>
|
||||
<NuxtLink class="router-link" :ref="setNavRef('life')" to="/life">{{ $t('nav.life') }}</NuxtLink>
|
||||
<div class="dot">·</div>
|
||||
<NuxtLink class="router-link" :ref="setNavRef('about')" to="/about">{{ $t('nav.about') }}</NuxtLink>
|
||||
<div class="dot">·</div>
|
||||
<NuxtLink class="router-link" :ref="setNavRef('home')" to="/">
|
||||
<svg focusable="false" data-prefix="fal" data-icon="house-night" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512" class="svg-inline--fa fa-house-night fa-w-20"><path fill="currentColor" d="M112,224a111.5,111.5,0,0,0,87-41.45,20.51,20.51,0,0,0-19.75-33.08A59.2,59.2,0,0,1,138.84,39.85a20.3,20.3,0,0,0,10.07-21.27,20.26,20.26,0,0,0-16.47-16.7A136,136,0,0,0,112,0a112,112,0,0,0,0,224ZM97.78,33.27a91.21,91.21,0,0,0,54.47,147.9A80,80,0,1,1,97.78,33.27Zm97.15,35.51,39.72,16.56,16.56,39.72a5.33,5.33,0,0,0,9.55,0l16.56-39.72L317,68.78a5.33,5.33,0,0,0,0-9.54L277.32,42.68,260.76,3a5.33,5.33,0,0,0-9.55,0L234.65,42.68,194.93,59.24a5.34,5.34,0,0,0,0,9.54ZM157,379.24l-39.72-16.57L100.76,323a5.34,5.34,0,0,0-9.55,0L74.65,362.67,34.93,379.24a5.34,5.34,0,0,0,0,9.54l39.72,16.56,16.56,39.72a5.33,5.33,0,0,0,9.55,0l16.56-39.72L157,388.78a5.33,5.33,0,0,0,0-9.54Zm179-101.9v85.33A21.39,21.39,0,0,0,357.36,384h85.31A21.39,21.39,0,0,0,464,362.67V277.34A21.4,21.4,0,0,0,442.67,256H357.36A21.4,21.4,0,0,0,336,277.34ZM368,288H432v64H368Zm266.49,8L576,244.75V144a16,16,0,0,0-32,0v72.75L410.53,100a16,16,0,0,0-21.07,0l-224,196a16,16,0,0,0,21.07,24.09L224,287.28V464a48.05,48.05,0,0,0,48,48H528a48.06,48.06,0,0,0,48-48V287.28l37.46,32.78A16,16,0,0,0,634.53,296ZM544,464a16,16,0,0,1-16,16H272a16,16,0,0,1-16-16V264a15.94,15.94,0,0,0-.81-4L400,133.27l144,126Z" class=""></path></svg>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
|
||||
<div id="nav-bookmark" ref="bookmark" :style="bookmarkCss"></div>
|
||||
<div id="nav-background"></div>
|
||||
|
||||
<img id="meru" src="/meru_256px.png" alt="">
|
||||
</div>
|
||||
|
||||
<NuxtPage/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {nextTick, onMounted, onUnmounted, ref, ComponentPublicInstance, watch} from 'vue';
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const currentRoute = ref('')
|
||||
const bookmarkCss = ref('')
|
||||
const lastTop = ref(0)
|
||||
const menuOpen = ref(false)
|
||||
const bookmarkUpdateIntervalId = ref<number | null>(null)
|
||||
|
||||
const navRefs = ref<Record<string, Element | ComponentPublicInstance | null>>({})
|
||||
|
||||
const showMenu = (): void => {
|
||||
menuOpen.value = !menuOpen.value
|
||||
|
||||
if (menuOpen.value) setTimeout(() => menuOpen.value = false, 2000)
|
||||
}
|
||||
|
||||
const setNavRef = (name: string) => (el: Element | ComponentPublicInstance | null) => {
|
||||
navRefs.value[name] = el
|
||||
}
|
||||
|
||||
const resolveNavElement = (target: Element | ComponentPublicInstance | null | undefined): Element | null => {
|
||||
if (!target) return null
|
||||
if (target instanceof Element) return target
|
||||
return (target.$el as Element | undefined) ?? null
|
||||
}
|
||||
|
||||
const calculateBookmarkCss = (): void => {
|
||||
const currentLink = resolveNavElement(navRefs.value[currentRoute.value])
|
||||
if (!currentLink) return
|
||||
|
||||
const box = currentLink.getBoundingClientRect()
|
||||
if (box.top === lastTop.value) return
|
||||
lastTop.value = box.top
|
||||
|
||||
const h = box.bottom - box.top
|
||||
const width = Math.round(h / 2) + 8
|
||||
|
||||
bookmarkCss.value = `top: ${box.top - 8}px;` +
|
||||
`border-width: ${width}px 20px ${width}px 50px;`
|
||||
}
|
||||
|
||||
const getRouteBookmark = (path: string): string => {
|
||||
if (path.startsWith('/photo')) return 'photo'
|
||||
if (path === '/kitchen-menu' || path === '/friends' || path === '/projects' || path === '/others') return 'others'
|
||||
if (path === '/about') return 'about'
|
||||
if (path === '/life') return 'life'
|
||||
if (path === '/blog') return 'blog'
|
||||
return 'home'
|
||||
}
|
||||
|
||||
const getRouteTitle = (path: string): string => {
|
||||
if (path === '/about') return '关于'
|
||||
if (path === '/life') return '生活'
|
||||
if (path === '/blog') return '记事本'
|
||||
if (path.startsWith('/photo')) return '相册'
|
||||
if (path === '/others') return '更多'
|
||||
if (path === '/kitchen-menu') return '菜单'
|
||||
if (path === '/friends') return '朋友们'
|
||||
if (path === '/projects') return '我做的'
|
||||
return 'Home'
|
||||
}
|
||||
|
||||
const updateBookmark = (): void => {
|
||||
nextTick(() => {
|
||||
if (route.path === '/blog' && Object.keys(route.query).length !== 0) return
|
||||
const title = getRouteTitle(route.path)
|
||||
document.title = title ? `Aza - ${title}` : 'Aza - Home'
|
||||
})
|
||||
|
||||
currentRoute.value = getRouteBookmark(route.path)
|
||||
|
||||
calculateBookmarkCss()
|
||||
menuOpen.value = false
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
updateBookmark()
|
||||
|
||||
window.addEventListener('resize', calculateBookmarkCss, true)
|
||||
bookmarkUpdateIntervalId.value = window.setInterval(calculateBookmarkCss, 1000)
|
||||
})
|
||||
|
||||
watch(() => route.fullPath, updateBookmark)
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', calculateBookmarkCss, true)
|
||||
if (bookmarkUpdateIntervalId.value !== null) {
|
||||
window.clearInterval(bookmarkUpdateIntervalId.value)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="sass">
|
||||
@use "css/global"
|
||||
@use "css/animations"
|
||||
|
||||
#nav
|
||||
position: fixed
|
||||
left: 0
|
||||
height: 100%
|
||||
font-size: 1.4em
|
||||
align-items: flex-start
|
||||
|
||||
z-index: 100
|
||||
pointer-events: none
|
||||
|
||||
#menu
|
||||
padding: 5px 10px
|
||||
margin: 15px 10px
|
||||
background-color: rgba(255, 255, 255, 0.49)
|
||||
border-radius: 10px
|
||||
text-shadow: -1px -1px 1px rgba(255,255,255,.1), 1px 1px 1px rgba(0,0,0,.5)
|
||||
filter: drop-shadow(0 0 30px rgb(255, 255, 255))
|
||||
|
||||
z-index: 100
|
||||
pointer-events: auto
|
||||
|
||||
opacity: 0
|
||||
|
||||
#nav-bookmark
|
||||
position: absolute
|
||||
left: 0
|
||||
width: 20px
|
||||
height: 0
|
||||
z-index: 5
|
||||
--bookmark-color: rgb(255, 225, 230)
|
||||
border-color: var(--bookmark-color) transparent var(--bookmark-color) var(--bookmark-color)
|
||||
border-style: solid
|
||||
border-width: 20px
|
||||
|
||||
#items
|
||||
justify-content: flex-end
|
||||
z-index: 10
|
||||
|
||||
.router-link
|
||||
color: rgba(128, 112, 92, 0.71)
|
||||
position: relative
|
||||
|
||||
z-index: 100
|
||||
pointer-events: auto
|
||||
|
||||
.dot
|
||||
content: '·'
|
||||
margin: 20px 0
|
||||
user-select: none
|
||||
|
||||
.router-link, .dot
|
||||
text-decoration: none
|
||||
writing-mode: vertical-rl
|
||||
text-orientation: sideways
|
||||
transform: scale(-1)
|
||||
padding-right: 20px
|
||||
|
||||
#nav-background
|
||||
position: absolute
|
||||
height: 100%
|
||||
width: 100px
|
||||
left: 0
|
||||
$nav-bg-color: #f9f2e0
|
||||
border-left: 20px solid $nav-bg-color
|
||||
background: linear-gradient(to right, $nav-bg-color, transparent)
|
||||
|
||||
z-index: 4
|
||||
pointer-events: none
|
||||
|
||||
#meru
|
||||
height: 160px
|
||||
|
||||
z-index: 100
|
||||
pointer-events: auto
|
||||
|
||||
svg
|
||||
display: inline-block
|
||||
height: 1em
|
||||
transform: rotate(180deg)
|
||||
*
|
||||
box-sizing: inherit
|
||||
|
||||
#nav *
|
||||
transition: all .25s ease
|
||||
|
||||
@media screen and (max-width: 800px)
|
||||
#nav #menu
|
||||
opacity: 1
|
||||
|
||||
#nav.home
|
||||
#menu, #nav-background
|
||||
opacity: 0
|
||||
|
||||
#nav:not(.home).open
|
||||
#items, #nav-bookmark, #nav-background, #meru
|
||||
opacity: 1
|
||||
animation: fade-in-left .5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both
|
||||
|
||||
#nav:not(.home)
|
||||
#items, #nav-bookmark, #nav-background, #meru
|
||||
opacity: 0
|
||||
animation: fade-out-left 1s 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both
|
||||
|
||||
@media screen and (max-width: 500px), (max-height: 660px)
|
||||
#app
|
||||
font-size: 14px
|
||||
|
||||
#nav
|
||||
#nav-bookmark
|
||||
width: 10px
|
||||
|
||||
#meru
|
||||
height: 120px
|
||||
|
||||
@media screen and (max-width: 370px)
|
||||
#nav #menu
|
||||
opacity: unset
|
||||
|
||||
#nav.home
|
||||
#menu, #nav-background
|
||||
opacity: unset
|
||||
|
||||
#nav.open
|
||||
#items, #nav-bookmark, #nav-background, #meru
|
||||
opacity: 1
|
||||
animation: fade-in-left .5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both
|
||||
|
||||
#nav
|
||||
#items, #nav-bookmark, #nav-background, #meru
|
||||
opacity: 0
|
||||
animation: fade-out-left 1s 0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both
|
||||
|
||||
@media screen and (max-height: 600px)
|
||||
#nav
|
||||
.dot
|
||||
margin: 10px 0
|
||||
|
||||
@media screen and (max-height: 500px)
|
||||
#nav
|
||||
.router-link
|
||||
margin-bottom: 10px
|
||||
|
||||
.dot
|
||||
display: none
|
||||
</style>
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
import {createApp, h} from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './scripts/router'
|
||||
import {i18n} from "@/scripts/messages"
|
||||
import '@fortawesome/fontawesome-free/css/all.min.css'
|
||||
import Collapse from "@/components/Collapse.vue"
|
||||
import BlogIndex from "@/components/BlogIndex.vue";
|
||||
import Tag from "@/components/Tag.vue";
|
||||
import 'virtual:uno.css'
|
||||
|
||||
const app = createApp(App).use(router).use(i18n)
|
||||
.component('Collapse', Collapse)
|
||||
.component('BlogIndex', BlogIndex)
|
||||
.component('Dynamic', {
|
||||
props: ['template'],
|
||||
render() {
|
||||
return h({template: this.template})
|
||||
}
|
||||
})
|
||||
.component('Tag', Tag)
|
||||
|
||||
// app.config.performance = true
|
||||
app.mount('#app')
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<AboutView />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import AboutView from '@/views/About.vue'
|
||||
</script>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<BlogView />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import BlogView from '@/views/Blog.vue'
|
||||
</script>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<FriendsView />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import FriendsView from '@/views/others/Friends.vue'
|
||||
</script>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<HomeView />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import HomeView from '@/views/Home.vue'
|
||||
</script>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<MenuView />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import MenuView from '@/views/others/Menu.vue'
|
||||
</script>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<LifeView />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import LifeView from '@/views/Life.vue'
|
||||
</script>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<OthersView />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import OthersView from '@/views/Others.vue'
|
||||
</script>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<PhotoView />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import PhotoView from '@/views/Photo.vue'
|
||||
</script>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<PhotoView />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import PhotoView from '@/views/Photo.vue'
|
||||
</script>
|
||||
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<ProjectsView />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ProjectsView from '@/views/others/Projects.vue'
|
||||
</script>
|
||||
@@ -0,0 +1,12 @@
|
||||
import {createI18n} from 'vue-i18n'
|
||||
import {messages, resolveLocale} from '@/scripts/messages'
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
const i18n = createI18n({
|
||||
messages,
|
||||
locale: resolveLocale(),
|
||||
fallbackLocale: 'en'
|
||||
})
|
||||
|
||||
nuxtApp.vueApp.use(i18n)
|
||||
})
|
||||
File diff suppressed because one or more lines are too long
+15
-27
@@ -1,31 +1,19 @@
|
||||
import {createI18n} from "vue-i18n";
|
||||
|
||||
export const messages = {
|
||||
en: {
|
||||
nav: {
|
||||
home: 'Home',
|
||||
about: '关于',
|
||||
blog: '记事本',
|
||||
life: '生活',
|
||||
projects: 'Projects',
|
||||
others: '更多',
|
||||
photo: '相册'
|
||||
}
|
||||
},
|
||||
zh: {
|
||||
// nav: {
|
||||
// home: '温馨家',
|
||||
// about: '关于我',
|
||||
// blog: '部落格',
|
||||
// projects: '我做的',
|
||||
// }
|
||||
en: {
|
||||
nav: {
|
||||
home: 'Home',
|
||||
about: '关于',
|
||||
blog: '记事本',
|
||||
life: '生活',
|
||||
projects: 'Projects',
|
||||
others: '更多',
|
||||
photo: '相册'
|
||||
}
|
||||
},
|
||||
zh: {}
|
||||
}
|
||||
|
||||
export const i18n = createI18n({
|
||||
messages,
|
||||
locale: navigator.language.split('-')[0],
|
||||
fallbackLocale: 'en'
|
||||
})
|
||||
|
||||
console.log(navigator.language)
|
||||
export const resolveLocale = (): string => {
|
||||
if (typeof navigator === 'undefined') return 'en'
|
||||
return navigator.language.split('-')[0]
|
||||
}
|
||||
|
||||
+10
-83
@@ -1,88 +1,15 @@
|
||||
import {createRouter, createWebHistory, NavigationFailure, RouteRecordRaw} from 'vue-router'
|
||||
import Home from '../views/Home.vue'
|
||||
import {NavigationFailure, useRoute, useRouter} from 'vue-router'
|
||||
|
||||
const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Home',
|
||||
meta: {title: 'Home', nav: true},
|
||||
component: Home
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
name: 'About',
|
||||
meta: {title: '关于', nav: true},
|
||||
component: () => import('../views/About.vue')
|
||||
},
|
||||
{
|
||||
path: '/life',
|
||||
name: 'Life',
|
||||
meta: {title: '生活', nav: true},
|
||||
component: () => import('../views/Life.vue')
|
||||
},
|
||||
{
|
||||
path: '/blog',
|
||||
name: 'Blog',
|
||||
meta: {title: '记事本', nav: true},
|
||||
component: () => import('../views/Blog.vue'),
|
||||
props: route => (route.query)
|
||||
},
|
||||
{
|
||||
path: '/photo',
|
||||
name: 'Photo',
|
||||
meta: {title: '相册', nav: true},
|
||||
component: () => import('../views/Photo.vue')
|
||||
},
|
||||
{
|
||||
path: '/photo/:id',
|
||||
name: 'Photo ID',
|
||||
meta: {title: '相册', navBookmark: 'Photo'},
|
||||
component: () => import('../views/Photo.vue')
|
||||
},
|
||||
{
|
||||
path: '/others',
|
||||
name: 'Others',
|
||||
meta: {title: '更多', nav: true},
|
||||
component: () => import('../views/Others.vue')
|
||||
},
|
||||
{
|
||||
path: '/kitchen-menu',
|
||||
name: 'Menu',
|
||||
meta: {title: '菜单', navBookmark: 'Others'},
|
||||
component: () => import('../views/others/Menu.vue')
|
||||
},
|
||||
{
|
||||
path: '/friends',
|
||||
name: 'Friends',
|
||||
meta: {title: '朋友们', navBookmark: 'Others'},
|
||||
component: () => import('../views/others/Friends.vue')
|
||||
},
|
||||
{
|
||||
path: '/projects',
|
||||
name: 'Projects',
|
||||
meta: {title: '我做的', navBookmark: 'Others'},
|
||||
component: () => import('../views/others/Projects.vue')
|
||||
},
|
||||
]
|
||||
export function pushQuery(query: {[id: string]: string | null}): Promise<void | NavigationFailure | undefined> {
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
export const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes
|
||||
})
|
||||
const queries = {...route.query}
|
||||
|
||||
export function pushQuery(query: {[id: string]: string | null}): Promise<void | NavigationFailure | undefined>
|
||||
{
|
||||
const queries = {...router.currentRoute.value.query ?? {}}
|
||||
for (const k of Object.keys(query)) {
|
||||
if (query[k] == null) delete queries[k]
|
||||
else queries[k] = query[k]
|
||||
}
|
||||
|
||||
console.log(query)
|
||||
|
||||
for (const k of Object.keys(query))
|
||||
{
|
||||
if (query[k] == null) delete queries[k]
|
||||
else queries[k] = query[k]
|
||||
}
|
||||
|
||||
return router.push({query: queries})
|
||||
return router.push({query: queries})
|
||||
}
|
||||
|
||||
export default router
|
||||
|
||||
+38
-39
@@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<div id="Blog" class="general-page" v-if="meta">
|
||||
<div class="title">
|
||||
<h2>记事本</h2>
|
||||
<div class="subtitle">一些值得留下来的文字</div>
|
||||
</div>
|
||||
<div id="breadcrumb">
|
||||
<span class="clickable" @click="() => $router.push({query: {}})">索引</span>
|
||||
<span v-if="tag">🏷️{{tag}}</span>
|
||||
<span v-if="category">📂{{category}}</span>
|
||||
<span class="no-after" v-if="post && activePost">{{activePost.title}}</span>
|
||||
</div>
|
||||
<BlogPostPreview v-for="m of filteredPosts" :key="m.id" :meta="m" :active="m === activePost"/>
|
||||
<div id="Blog" class="general-page" v-if="meta">
|
||||
<div class="title">
|
||||
<h2>记事本</h2>
|
||||
<div class="subtitle">一些值得留下来的文字</div>
|
||||
</div>
|
||||
<Loading v-else></Loading>
|
||||
<div id="breadcrumb">
|
||||
<span class="clickable" @click="clearQuery">索引</span>
|
||||
<span v-if="tag">🏷️{{tag}}</span>
|
||||
<span v-if="category">📂{{category}}</span>
|
||||
<span class="no-after" v-if="post && activePost">{{activePost.title}}</span>
|
||||
</div>
|
||||
<BlogPostPreview v-for="m of filteredPosts" :key="m.id" :meta="m" :active="m === activePost"/>
|
||||
</div>
|
||||
<Loading v-else></Loading>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -22,40 +22,39 @@ import {BlogMeta} from "@/scripts/models";
|
||||
import {Ref, ref, computed, onMounted} from "vue";
|
||||
import {hosts} from "@/scripts/constants";
|
||||
import {globals} from "@/scripts/global";
|
||||
import {Router} from "vue-router";
|
||||
|
||||
let $router: Router
|
||||
|
||||
const p = defineProps<{
|
||||
post?: string,
|
||||
category?: string,
|
||||
tag?: string
|
||||
}>()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
let meta: Ref<BlogMeta> = ref({tags: [], categories: [], posts: []})
|
||||
|
||||
onMounted(() => {
|
||||
fetch(`${hosts.content}/content/generated/metas.json`).then(it => it.json()).then(it => {
|
||||
meta.value = it
|
||||
globals.staticMeta = it
|
||||
})
|
||||
fetch(`${hosts.content}/content/generated/metas.json`).then(it => it.json()).then(it => {
|
||||
meta.value = it
|
||||
globals.staticMeta = it
|
||||
})
|
||||
})
|
||||
|
||||
const post = computed(() => typeof route.query.post === 'string' ? route.query.post : undefined)
|
||||
const category = computed(() => typeof route.query.category === 'string' ? route.query.category : undefined)
|
||||
const tag = computed(() => typeof route.query.tag === 'string' ? route.query.tag : undefined)
|
||||
|
||||
const clearQuery = (): Promise<void> => router.push({query: {}})
|
||||
|
||||
const filteredPosts = computed(() => {
|
||||
const posts = meta.value.posts.filter(it => it.pinned || (p.tag ? it.tags.includes(p.tag) :
|
||||
p.category ? it.category == p.category : true))
|
||||
const posts = meta.value.posts.filter(it => it.pinned || (tag.value ? it.tags.includes(tag.value) :
|
||||
category.value ? it.category == category.value : true))
|
||||
|
||||
// Put pinned posts on top
|
||||
posts.sort((a, b) => (b.pinned ?? 0) - (a.pinned ?? 0))
|
||||
posts.sort((a, b) => (b.pinned ?? 0) - (a.pinned ?? 0))
|
||||
|
||||
return posts
|
||||
return posts
|
||||
})
|
||||
|
||||
const activePost = computed(() => {
|
||||
const posts = filteredPosts.value
|
||||
if (posts.length == 0) return null
|
||||
if (!p.post) return null
|
||||
return p.post ? posts.filter(it => it.url_name == p.post)[0] : posts[0].pinned ? posts[0] : null
|
||||
const posts = filteredPosts.value
|
||||
if (posts.length == 0) return null
|
||||
if (!post.value) return null
|
||||
return post.value ? posts.filter(it => it.url_name == post.value)[0] : posts[0].pinned ? posts[0] : null
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -64,11 +63,11 @@ const activePost = computed(() => {
|
||||
@use "../css/responsive"
|
||||
|
||||
#breadcrumb
|
||||
color: colors.$color-text-light
|
||||
margin-bottom: 20px
|
||||
color: colors.$color-text-light
|
||||
margin-bottom: 20px
|
||||
|
||||
span:not(.no-after):after
|
||||
content: ">"
|
||||
margin: 0 10px
|
||||
span:not(.no-after):after
|
||||
content: ">"
|
||||
margin: 0 10px
|
||||
|
||||
</style>
|
||||
|
||||
+4
-39
@@ -1,41 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"strict": false,
|
||||
"jsx": "preserve",
|
||||
"importHelpers": true,
|
||||
"moduleResolution": "node",
|
||||
"experimentalDecorators": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
},
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"scripthost"
|
||||
],
|
||||
|
||||
"emitDecoratorMetadata": true,
|
||||
"allowJs": true,
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"tests/**/*.ts",
|
||||
"tests/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
"extends": "./.nuxt/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["@types/jquery", "@types/jqueryui"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
import { defineConfig } from "vite";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import UnoCSS from 'unocss/vite';
|
||||
import path from "path";
|
||||
|
||||
const src = path.resolve(__dirname, 'src')
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(), UnoCSS()
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': src,
|
||||
|
||||
// Runtime compilation
|
||||
vue: "vue/dist/vue.esm-bundler.js"
|
||||
},
|
||||
dedupe: ['vue'],
|
||||
},
|
||||
server: {
|
||||
watch: {
|
||||
usePolling: true
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user