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:
parent
178c07f666
commit
f929f08f41
14
README.md
14
README.md
@ -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.
|
||||||
|
|||||||
88
package.json
88
package.json
@ -1,46 +1,46 @@
|
|||||||
{
|
{
|
||||||
"name": "personalsite",
|
"name": "personalsite",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"prepare": "svelte-kit sync || echo ''",
|
"prepare": "svelte-kit sync || echo ''",
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"lint": "prettier --check . && eslint ."
|
"lint": "prettier --check . && eslint ."
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/compat": "^1.2.5",
|
"@eslint/compat": "^1.2.5",
|
||||||
"@eslint/js": "^9.18.0",
|
"@eslint/js": "^9.18.0",
|
||||||
"@sveltejs/adapter-auto": "^4.0.0",
|
"@sveltejs/adapter-auto": "^4.0.0",
|
||||||
"@sveltejs/adapter-node": "^5.2.12",
|
"@sveltejs/adapter-node": "^5.2.12",
|
||||||
"@sveltejs/kit": "^2.16.0",
|
"@sveltejs/kit": "^2.16.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
"@sveltejs/vite-plugin-svelte": "^5.0.0",
|
||||||
"@tailwindcss/vite": "^4.0.0",
|
"@tailwindcss/vite": "^4.0.0",
|
||||||
"eslint": "^9.18.0",
|
"eslint": "^9.18.0",
|
||||||
"eslint-config-prettier": "^10.0.1",
|
"eslint-config-prettier": "^10.0.1",
|
||||||
"eslint-plugin-svelte": "^2.46.1",
|
"eslint-plugin-svelte": "^2.46.1",
|
||||||
"globals": "^15.14.0",
|
"globals": "^15.14.0",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"prettier-plugin-svelte": "^3.3.3",
|
"prettier-plugin-svelte": "^3.3.3",
|
||||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||||
"svelte": "^5.0.0",
|
"svelte": "^5.0.0",
|
||||||
"svelte-check": "^4.0.0",
|
"svelte-check": "^4.0.0",
|
||||||
"tailwindcss": "^4.0.0",
|
"tailwindcss": "^4.0.0",
|
||||||
"typescript": "^5.0.0",
|
"typescript": "^5.0.0",
|
||||||
"typescript-eslint": "^8.20.0",
|
"typescript-eslint": "^8.20.0",
|
||||||
"vite": "^6.0.0"
|
"vite": "^6.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "^22.13.5",
|
"@types/node": "^22.13.5",
|
||||||
"dompurify": "^3.2.4",
|
"dompurify": "^3.2.4",
|
||||||
"highlight.js": "^11.11.1",
|
"highlight.js": "^11.11.1",
|
||||||
"marked": "^15.0.7",
|
"marked": "^15.0.7",
|
||||||
"marked-highlight": "^2.2.1",
|
"marked-highlight": "^2.2.1",
|
||||||
"path": "^0.12.7"
|
"path": "^0.12.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
@ -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
|
||||||
|
|||||||
@ -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
52
src/blog/README.md
Normal 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.
|
||||||
53
src/routes/blog/+page.server.ts
Normal file
53
src/routes/blog/+page.server.ts
Normal 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,
|
||||||
|
};
|
||||||
|
};
|
||||||
38
src/routes/blog/+page.svelte
Normal file
38
src/routes/blog/+page.svelte
Normal 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>
|
||||||
@ -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,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user