:3
This commit is contained in:
parent
c7f546f58a
commit
b62a50b12e
12 changed files with 444 additions and 638 deletions
144
pages/article/[category]/[id].vue
Normal file
144
pages/article/[category]/[id].vue
Normal file
|
@ -0,0 +1,144 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted, watch, ref } from 'vue';
|
||||
import fm from 'front-matter';
|
||||
|
||||
import PostCard from '~/components/PostCard.vue';
|
||||
import * as pages from '~/utils/page_updater/update_pagelist';
|
||||
import type { PageInfo, PageInfoMetdata } from '~/utils/page_updater/pages';
|
||||
import type { ParsedContent } from '@nuxt/content';
|
||||
|
||||
let route = useRoute()
|
||||
console.log(route)
|
||||
|
||||
const url: Ref<string> = ref("")
|
||||
url.value = '/' + route.params.category.concat('/' + route.params.id as string) as string
|
||||
|
||||
console.log(url.value)
|
||||
|
||||
const loading: Ref<boolean> = ref(false)
|
||||
|
||||
const tagFilter: Ref<string[]> = ref([])
|
||||
tagFilter.value = []
|
||||
|
||||
const markdown: Ref<any> = ref(null)
|
||||
|
||||
const title: Ref<string> = ref("")
|
||||
const description: Ref<string> = ref("")
|
||||
const date: Ref<string> = ref("")
|
||||
const tags: Ref<string[]> = ref([])
|
||||
const background: Ref<string> = ref("")
|
||||
const next: Ref<string> = ref("")
|
||||
const previous: Ref<string> = ref("")
|
||||
|
||||
watch(markdown , (newVal) => {
|
||||
if (newVal) {
|
||||
title.value = newVal.title ? newVal.title : ""
|
||||
description.value = newVal.description ? newVal.description : ""
|
||||
date.value = newVal.date ? new Date(newVal.date).toLocaleDateString() : ""
|
||||
tags.value = newVal.tags ? newVal.tags : []
|
||||
background.value = newVal.background ? newVal.background : ""
|
||||
}
|
||||
})
|
||||
|
||||
// watch the params of the route to fetch the data again
|
||||
watch(route, async () => {
|
||||
url.value = '/' + route.params.category.concat('/' + route.params.id as string) as string
|
||||
if (url.value) {
|
||||
console.log("Fetching article")
|
||||
loading.value = true
|
||||
try {
|
||||
await fetchArticle(url.value)
|
||||
}
|
||||
finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
}, {
|
||||
immediate: true
|
||||
});
|
||||
|
||||
// Fetch the article contents from the URL
|
||||
async function fetchArticle(url: string) {
|
||||
if (!url) {
|
||||
return
|
||||
}
|
||||
// Trim the .md extension
|
||||
var url = url.replace(/\.md$/, "")
|
||||
console.log("Fetching article: " + url)
|
||||
const { data } = await useAsyncData(url, () => queryContent(url).findOne())
|
||||
console.log(data)
|
||||
|
||||
markdown.value = data.value;
|
||||
}
|
||||
|
||||
function resetReadingPosition() {
|
||||
window.scrollTo(0, 0)
|
||||
}
|
||||
|
||||
fetchArticle(url.value)
|
||||
|
||||
console.log("Prefetching article")
|
||||
onMounted(async () => {
|
||||
console.log("Fetching article :3")
|
||||
await fetchArticle(url.value)
|
||||
})
|
||||
const temp_url = route.query.post as string
|
||||
await fetchArticle(temp_url);
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative z-50 flex w-full justify-center text-white">
|
||||
<!-- Metadata -->
|
||||
<MetaSet :title="title" :description="description" :date="date"
|
||||
:background="background" tags="tags" />
|
||||
<!-- Article Viewer -->
|
||||
<div class="mt-8 flex-col text-center">
|
||||
<Transition name="list">
|
||||
<div class="flex flex-col" :key="url">
|
||||
<h1>{{ title }}</h1>
|
||||
<small>{{ date }}</small>
|
||||
<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-black border-purple-400 border-2 text-white p-1 rounded-md">{{
|
||||
tag }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<!-- Next/Prev controls, on the left and right side using PostCards -->
|
||||
<div class="flex max-w-4xl max-md:w-screen">
|
||||
<div class="justify-start">
|
||||
<NuxtLink v-if="previous" :onclick="resetReadingPosition" :to="previous"
|
||||
class="m-2 text-white">Previous</NuxtLink>
|
||||
</div>
|
||||
<div class="justify-end">
|
||||
<NuxtLink v-if="next" :onclick="resetReadingPosition" :to="next"
|
||||
class="m-2 text-white">Next</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Article Content -->
|
||||
<Card class="text-pretty max-w-4xl mt-4 max-md:w-screen text-left">
|
||||
<article>
|
||||
<div v-if="markdown != null">
|
||||
<Markdown :input="markdown" />
|
||||
</div>
|
||||
<!-- Aligned next/prev controls -->
|
||||
<div class="flex">
|
||||
<div class="justify-start">
|
||||
<NuxtLink v-if="previous" :onclick="resetReadingPosition" :to="previous"
|
||||
class="m-2 text-white">Previous</NuxtLink>
|
||||
</div>
|
||||
<div class="justify-end">
|
||||
<NuxtLink v-if="next" :onclick="resetReadingPosition" :to="next"
|
||||
class="m-2 text-white">Next</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</Card>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
91
pages/article/index.vue
Normal file
91
pages/article/index.vue
Normal file
|
@ -0,0 +1,91 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted, watch, ref } from 'vue';
|
||||
import fm from 'front-matter';
|
||||
|
||||
import PostCard from '~/components/PostCard.vue';
|
||||
import * as pages from '~/utils/page_updater/update_pagelist';
|
||||
import type { PageInfo, PageInfoMetdata } from '~/utils/page_updater/pages';
|
||||
import type { ParsedContent } from '@nuxt/content';
|
||||
|
||||
// Automatically maintained is a blog_list.json in assets/meta. This file contains a list of all blog posts and their metadata.
|
||||
// This file is generated by a script in the utils/pageupdater folder.
|
||||
const article_list: pages.PageList = await import('~/assets/meta/blog_list.json') as pages.PageList;
|
||||
|
||||
let route = useRoute()
|
||||
console.log(route)
|
||||
|
||||
const loading: Ref<boolean> = ref(false)
|
||||
|
||||
const listCategoryKeys: Ref<string[]> = ref([])
|
||||
|
||||
const tagList: Ref<string[]> = ref([])
|
||||
const tagFilter: Ref<string[]> = ref([])
|
||||
tagFilter.value = []
|
||||
|
||||
function resetReadingPosition() {
|
||||
window.scrollTo(0, 0)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// Extract the tags from each post in each category
|
||||
var tags: string[] = []
|
||||
for (const category in article_list.categories) {
|
||||
console.log("Category: " + category)
|
||||
for (const post of article_list.categories[category].posts) {
|
||||
if (post.metadata.tags) {
|
||||
for (const tag of post.metadata.tags) {
|
||||
if (!tags.includes(tag)) {
|
||||
console.log("Adding tag: " + tag)
|
||||
tags.push(tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tagList.value = tags
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative z-50 flex w-full justify-center text-white">
|
||||
<!-- Metadata -->
|
||||
<MetaSet title="Articles" description="Ramblings." background="https://avatars.githubusercontent.com/u/94077364?v=4"
|
||||
tags="blog, personal, author" />
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="mt-8 flex-col text-center">
|
||||
<Transition name="list">
|
||||
<div>
|
||||
<!-- Article List -->
|
||||
<h1>Articles</h1>
|
||||
<div class="flex justify-center">
|
||||
|
||||
<div class="flex flex-wrap justify-center m-5 max-w-96">
|
||||
<div v-for="tag in tagList" :key="tag" class="m-1">
|
||||
<button
|
||||
@click="tagFilter.includes(tag) ? tagFilter.splice(tagFilter.indexOf(tag), 1) : tagFilter.push(tag)"
|
||||
class="text-xs bg-black border-purple-400 border text-white p-1 rounded-md"
|
||||
:class="tagFilter.includes(tag) ? 'border-2 border-white bg-slate-700' : 'border-2 bg-black text-white'">{{
|
||||
tag }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div v-for="categoryKey in Object.keys(article_list.categories)" :key="categoryKey">
|
||||
<div class="lg:w-[48rem] md:w-max flex flex-col bg-secondary bg-opacity-50 rounded-md shadow-md shadow-secondary p-2 m-2">
|
||||
<h2>{{ categoryKey }}</h2>
|
||||
<div
|
||||
v-for="post in tagFilter.length == 0 ? article_list.categories[categoryKey].posts : article_list.categories[categoryKey].posts.filter((post) => post.metadata.tags ? post.metadata.tags.some((tag) => tagFilter.includes(tag)) : true)">
|
||||
<PostCard class="lg:w-[48rem]" :url="post.url" :key="post.id" :tagFilter="tagFilter" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
Loading…
Add table
Add a link
Reference in a new issue