Fancy transitions!
This commit is contained in:
parent
472ab354d8
commit
5f9eb1fc50
11 changed files with 183 additions and 107 deletions
31
app.vue
31
app.vue
|
@ -7,11 +7,28 @@ import './assets/style.css'
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<Navbar/>
|
||||
<NuxtLayout>
|
||||
<NuxtPage/>
|
||||
</NuxtLayout>
|
||||
<background-calm />
|
||||
</div>
|
||||
<Navbar/>
|
||||
<NuxtPage :transition="{
|
||||
name: 'page',
|
||||
mode: 'out-in'
|
||||
}" />
|
||||
<background-calm />
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.page-move,
|
||||
.page-enter-active,
|
||||
.page-leave-active {
|
||||
transition: all 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
|
||||
}
|
||||
|
||||
.page-enter-from,
|
||||
.page-leave-to {
|
||||
opacity: 0;
|
||||
transform: translate(100px, 0);
|
||||
}
|
||||
|
||||
.page-leave-active {
|
||||
position: absolute;
|
||||
}
|
||||
</style>
|
||||
|
|
36
assets/markdown_conf.ts
Normal file
36
assets/markdown_conf.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import hljs from 'highlight.js';
|
||||
import MarkdownIt from 'markdown-it';
|
||||
|
||||
export default function configured_markdown(): MarkdownIt {
|
||||
const md: MarkdownIt = MarkdownIt({
|
||||
breaks: true,
|
||||
typographer: true,
|
||||
html: true,
|
||||
highlight: function (str, lang) {
|
||||
if (lang && hljs.getLanguage(lang)) {
|
||||
try {
|
||||
return '<pre><code class="hljs">' +
|
||||
hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
|
||||
'</code></pre>';
|
||||
} catch (__) { }
|
||||
}
|
||||
|
||||
return '<pre><code class="hljs">' + md.utils.escapeHtml(str) + '</code></pre>';
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
md.renderer.rules.hr = function (tokens, idx, options, env, self) {
|
||||
return '<div class="rounded-full h-0.5 bg-purple-500 my-3"></div>'
|
||||
}
|
||||
|
||||
md.renderer.rules.softbreak = function (tokens, idx, options, env, self) {
|
||||
return '<br>'
|
||||
}
|
||||
|
||||
md.renderer.rules.hardbreak = function (tokens, idx, options, env, self) {
|
||||
return '<br><br>'
|
||||
}
|
||||
|
||||
return md;
|
||||
}
|
35
components/Markdown.vue
Normal file
35
components/Markdown.vue
Normal file
|
@ -0,0 +1,35 @@
|
|||
<script setup lang="ts">
|
||||
import configured_markdown from '~/assets/markdown_conf';
|
||||
import { useSlots } from 'vue';
|
||||
|
||||
let markdown = configured_markdown();
|
||||
|
||||
const text = ref("");
|
||||
const loading = ref(true);
|
||||
|
||||
const props = defineProps({
|
||||
text: String,
|
||||
});
|
||||
|
||||
function render_markdown(data: string | undefined) {
|
||||
if (!data) {
|
||||
loading.value = false;
|
||||
return;
|
||||
}
|
||||
text.value = markdown.render(data);
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
watch(() => props.text, (newVal) => {
|
||||
render_markdown(newVal);
|
||||
}, {
|
||||
immediate: true
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="loading" class="text-center animate-pulse">
|
||||
<h2>Loading...</h2>
|
||||
</div>
|
||||
<div v-html="text"></div>
|
||||
</template>
|
|
@ -1,14 +1,17 @@
|
|||
<script setup>
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-center">
|
||||
<div class="flex-col transition-[margin] justify-center md:rounded-md max-md:w-screen lg:mt-3 w-fit-content pr-4 pl-4 bg-purple-500 bg-opacity-25 text-white">
|
||||
<div class="flex justify-center">
|
||||
<a href="/" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Home</a>
|
||||
<a href="/blog/" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Blog</a>
|
||||
<a href="/blog/?post=/blog/awesome.md" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Awesome</a>
|
||||
<a href="/blog/?post=/blog/badges.md" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Badges</a>
|
||||
<NuxtLink href="/" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Home</NuxtLink>
|
||||
<NuxtLink href="/blog/" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Blog</NuxtLink>
|
||||
<NuxtLink href="/blog/?post=/blog/awesome.md" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Awesome</NuxtLink>
|
||||
<NuxtLink href="/blog/?post=/blog/badges.md" class="transition text-xl pl-2 pr-2 ease-in-out text-purple-100 hover:text-purple-400 duration-200">Badges</NuxtLink>
|
||||
</div>
|
||||
<div class="flex justify-center">
|
||||
<small class=" ml-3 mr-3">Hosted with <a href="https://github.com/misslunatic/misslunatic.github.io" class="text-blue-500">GitHub Pages</a></small>
|
||||
<small class=" ml-3 mr-3">Hosted with <NuxtLink href="https://github.com/misslunatic/misslunatic.github.io" class="text-blue-500">GitHub Pages</NuxtLink></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -6,11 +6,6 @@ const props = defineProps({
|
|||
url: String,
|
||||
});
|
||||
|
||||
import { useSlots } from 'vue';
|
||||
|
||||
const slots = useSlots();
|
||||
|
||||
|
||||
const url = ref(props.url)
|
||||
url.value = props.url
|
||||
const loading = ref(false)
|
||||
|
@ -52,11 +47,10 @@ async function fetchData() {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<a :href="'/blog?post=' +url">
|
||||
<div class="m-4 p-3 min-h-10 w-90 text-white rounded-2xl border-2 border-purple-300 transition hover:bg-purple-600 bg-purple-700 bg-opacity-50 hover:bg-opacity-70"
|
||||
<NuxtLink :href="'/blog?post=' +url">
|
||||
<div class="m-4 p-3 min-h-30 w-90 text-white rounded-2xl border-2 border-purple-300 transition hover:bg-purple-600 bg-purple-700 bg-opacity-50 hover:bg-opacity-70"
|
||||
:style="{ backgroundImage: `url(${background})` }">
|
||||
<div v-if="loading" class="text-center animate-pulse">
|
||||
<h2>Loading...</h2>
|
||||
</div>
|
||||
<div v-else-if="error" class="text-center">
|
||||
<h2>Error: {{ error }}</h2>
|
||||
|
@ -76,5 +70,5 @@ async function fetchData() {
|
|||
<p>{{ description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</NuxtLink>
|
||||
</template>
|
15
deno.lock
generated
15
deno.lock
generated
|
@ -5,6 +5,7 @@
|
|||
"npm:@tsparticles/engine@^3.5.0": "3.7.1",
|
||||
"npm:@tsparticles/slim@^3.7.1": "3.7.1",
|
||||
"npm:@tsparticles/vue3@^3.0.1": "3.0.1",
|
||||
"npm:@types/markdown-it@^14.1.2": "14.1.2",
|
||||
"npm:autoprefixer@^10.4.20": "10.4.20_postcss@8.4.49",
|
||||
"npm:front-matter@^4.0.2": "4.0.2",
|
||||
"npm:highlight.js@^11.10.0": "11.11.0",
|
||||
|
@ -1307,6 +1308,19 @@
|
|||
"@types/node"
|
||||
]
|
||||
},
|
||||
"@types/linkify-it@5.0.0": {
|
||||
"integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q=="
|
||||
},
|
||||
"@types/markdown-it@14.1.2": {
|
||||
"integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==",
|
||||
"dependencies": [
|
||||
"@types/linkify-it",
|
||||
"@types/mdurl"
|
||||
]
|
||||
},
|
||||
"@types/mdurl@2.0.0": {
|
||||
"integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="
|
||||
},
|
||||
"@types/node@22.5.4": {
|
||||
"integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==",
|
||||
"dependencies": [
|
||||
|
@ -4672,6 +4686,7 @@
|
|||
"npm:@tsparticles/engine@^3.5.0",
|
||||
"npm:@tsparticles/slim@^3.7.1",
|
||||
"npm:@tsparticles/vue3@^3.0.1",
|
||||
"npm:@types/markdown-it@^14.1.2",
|
||||
"npm:autoprefixer@^10.4.20",
|
||||
"npm:front-matter@^4.0.2",
|
||||
"npm:highlight.js@^11.10.0",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
compatibilityDate: '2024-11-01',
|
||||
devtools: { enabled: true },
|
||||
ssr: true,
|
||||
postcss: {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
|
@ -9,10 +9,10 @@ export default defineNuxtConfig({
|
|||
},
|
||||
},
|
||||
app: {
|
||||
layoutTransition: {
|
||||
name: 'layout',
|
||||
pageTransition: {
|
||||
name: 'page',
|
||||
mode: 'out-in'
|
||||
}
|
||||
},
|
||||
},
|
||||
modules: [
|
||||
'nuxt-particles'
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@tsparticles/slim": "^3.7.1",
|
||||
"@types/markdown-it": "^14.1.2",
|
||||
"nuxt": "^3.14.1592",
|
||||
"tsparticles": "^3.7.1",
|
||||
"vue": "latest",
|
||||
|
|
|
@ -1,43 +1,14 @@
|
|||
<script setup>
|
||||
import { onMounted, watch, ref } from 'vue';
|
||||
import fm from 'front-matter';
|
||||
import markdownit from 'markdown-it'
|
||||
|
||||
import PostCard from '../components/PostCard.vue';
|
||||
import hljs from 'highlight.js';
|
||||
|
||||
|
||||
// Automatically maintained is a blog_list.json in assets/. This file contains a list of all blog posts and their metadata.
|
||||
// This file is generated by a script in the root directory of the project.
|
||||
import blog_list from '../assets/blog_list.json';
|
||||
|
||||
const md = markdownit({
|
||||
breaks: true,
|
||||
typographer: true,
|
||||
html: true,
|
||||
highlight: function (str, lang) {
|
||||
if (lang && hljs.getLanguage(lang)) {
|
||||
try {
|
||||
return '<pre><code class="hljs">' +
|
||||
hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
|
||||
'</code></pre>';
|
||||
} catch (__) { }
|
||||
}
|
||||
|
||||
return '<pre><code class="hljs">' + md.utils.escapeHtml(str) + '</code></pre>';
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
md.renderer.rules.hr = function (tokens, idx, options, env, self) {
|
||||
return '<div class="rounded-full h-0.5 bg-purple-500 my-3"></div>'
|
||||
}
|
||||
|
||||
md.renderer.rules.softbreak = function (tokens, idx, options, env, self) {
|
||||
return '<br>'
|
||||
}
|
||||
|
||||
md.renderer.rules.hardbreak = function (tokens, idx, options, env, self) {
|
||||
return '<br><br>'
|
||||
}
|
||||
import configured_markdown from '~/assets/markdown_conf';
|
||||
|
||||
const modules = import.meta.glob('/blog/');
|
||||
|
||||
|
@ -73,10 +44,16 @@ const tags = ref(null);
|
|||
|
||||
// watch the params of the route to fetch the data again
|
||||
|
||||
fetchData(url.value)
|
||||
watch(route, async () => {
|
||||
url.value = route.query.post
|
||||
await fetchData(route.query.post)
|
||||
}, {
|
||||
immediate: true
|
||||
});
|
||||
|
||||
|
||||
async function fetchData(url) {
|
||||
const md = configured_markdown();
|
||||
error.value = data.value = null
|
||||
loading.value = true
|
||||
console.log(url)
|
||||
|
@ -140,12 +117,21 @@ async function fetchList() {
|
|||
|
||||
}
|
||||
fetchList()
|
||||
|
||||
// Hook and check if the URL gets changed in the query params
|
||||
watch(url, async () => {
|
||||
await fetchData(url.value)
|
||||
}, {
|
||||
immediate: true
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative z-50 flex w-full justify-center text-white">
|
||||
<div class="mt-8 flex-col text-center">
|
||||
<div v-if="url == null">
|
||||
<Transition name="list">
|
||||
<div v-if="url == null" :key="url">
|
||||
<h1>Blog</h1>
|
||||
<div class="flex justify-center m-5">
|
||||
<div v-for="tag in tagList" :key="tag" class="m-1 text-center">
|
||||
|
@ -165,20 +151,23 @@ fetchList()
|
|||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="flex flex-col">
|
||||
<h1>{{ title }}</h1>
|
||||
<div class="max-w-50 flex flex-row justify-center">
|
||||
<div v-for="tag in tags" :key="tag" class="m-1 text-center">
|
||||
<span class="text-xs bg-purple-800 border-purple-400 border text-white p-1 rounded-md">{{
|
||||
tag }}</span>
|
||||
<Transition name="list">
|
||||
<div class="flex flex-col" :key="url">
|
||||
<h1>{{ title }}</h1>
|
||||
<div class="max-w-50 flex flex-row justify-center">
|
||||
<div v-for="tag in tags" :key="tag" class="m-1 text-center">
|
||||
<span class="text-xs bg-purple-800 border-purple-400 border text-white p-1 rounded-md">{{
|
||||
tag }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="text-pretty min-w-96 text-left max-w-4xl mt-4 p-6 max-md:w-screen rounded-md container bg-opacity-90 bg-purple-950">
|
||||
<div v-html="text"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="text-pretty min-w-96 text-left max-w-4xl mt-4 p-6 max-md:w-screen rounded-md container bg-opacity-90 bg-purple-950">
|
||||
<div v-html="text"></div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -187,7 +176,7 @@ fetchList()
|
|||
.list-move,
|
||||
.list-enter-active,
|
||||
.list-leave-active {
|
||||
transition: all 0.5s cubic-bezier(0.55, 0, 0.1, 1);
|
||||
transition: all 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55);
|
||||
}
|
||||
|
||||
.list-enter-from,
|
||||
|
|
|
@ -1,47 +1,33 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import aboutMe from '../assets/about_me.md?raw'
|
||||
import markdownit from 'markdown-it'
|
||||
import PostCard from '../components/PostCard.vue';
|
||||
import configured_markdown from '~/assets/markdown_conf';
|
||||
import Markdown from '~/components/Markdown.vue';
|
||||
|
||||
const md = markdownit({
|
||||
breaks: true,
|
||||
typographer: true,
|
||||
html: true,
|
||||
})
|
||||
const aboutMe = ref("");
|
||||
|
||||
|
||||
md.renderer.rules.hr = function(tokens, idx, options, env, self) {
|
||||
return '<div class="rounded-full h-0.5 bg-purple-500 my-3"></div>'
|
||||
}
|
||||
|
||||
md.renderer.rules.softbreak = function(tokens, idx, options, env, self) {
|
||||
return '<br>'
|
||||
}
|
||||
|
||||
md.renderer.rules.hardbreak = function(tokens, idx, options, env, self) {
|
||||
return '<br><br>'
|
||||
}
|
||||
md.renderer.rules.blockquote_open = function(tokens, idx, options, env, self) {
|
||||
return '<blockquote class="border-l-4 border-purple-500 pl-4 my-4">'
|
||||
}
|
||||
const result = ref('')
|
||||
|
||||
result.value = md.render(aboutMe);
|
||||
fetch("/about_me.md")
|
||||
.then((res) => res.text())
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
aboutMe.value = data;
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative z-50 flex w-full justify-center text-white">
|
||||
<div class="mt-8 flex-col text-center">
|
||||
<div class="flex justify-center">
|
||||
<div class="p-2 shadow-md rounded-full bg-pink-500">
|
||||
<img class="z-20 transition-all w-40 h-40 md:w-56 md:h-56 rounded-full" src="https://avatars.githubusercontent.com/u/94077364?v=4" alt="User PFP" />
|
||||
<div class="relative z-50 flex w-full justify-center text-white">
|
||||
<div class="mt-8 flex-col text-center">
|
||||
<div class="flex justify-center">
|
||||
<div class="p-2 shadow-md rounded-full bg-pink-500">
|
||||
<img class="z-20 transition-all w-40 h-40 md:w-56 md:h-56 rounded-full"
|
||||
src="https://avatars.githubusercontent.com/u/94077364?v=4" alt="User PFP" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="max-w-4xl mt-4 p-6 max-md:w-screen rounded-md container bg-opacity-70 bg-purple-950">
|
||||
<div v-html=result></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="max-w-4xl mt-4 p-6 max-md:w-screen rounded-md container bg-opacity-70 bg-purple-950">
|
||||
<Markdown :text="aboutMe"></Markdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
Loading…
Add table
Reference in a new issue