FEAT: Posts are pretty much complete.

Need some handling for images, an error message when no posts are found
or when an issue occurs. I would also like to work on some more modular
styling for the layout.
This commit is contained in:
Hayden Hargreaves 2025-02-24 14:30:10 -07:00
parent 178c07f666
commit f929f08f41
10 changed files with 221 additions and 50 deletions

View File

@ -36,3 +36,17 @@ npm run build
You can preview the production build with `npm run preview`. You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment. > To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
# Create Blog Posts
To create a new post, all you must do is create a new markdown file in the `./src/blog/` directory.
However, before you begin writing, you must first add the following two lines at the top of the
new markdown file:
```markdown
Date: YYYY-MM-DD
Desc: Some short description to post on the index page of the blogs.
```
Below this, you can write your blog post in the markdown format. The metadata above is used for
displaying and parsing the post.

View File

@ -1,4 +1,5 @@
Date: 2025-02-23 Date: 2025-02-23
Desc: Testing the markdown parser with various elements and edge cases.
# H1 Tag # H1 Tag
## H2 Tag ## H2 Tag
### H3 Tag ### H3 Tag

View File

@ -1,4 +1,5 @@
Date: 2025-02-24 Date: 2025-02-24
Desc: A comparison of performance, extensibility, modal editing, community, and popularity.
# Neovim: A Robust Alternative to Visual Studio Code # Neovim: A Robust Alternative to Visual Studio Code
###### Author: Hayden Hargreaves ###### Author: Hayden Hargreaves

View File

@ -1,4 +1,5 @@
Date: 2025-02-24 Date: 2025-02-24
Desc: A silly article from Gemini.
# Diving Deep into the World of Programming: A Journey of Logic and Creativity # Diving Deep into the World of Programming: A Journey of Logic and Creativity
Programming, in its essence, is the art and science of communicating with computers. It's about crafting a precise sequence of instructions, a "program," that dictates every step a machine should take. From the sleek applications on your smartphone to the intricate systems that manage global infrastructure, programming is the invisible hand shaping the technological world we inhabit. It's more than just lines of code; it's the engine of innovation. Programming, in its essence, is the art and science of communicating with computers. It's about crafting a precise sequence of instructions, a "program," that dictates every step a machine should take. From the sleek applications on your smartphone to the intricate systems that manage global infrastructure, programming is the invisible hand shaping the technological world we inhabit. It's more than just lines of code; it's the engine of innovation.

52
src/blog/README.md Normal file
View File

@ -0,0 +1,52 @@
# sv
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
## Creating a project
If you're seeing this, you've probably already done this step. Congrats!
```bash
# create a new project in the current directory
npx sv create
# create a new project in my-app
npx sv create my-app
```
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
```bash
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
To create a production version of your app:
```bash
npm run build
```
You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
# Create Blog Posts
To create a new post, all you must do is create a new markdown file in the `./src/blog/` directory.
However, before you begin writing, you must first add the following two lines at the top of the
new markdown file:
```markdown
Date: YYYY-MM-DD
Desc: Some short description to post on the index page of the blogs.
```
Below this, you can write your blog post in the markdown format. The metadata above is used for
displaying and parsing the post.

View File

@ -0,0 +1,53 @@
import { readdirSync, readFileSync } from 'fs';
// Location of the blogs, all md files should be placed here
const blog_path = process.cwd().concat('/src', '/blog');
/**
* The post object for use in the page.
* @property {string} title - The title of the post.
* @property {string} description - The description of the post.
* @property {string} path - The path to the post for the URL.
* @property {Date} date - The date the post was created.
*/
type Post = {
title: string;
description: string;
path: string;
date: Date;
};
// For this use, we do not need the RequestEvent object
export const load = async () => {
const posts: Post[] = [];
// Read all the files names in the blog directory.
readdirSync(blog_path).forEach(file => {
const content: string = readFileSync(blog_path.concat('/', file), 'utf-8');
// Date: 2025-02-24 -> date object
// Desc: ... -> description
const lines: string[] = content.split("\n");
let date: Date = new Date();
let description: string = "";
// Ensure the meta data is provided
if (lines[0].slice(0, 5) == "Date:" || lines[1].slice(0, 5) == "Desc:") {
date = new Date(lines[0].split("Date:")[1].trim());
description = lines[1].split("Desc:")[1].trim();
}
// Create the post
const post: Post = {
title: file.split('.')[0],
path: '/blog'.concat('/', file.split('.')[0]),
date,
description
}
posts.push(post);
});
return {
posts: posts,
};
};

View File

@ -0,0 +1,38 @@
<script lang="ts">
import type { PageProps } from './$types';
let { data }: PageProps = $props();
// Sort the posts by date, descending
data.posts.sort((a, b) => {
if (a.date > b.date) return -1;
if (a.date < b.date) return 1;
return 0;
});
</script>
<main class="mx-[7.5%] my-[5%] min-h-screen">
<!-- Header -->
<div class="my-8 w-1/2">
<h1 class="font-mono text-6xl font-[900] text-blue-300">Blog Posts.</h1>
<p class="my-5 py-2 text-gray-200 italic">
Here you can find a list of all the blog posts I have written. Some of them are about my
projects, some are about my thoughts, and some are about my experiences. I hope you enjoy!
</p>
</div>
<!-- Posts List -->
<div class="">
{#each data.posts as post}
<div class="group my-5 rounded-sm border-l-4 border-blue-300 px-4">
<h2 class="text-xl">
<a href={post.path} class="group relative inline-block no-underline">
<span class="relative z-10 text-gray-300">{post.title}</span>
<span
class="absolute bottom-0 left-0 h-[3px] w-0 bg-blue-300 transition-all duration-300 group-hover:w-full"
></span>
</a>
</h2>
<p class="text-sm text-gray-400">{post.description}</p>
</div>
{/each}
</div>
</main>

View File

@ -18,9 +18,9 @@ export const load = async ({ url }: RequestEvent) => {
const cleanPath = blogPath.replaceAll("%20", " "); const cleanPath = blogPath.replaceAll("%20", " ");
// Read the file and get the data // Read the file and get the data
let data: string = ""; let content: string = "";
try { try {
data = readFileSync(cleanPath, 'utf-8'); content = readFileSync(cleanPath, 'utf-8');
} catch { } catch {
// Catch and return any errors // Catch and return any errors
return { return {
@ -33,7 +33,19 @@ export const load = async ({ url }: RequestEvent) => {
} }
// Date: 2025-02-24 -> date object // Date: 2025-02-24 -> date object
const date: Date = new Date(data.split("\n")[0].split(":")[1].trim()); // Desc: ... -> description
let lines: string[] = content.split("\n");
let date: Date = new Date();
let description: string = "";
// Ensure the meta data is provided
if (lines[0].slice(0, 5) == "Date:" || lines[1].slice(0, 5) == "Desc:") {
date = new Date(lines[0].split("Date:")[1].trim());
description = lines[1].split("Desc:")[1].trim();
// Remove meta data from final content
lines = lines.slice(2);
}
// Create a marked object that can parse the data // Create a marked object that can parse the data
const marked = new Marked( const marked = new Marked(
@ -50,8 +62,9 @@ export const load = async ({ url }: RequestEvent) => {
return { return {
post: { post: {
// Convert the markdown to HTML. Slice off the first line which is the date of publication. // Convert the markdown to HTML. Slice off the first line which is the date of publication.
// The second line is the description of the post.
// Any other meta data that needs to be cut can be removed by increasing the '1' in the slice. // Any other meta data that needs to be cut can be removed by increasing the '1' in the slice.
content: marked.parse(data.split("\n").slice(1).join("\n")), content: marked.parse(lines.join("\n")),
date: date, date: date,
error: null, error: null,
} }

View File

@ -1,8 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { PageProps } from './$types'; import type { PageProps } from './$types';
let { data }: PageProps = $props(); let { data }: PageProps = $props();
console.log(`Post's date: ${data.post.date.toUTCString()}`);
</script> </script>
{#if data.post.error} {#if data.post.error}