generated from Templates/Baseline
add blog feature to docs (#101)
### 📖 Summary - adds blog index page with card layout - loads markdown pages in `posts/**/*.md` ### 📑 Test Plan ✅ CI pipeline tests (Default) ### 💬 Details _No response_ ### 📚 Additional Notes _No response_ Reviewed-on: #101
This commit is contained in:
parent
666c9503b7
commit
8e8febb936
@ -14,6 +14,7 @@ function getItems(version) {
|
||||
|
||||
return [
|
||||
{ text: 'Home', link: '/' },
|
||||
{ text: 'Blog', link: '/blog' },
|
||||
{ text: 'Guide', link: '/guide/about' },
|
||||
{
|
||||
text: nver,
|
||||
|
51
docs/.vitepress/theme/components/Blog.vue
Normal file
51
docs/.vitepress/theme/components/Blog.vue
Normal file
@ -0,0 +1,51 @@
|
||||
<script setup>
|
||||
import Posts from './Posts.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="blog-container">
|
||||
<h1>Blog</h1>
|
||||
<h2>⭐ Featured Articles</h2>
|
||||
<Posts featured/>
|
||||
<h2>📰 All Posts</h2>
|
||||
<Posts/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.blog-container {
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
max-width: 1280px;
|
||||
padding: 0 64px;
|
||||
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
position: relative;
|
||||
font-weight: 600;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
h1 {
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 40px;
|
||||
font-size: 32px;
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 40px 0 16px;
|
||||
border-top: 1px solid var(--vp-c-divider);
|
||||
padding-top: 24px;
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 32px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 32px 0 0;
|
||||
letter-spacing: -0.01em;
|
||||
font-size: 20px;
|
||||
}
|
||||
</style>
|
142
docs/.vitepress/theme/components/Post.vue
Normal file
142
docs/.vitepress/theme/components/Post.vue
Normal file
@ -0,0 +1,142 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { withBase } from 'vitepress'
|
||||
import Badge from 'vitepress/dist/client/theme-default/components/VPBadge.vue'
|
||||
|
||||
const props = defineProps({
|
||||
image: {
|
||||
type: String,
|
||||
default: 'placeholder.jpg',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
default: 'no-tag',
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
featured: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
date: {
|
||||
type: String,
|
||||
default: '2020-01-01'
|
||||
}
|
||||
})
|
||||
|
||||
const normTitle = computed(() => {
|
||||
if (props.title.length > 50) {
|
||||
return props.title.slice(0, 50) + '...'
|
||||
} else {
|
||||
return props.title
|
||||
}
|
||||
})
|
||||
|
||||
const normImage = computed(() => {
|
||||
if (props.image !== null) return withBase(props.image)
|
||||
else {
|
||||
return withBase('placeholder.jpg')
|
||||
}
|
||||
})
|
||||
|
||||
const normTag = computed(() => {
|
||||
if (props.tag !== null) return props.tag.toUpperCase()
|
||||
else {
|
||||
return 'EMPTY-TAG'
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article class="card">
|
||||
<div class="card-header">
|
||||
<img :src="normImage" />
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<div class="badge-container">
|
||||
<Badge :text="normTag" type="tip" />
|
||||
</div>
|
||||
<h3>{{ normTitle }}</h3>
|
||||
<a :href="url">Read More</a>
|
||||
</div>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.card {
|
||||
margin: 15px;
|
||||
padding: 0px;
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
border-color: var(--vp-c-brand-2);
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-radius: 10px;
|
||||
width: 325px;
|
||||
/*height: 450px; */
|
||||
overflow: hidden;
|
||||
box-shadow: 0px 8px 16px var(--vp-c-brand-soft);
|
||||
position: relative;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
filter: brightness(125%);
|
||||
transition: 0.25s;
|
||||
box-shadow: 0px 16px 32px var(--vp-c-brand-soft);
|
||||
/*top: -10px;*/
|
||||
}
|
||||
|
||||
.card-header {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
}
|
||||
.card-header img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
padding: 10px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.card-content h3 {
|
||||
margin-top: 5px;
|
||||
height: 90px;
|
||||
}
|
||||
|
||||
.badge-container {
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
position: relative;
|
||||
font-weight: 600;
|
||||
outline: none;
|
||||
|
||||
margin: 32px 0 0;
|
||||
letter-spacing: -0.01em;
|
||||
line-height: 28px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: var(--vp-c-brand-1);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
transition: color 0.025s, opacity 0.25s;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--vp-c-brand-2);
|
||||
}
|
||||
</style>
|
53
docs/.vitepress/theme/components/Posts.vue
Normal file
53
docs/.vitepress/theme/components/Posts.vue
Normal file
@ -0,0 +1,53 @@
|
||||
<script setup>
|
||||
import { data } from './posts.data.js'
|
||||
import Post from './Post.vue'
|
||||
|
||||
const props = defineProps({
|
||||
tagFilter: {
|
||||
type: String,
|
||||
default: 'none',
|
||||
},
|
||||
featured: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
|
||||
const posts = data.filter((el) => {
|
||||
if (!props.featured) {
|
||||
if (props.tagFilter.toLowerCase() === 'none') {
|
||||
return true
|
||||
} else if (props.tagFilter.toLowerCase() === el.frontmatter.tag.toLowerCase()) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if (el.frontmatter.featured) {
|
||||
return true
|
||||
} else return false
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="card-container">
|
||||
<Post
|
||||
:image="post.frontmatter.image"
|
||||
:title="post.frontmatter.title"
|
||||
:tag="post.frontmatter.tag"
|
||||
:url="post.url"
|
||||
:date="post.frontmatter.date"
|
||||
v-for="post in posts"
|
||||
/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.card-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
}
|
||||
</style>
|
10
docs/.vitepress/theme/components/posts.data.js
Normal file
10
docs/.vitepress/theme/components/posts.data.js
Normal file
@ -0,0 +1,10 @@
|
||||
import { createContentLoader } from 'vitepress'
|
||||
|
||||
export default createContentLoader('posts/**/*.md', {
|
||||
excerpt: false,
|
||||
transform(raw) {
|
||||
return raw.sort((a, b) => {
|
||||
return +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date)
|
||||
})
|
||||
}
|
||||
})
|
@ -3,6 +3,8 @@ import { h } from 'vue'
|
||||
import DefaultTheme from 'vitepress/theme'
|
||||
import './style.css'
|
||||
|
||||
import Blog from './components/Blog.vue'
|
||||
|
||||
/** @type {import('vitepress').Theme} */
|
||||
export default {
|
||||
extends: DefaultTheme,
|
||||
@ -12,6 +14,6 @@ export default {
|
||||
})
|
||||
},
|
||||
enhanceApp({ app, router, siteData }) {
|
||||
// ...
|
||||
}
|
||||
app.component('blog', Blog)
|
||||
},
|
||||
}
|
||||
|
3
docs/blog.md
Normal file
3
docs/blog.md
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
layout: blog
|
||||
---
|
12
docs/posts/2024/next-release.md
Normal file
12
docs/posts/2024/next-release.md
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
author: OCram85
|
||||
title: 'Working on Arkanum 2.0.0'
|
||||
tag: 'roadmap'
|
||||
image: 'screens/screen1.png'
|
||||
date: '2024-06-06'
|
||||
---
|
||||
|
||||
# Working on Arkanum 2.0
|
||||
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Rerum dolorum ab optio, dolore saepe accusamus
|
||||
au
|
BIN
docs/public/placeholder.jpg
Normal file
BIN
docs/public/placeholder.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.6 KiB |
Loading…
x
Reference in New Issue
Block a user