Compare commits

...

2 Commits

  1. 3
      content.config.ts
  2. 7
      content/articles/first.md
  3. 7
      content/articles/personal-website.md
  4. 5
      content/articles/second.md
  5. 15
      src/components/content/prose-img.vue
  6. 1
      src/pages/articles/[slug].vue
  7. 19
      src/pages/articles/index.vue
  8. 37
      src/utils/index.ts

3
content.config.ts

@ -11,9 +11,8 @@ export default defineContentConfig({
schema: z.object({ schema: z.object({
date: z.date(), date: z.date(),
img: z.string(), img: z.string(),
sub: z.string(),
tags: z.array(z.string()), tags: z.array(z.string()),
}) })
}) })
} }
}) });

7
content/articles/first.md

@ -2,9 +2,12 @@
title: "My First Blog Post" title: "My First Blog Post"
description: "This is a test article." description: "This is a test article."
navigation: true navigation: true
sub: "C++20, GLSL, Lua"
img: "/img/personal-website/login.png"
date: "2025-03-01" date: "2025-03-01"
img: "/img/personal-website/login.png"
tags:
- C++20
- GLSL
- Lua
--- ---
Foobarbazbuz. Foobarbazbuz.

7
content/articles/personal-website.md

@ -2,9 +2,12 @@
title: "Personal Website" title: "Personal Website"
description: "An open-source content management system, used for this website." description: "An open-source content management system, used for this website."
navigation: false navigation: false
sub: "PHP 7, MySQL, jQuery"
img: "/img/personal-website/admin-menu.png"
date: "2025-03-03" date: "2025-03-03"
img: "/img/personal-website/admin-menu.png"
tags:
- PHP 7
- MySQL
- jQuery
--- ---
<small>Open-source content management system.<br> <small>Open-source content management system.<br>

5
content/articles/second.md

@ -2,9 +2,10 @@
title: "My Second Blog Post" title: "My Second Blog Post"
description: "This is another article." description: "This is another article."
navigation: false navigation: false
sub: "Bash"
img: "/img/personal-website/reset-password.png"
date: "2025-03-02" date: "2025-03-02"
img: "/img/personal-website/reset-password.png"
tags:
- Bash
--- ---
This is another article. This is another article.

15
src/components/content/prose-img.vue

@ -8,8 +8,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { withTrailingSlash, withLeadingSlash, joinURL } from "ufo" import { computed } from "#imports"
import { useRuntimeConfig, computed } from "#imports"
import ImageComponent from "#build/mdc-image-component.mjs" import ImageComponent from "#build/mdc-image-component.mjs"
@ -43,17 +42,11 @@ const props = defineProps({
type: String, type: String,
default: "lazy" // eager, lazy default: "lazy" // eager, lazy
}, },
}) });
const refinedSrc = computed(() => { const refinedSrc = computed(() => {
if (props.src?.startsWith("/") && !props.src.startsWith("//")) { return getPublicPath(props.src);
const _base = withLeadingSlash(withTrailingSlash(useRuntimeConfig().app.baseURL)) });
if (_base !== "/" && !props.src.startsWith(_base)) {
return joinURL(_base, props.src)
}
}
return props.src
})
</script> </script>
<!-- <!--

1
src/pages/articles/[slug].vue

@ -4,6 +4,7 @@
<ArticlesTableOfContents v-if="article.navigation" :toc="article.body.toc" /> <ArticlesTableOfContents v-if="article.navigation" :toc="article.body.toc" />
<h1>{{ article.title }}</h1> <h1>{{ article.title }}</h1>
<p><i><small>{{ prettyDate(article.date) }}</small></i></p>
<ContentRenderer :value="article" /> <ContentRenderer :value="article" />
</template> </template>
<template v-else> <template v-else>

19
src/pages/articles/index.vue

@ -5,15 +5,18 @@
<div class="row pt-5" v-for="article in articles" :key="article.path"> <div class="row pt-5" v-for="article in articles" :key="article.path">
<div class="col-5 col-lg-4 col-xl-3"> <div class="col-5 col-lg-4 col-xl-3">
<NuxtLink v-if="article.img" :to="article.path"> <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"> <img class="img-fluid" :src="getPublicPath(article.img)" :alt="article.title" loading="lazy" :title="article.title">
</NuxtLink> </NuxtLink>
</div> </div>
<div class="col-7 col-lg-8 col-xl-9"> <div class="col-7 col-lg-8 col-xl-9">
<NuxtLink v-if="article.img" :to="article.path"> <NuxtLink v-if="article.img" :to="article.path">
<h4><strong>{{ article.title }}</strong></h4> <h4 class="mb-0"><strong>{{ article.title }}</strong></h4>
</NuxtLink> </NuxtLink>
{{ article.description }}<br> <p><i><small>{{ prettyDate(article.date) }}</small></i></p>
<i><small>{{ article.sub }}</small></i> <p>{{ article.description }}</p>
<template v-if="article.tags">
<p>Tags: <code>{{ article.tags.join(", ") }}</code></p>
</template>
</div> </div>
</div> </div>
@ -38,10 +41,14 @@ a h4 {
a h4:hover { a h4:hover {
color: var(--bs-link-hover-color); color: var(--bs-link-hover-color);
} }
code {
color: var(--bs-link-color);
}
</style> </style>
<script setup lang="ts"> <script setup lang="ts">
import { useAsyncData, queryCollection } from "#imports"; import { useAsyncData, queryCollection } from "#imports"
const { data: articles } = await useAsyncData("articles", () => queryCollection("content").order("date", "DESC").all()) const { data: articles } = await useAsyncData("articles", () => queryCollection("content").order("date", "DESC").all());
</script> </script>

37
src/utils/index.ts

@ -1 +1,38 @@
import { withTrailingSlash, withLeadingSlash, joinURL } from "ufo"
import { useRuntimeConfig } from "#imports"
/**
* Returns if environment is in development mode
*/
export const isDev = process.env.NODE_ENV === "development"; export const isDev = process.env.NODE_ENV === "development";
/**
* Gets URL path, taking into acount the baseURL
*/
export const getPublicPath = function (path: string): string {
if (path?.startsWith("/") && !path.startsWith("//")) {
const _base = withLeadingSlash(withTrailingSlash(useRuntimeConfig().app.baseURL));
if (_base !== "/" && !path.startsWith(_base)) {
return joinURL(_base, path);
}
}
return path;
}
/**
* Return date string in format "Feb 10, 2025"
*/
export const prettyDate = function (date: string | Date): string {
if (typeof date === "string") {
date = new Date(date);
}
const formatted = new Intl.DateTimeFormat("en-US", {
month: "short",
day: "numeric",
year: "numeric"
}).format(date);
return formatted;
}

Loading…
Cancel
Save