Order articles by date DESC
This commit is contained in:
+13
-7
@@ -1,13 +1,19 @@
|
||||
import { defineContentConfig, defineCollection } from '@nuxt/content'
|
||||
import { defineContentConfig, defineCollection, z } from '@nuxt/content'
|
||||
|
||||
// Lookup resolved from path: rootDir/content
|
||||
// see: https://github.com/nuxt/content/issues/3161
|
||||
|
||||
export default defineContentConfig({
|
||||
collections: {
|
||||
content: defineCollection({
|
||||
type: "page",
|
||||
source: "**/*.md"
|
||||
})
|
||||
}
|
||||
collections: {
|
||||
content: defineCollection({
|
||||
type: "page",
|
||||
source: "**/*.md",
|
||||
schema: z.object({
|
||||
date: z.date(),
|
||||
img: z.string(),
|
||||
sub: z.string(),
|
||||
tags: z.array(z.string()),
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
title: "My First Blog Post"
|
||||
description: "This is a test article."
|
||||
navigation: true
|
||||
sub: "C++20, GLSL, Lua"
|
||||
img: "/img/personal-website/login.png"
|
||||
date: "2025-03-01"
|
||||
---
|
||||
|
||||
Foobarbazbuz.
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
---
|
||||
title: "Personal Website"
|
||||
description: "Open-source content management system."
|
||||
description: "An open-source content management system, used for this website."
|
||||
navigation: false
|
||||
sub: "PHP 7, MySQL, jQuery"
|
||||
img: "/img/personal-website/admin-menu.png"
|
||||
date: "2025-03-03"
|
||||
---
|
||||
|
||||
<small>Open-source content management system.<br>
|
||||
@@ -25,18 +28,18 @@ Features:
|
||||
- CMS with CRUD functions for managing data
|
||||
- ORM for mapping between PHP classes and data
|
||||
- Login system
|
||||
- Stay logged in using cookies
|
||||
- Forget password with a generated link send using mail
|
||||
- Stay logged in using cookies
|
||||
- Forget password with a generated link send using mail
|
||||
- Security mitigations
|
||||
- Password hashing using BCrypt
|
||||
- Per-user cryptographically secure generated salt
|
||||
- SQL injection protection using prepared statements
|
||||
- XSS
|
||||
- Cookies set to 'HttpOnly'
|
||||
- Escape rendered user input using: `htmlentities(ENT_QUOTES | ENT_HTML5, 'UTF-8');`
|
||||
- CSRF
|
||||
- Cookies 'SameSite' set to 'Strict'
|
||||
- Token for each session used in POST/PUT/DELETE requests
|
||||
- Password hashing using BCrypt
|
||||
- Per-user cryptographically secure generated salt
|
||||
- SQL injection protection using prepared statements
|
||||
- XSS
|
||||
- Cookies set to 'HttpOnly'
|
||||
- Escape rendered user input using: `htmlentities(ENT_QUOTES | ENT_HTML5, 'UTF-8');`
|
||||
- CSRF
|
||||
- Cookies 'SameSite' set to 'Strict'
|
||||
- Token for each session used in POST/PUT/DELETE requests
|
||||
- Bootstrap
|
||||
- jQuery
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
---
|
||||
title: "My Second Blog Post"
|
||||
description: "This is another article."
|
||||
navigation: false
|
||||
sub: "Bash"
|
||||
img: "/img/personal-website/reset-password.png"
|
||||
date: "2025-03-02"
|
||||
---
|
||||
|
||||
This is another article.
|
||||
|
||||
@@ -26,7 +26,3 @@ body {
|
||||
|
||||
/* Main content */
|
||||
/*----------------------------------------*/
|
||||
|
||||
a:hover {
|
||||
color: var(--bs-link-color) !important;
|
||||
}
|
||||
|
||||
@@ -29,11 +29,11 @@
|
||||
|
||||
/* Select any <a> inside a <h> */
|
||||
:deep(:is(h1, h2, h3, h4, h5, h6) a) {
|
||||
color: inherit;
|
||||
color: var(--bs-body-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Select <pre class="shiki"> */
|
||||
/* Select <pre class="language-"> */
|
||||
:deep(pre[class^="language-"]) {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -54,8 +54,7 @@
|
||||
|
||||
/* Select <code> */
|
||||
:deep(code:not([class^="language-"]):not(pre code)) {
|
||||
/* reset font to black */
|
||||
color: inherit;
|
||||
color: var(--bs-body-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -1,18 +1,47 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Articles</h1>
|
||||
<ul>
|
||||
<li v-for="article in articles" :key="article.path">
|
||||
<NuxtLink :to="article.path">{{ article.title }}</NuxtLink>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div v-for="article in articles" :key="article.path">
|
||||
<pre>{{ article }}</pre>
|
||||
<div class="row pt-5" v-for="article in articles" :key="article.path">
|
||||
<div class="col-5 col-lg-4 col-xl-3">
|
||||
<NuxtLink v-if="article.img" :to="article.path">
|
||||
<img class="img-fluid" :src="article.img as string" :alt="article.title" loading="lazy" :title="article.title">
|
||||
</NuxtLink>
|
||||
</div>
|
||||
<div class="col-7 col-lg-8 col-xl-9">
|
||||
<NuxtLink v-if="article.img" :to="article.path">
|
||||
<h4><strong>{{ article.title }}</strong></h4>
|
||||
</NuxtLink>
|
||||
{{ article.description }}<br>
|
||||
<i><small>{{ article.sub }}</small></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="isDev">
|
||||
<br>
|
||||
<div v-for="article in articles" :key="article.path">
|
||||
<pre>{{ article }}</pre>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
a {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
a h4 {
|
||||
color: var(--bs-body-color);
|
||||
}
|
||||
|
||||
a h4:hover {
|
||||
color: var(--bs-link-hover-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
<script setup lang="ts">
|
||||
const { data: articles } = await useAsyncData("articles", () => queryCollection("content").all())
|
||||
import { useAsyncData, queryCollection } from "#imports";
|
||||
|
||||
const { data: articles } = await useAsyncData("articles", () => queryCollection("content").order("date", "DESC").all())
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export const isDev = process.env.NODE_ENV === "development";
|
||||
Reference in New Issue
Block a user