diff --git a/assets/styles/components/_blog.scss b/assets/styles/components/_blog.scss index 4f72c70..658f22e 100644 --- a/assets/styles/components/_blog.scss +++ b/assets/styles/components/_blog.scss @@ -222,4 +222,53 @@ display: inline-block; } } + + &-archives { + margin: 50px 0; + &__year { + margin-bottom: 1em; + font-size: 0.85em; + text-decoration: none; + text-transform: uppercase; + letter-spacing: 2px; + margin-left: 5px; + line-height: 1em; + + a { + color: #999; + text-shadow: 0 1px #fff; + font-weight: bold; + } + } + + &__posts { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1.5rem; + } + + &__time { + color: #999 !important; + text-decoration: none; + font-size: 0.85em; + line-height: 1em; + margin-bottom: 0.5em; + display: block; + } + + &__post { + padding: 20px; + background-color: #fff; + + header { + display: flex; + flex-direction: column; + height: 100%; + + h1 { + margin-top: auto; + } + } + } + } } diff --git a/components/blog-archive.vue b/components/blog-archive.vue new file mode 100644 index 0000000..a6a8719 --- /dev/null +++ b/components/blog-archive.vue @@ -0,0 +1,81 @@ + + + diff --git a/components/blog-post.vue b/components/blog-post.vue index 029d205..f128e34 100644 --- a/components/blog-post.vue +++ b/components/blog-post.vue @@ -1,11 +1,11 @@
- #{{ tag }}
@@ -34,5 +34,7 @@ diff --git a/components/icon-link-list.vue b/components/icon-link-list.vue index f7f297c..f872d2a 100644 --- a/components/icon-link-list.vue +++ b/components/icon-link-list.vue @@ -3,8 +3,10 @@

{{ title }}

diff --git a/layouts/blog.vue b/layouts/blog.vue index 28d93dd..4a1ddcc 100644 --- a/layouts/blog.vue +++ b/layouts/blog.vue @@ -1,7 +1,16 @@ diff --git a/lib/blog/read-posts.ts b/lib/blog/read-posts.ts index 8e18d8e..c4746c7 100644 --- a/lib/blog/read-posts.ts +++ b/lib/blog/read-posts.ts @@ -4,6 +4,7 @@ import yaml from 'yaml'; import { marked } from 'marked'; import hljs from 'highlight.js'; import { getDateObject } from '../utils/date-object'; +import { BlogPost, BlogPostTag } from '../types/post'; const dir = join('content', 'blog'); @@ -14,11 +15,16 @@ marked.use({ const created = hljs.highlight(code, { language }).value; return `
${created}
`; }, + link: (href: string, title: string, text: string): string => { + return `${text}`; + }, }, }); export async function readBlogPosts( - condition?: (body: any) => boolean, + condition?: (body: BlogPost) => boolean, render = true, includeContent = true ) { @@ -45,10 +51,10 @@ export async function readBlogPosts( export async function readBlogPost( slug: string, - condition?: (body: any) => boolean, + condition?: (body: BlogPost) => boolean, render = true, includeContent = true -): Promise { +): Promise { const decoded = decodeURIComponent(slug); if (!slug || decoded.includes('/') || decoded.includes('.')) throw new Error('Invalid post slug'); @@ -80,9 +86,9 @@ export async function readBlogPost( return content; } -export async function getTags() { +export async function getTags(): Promise { const posts = await readBlogPosts(undefined, false, false); - const obj = []; + const obj: BlogPostTag[] = []; for (const post of posts) { for (const tag of post.tags || []) { @@ -104,8 +110,8 @@ export async function getTags() { return obj; } -export async function getArchiveTree() { - const posts = await readBlogPosts(undefined, false, false); +export async function getArchiveTree(condition?: (body: BlogPost) => boolean) { + const posts = await readBlogPosts(condition, false, false); const obj = {}; for (const post of posts) { diff --git a/lib/types/post.ts b/lib/types/post.ts new file mode 100644 index 0000000..2c5adf0 --- /dev/null +++ b/lib/types/post.ts @@ -0,0 +1,16 @@ +export interface BlogPost { + date: string; + title: string; + tags: string[]; + file: string; + slug: string; + fullSlug: string; + markdown: string; + html: string; +} + +export interface BlogPostTag { + name: string; + count: number; + posts: string[]; +} diff --git a/lib/utils/date-object.ts b/lib/utils/date-object.ts index 8f0db77..5d58bed 100644 --- a/lib/utils/date-object.ts +++ b/lib/utils/date-object.ts @@ -1,4 +1,6 @@ -export function getDateObject(post) { +import { BlogPost } from '../types/post'; + +export function getDateObject(post: BlogPost) { const date = new Date(post.date); const year = date.getFullYear(); const month = (date.getMonth() + 1).toString().padStart(2, '0'); diff --git a/pages/blog/[year]/[month]/[day]/[slug].vue b/pages/blog/[year]/[month]/[day]/[slug].vue index c44ac2d..8573715 100644 --- a/pages/blog/[year]/[month]/[day]/[slug].vue +++ b/pages/blog/[year]/[month]/[day]/[slug].vue @@ -1,10 +1,44 @@ diff --git a/pages/blog/archive/[year]/[month]/[day]/index.vue b/pages/blog/archive/[year]/[month]/[day]/index.vue index 9bc55ac..1b08231 100644 --- a/pages/blog/archive/[year]/[month]/[day]/index.vue +++ b/pages/blog/archive/[year]/[month]/[day]/index.vue @@ -1,14 +1,24 @@ diff --git a/pages/blog/archive/[year]/[month]/index.vue b/pages/blog/archive/[year]/[month]/index.vue index 01927d3..c3568aa 100644 --- a/pages/blog/archive/[year]/[month]/index.vue +++ b/pages/blog/archive/[year]/[month]/index.vue @@ -1,14 +1,23 @@ diff --git a/pages/blog/archive/[year]/index.vue b/pages/blog/archive/[year]/index.vue index 264c6ef..61a41d5 100644 --- a/pages/blog/archive/[year]/index.vue +++ b/pages/blog/archive/[year]/index.vue @@ -1,12 +1,22 @@ diff --git a/pages/blog/archive/index.vue b/pages/blog/archive/index.vue new file mode 100644 index 0000000..52603d2 --- /dev/null +++ b/pages/blog/archive/index.vue @@ -0,0 +1,16 @@ + + + diff --git a/pages/blog/tags/[tag].vue b/pages/blog/tags/[tag].vue new file mode 100644 index 0000000..87d3cbe --- /dev/null +++ b/pages/blog/tags/[tag].vue @@ -0,0 +1,22 @@ + + + diff --git a/pages/index.vue b/pages/index.vue index 58fcacc..c668a30 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -140,7 +140,7 @@ const linksList = [ { name: 'Web apps', icon: 'icon-controller-classic', - href: '/apps', + href: 'https://lunasqu.ee/apps', }, { name: 'GnuPG Public Key', diff --git a/server/api/blog/archive.ts b/server/api/blog/archive.ts index 7e87875..4370aba 100644 --- a/server/api/blog/archive.ts +++ b/server/api/blog/archive.ts @@ -1,5 +1,16 @@ import { getArchiveTree } from '~~/lib/blog/read-posts'; export default defineEventHandler(async (event) => { - return getArchiveTree(); + const query = getQuery(event); + const include = (content) => { + if (query.tag) { + if (!content.tags?.length || !content.tags.includes(query.tag)) { + return false; + } + } + + return true; + }; + + return getArchiveTree(include); }); diff --git a/server/api/blog/index.ts b/server/api/blog/index.ts index 665d5b9..f73efe9 100644 --- a/server/api/blog/index.ts +++ b/server/api/blog/index.ts @@ -23,8 +23,18 @@ export default defineEventHandler(async (event) => { } } + if (query.tag) { + if (!content.tags?.length || !content.tags.includes(query.tag)) { + return false; + } + } + return true; }; - return readBlogPosts(include); + return readBlogPosts( + include, + query.render !== 'false', + query.body !== 'false' + ); });