FEAT: Lots of work on the blogs!

Syntax highlighting looks really good so far! Rendering of the markdowns
works when a valid URL is provided, need to work on routing some more.
This commit is contained in:
Hayden Hargreaves 2025-02-23 23:47:24 -07:00
parent 9acb11f6e2
commit 022bd1bcf7
8 changed files with 3437 additions and 4 deletions

BIN
bun.lockb

Binary file not shown.

2859
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -34,5 +34,14 @@
"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": {
"@types/node": "^22.13.5",
"dompurify": "^3.2.4",
"fs": "^0.0.1-security",
"highlight.js": "^11.11.1",
"marked": "^15.0.7",
"marked-highlight": "^2.2.1",
"path": "^0.12.7"
} }
} }

View File

@ -1 +1,79 @@
@import 'tailwindcss'; @import 'tailwindcss';
/* This is very painful. There must be a better way. */
@layer base {
pre {
background-color: #191724;
/* background-color: red; */
/* Or any color you want */
padding: 0.5rem 2rem;
margin-inline: 2%;
/* Adjust padding as needed */
border-radius: 10px;
/* Optional: Add rounded corners */
overflow-x: auto;
/* Handle horizontal overflow if code is wider */
white-space: pre-wrap;
/* Allows code to wrap within the pre element*/
}
code.hljs {
color: #e0def4;
}
.hljs-string,
.hljs-number,
.hljs-meta {
color: #f6c177;
}
.hljs-punctuation,
.hljs-operator {
color: #908caa;
}
.hljs-comment {
color: #6e6a86;
}
.hljs-keyword {
color: #31748f;
}
.hljs-params,
.hljs-method,
.hljs-methods,
.hljs-regexp,
code.language-python .hljs-meta {
color: #c4a7e7;
}
.hljs-variable,
.hljs-attr {
color: #e0def4;
}
.language_ {
color: #eb6f92;
}
.function_,
.hljs-literal,
.hljs-built_in,
.hljs-title,
code.language-python .hljs-built_in,
code.language-go .hljs-built_in {
color: #ebbcba;
}
.hljs-property,
.class_,
.hljs-type,
.hljs-tag,
.hljs-selector-tag,
.hljs-selector-class,
code.language-ts .hljs-built_in {
color: #9ccfd8;
}
}

415
src/blog/postOne.md Normal file
View File

@ -0,0 +1,415 @@
# This is a blog post
This is a blog post about something. It's really interesting. I hope you enjoy it.
My favorite color is red.
```js
// JavaScript
// Function with parameters and return value
function greet(name, greeting = "Hello") {
return `${greeting}, ${name}!`;
}
// Arrow function
const multiply = (a, b) => a * b;
// Object literal
const person = {
name: "Alice",
age: 30,
greet: function() {
console.log(`My name is ${this.name}.`);
}
};
// Array methods
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2);
// Promises and async/await
async function fetchData() {
const response = await fetch('https://example.com/data');
const data = await response.json();
return data;
}
// Class definition
class Dog {
constructor(name, breed) {
this.name = name;
this.breed = breed;
}
bark() {
console.log("Woof!");
}
}
// Comments: single-line and multi-line
// This is a single-line comment.
/*
This is a
multi-line comment.
*/
// Regular expressions
const regex = /^[a-zA-Z]+$/;
// Destructuring
const { name, age } = person;
// Template literals
const message = `Name: ${name}, Age: ${age}`;
// TypeScript (If your highlighter supports it)
// interface Person {
// name: string;
// age: number;
// }
// function greet(person: Person): string {
// return `Hello, ${person.name}!`;
// }
```
```json
{
"name": "John Doe",
"age": 30
}
```
```html
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<h1>Hello world</h1>
</body>
```
```css
@import 'tailwindcss';
/* This is very painful. There must be a better way. */
@layer base {
pre {
background-color: #191724;
/* background-color: red; */
/* Or any color you want */
padding: 0.5rem 2rem;
margin-inline: 2%;
/* Adjust padding as needed */
border-radius: 10px;
/* Optional: Add rounded corners */
overflow-x: auto;
/* Handle horizontal overflow if code is wider */
white-space: pre-wrap;
/* Allows code to wrap within the pre element*/
}
code.hljs {
color: #e0def4;
}
.hljs-string,
.hljs-number,
.hljs-meta {
color: #f6c177;
}
.hljs-punctuation,
.hljs-operator {
color: #908caa;
}
.hljs-comment {
color: #6e6a86;
}
.hljs-keyword {
color: #31748f;
}
.hljs-params {
color: #c4a7e7;
}
.hljs-variable,
.hljs-attr {
color: #e0def4;
}
.language_ {
color: #eb6f92;
}
.function_,
.hljs-literal,
.hljs-built_in,
.hljs-title,
code.language-python .hljs-built_in,
code.language-go .hljs-built_in {
color: #ebbcba;
}
.hljs-property,
.class_,
.hljs-type,
.hljs-tag,
.hljs-selector-tag,
code.language-ts .hljs-built_in {
color: #9ccfd8;
}
}
```
```rs
fn main() {
// A simple function to add two numbers
fn add(a: i32, b: i32) -> i32 {
a + b
}
// A struct representing a point in 2D space
struct Point {
x: f64,
y: f64,
}
impl Point {
// Method to calculate the distance from the origin
fn distance_from_origin(&self) -> f64 {
(self.x * self.x + self.y * self.y).sqrt()
}
}
// Example usage
let num1 = 10;
let num2 = 20;
let sum = add(num1, num2);
println!("The sum of {} and {} is {}", num1, num2, sum);
let point = Point { x: 3.0, y: 4.0 };
let distance = point.distance_from_origin();
println!("The distance of the point from the origin is {}", distance);
// Demonstrating a for loop
for i in 0..5 {
println!("Value of i: {}", i);
}
// Example of a vector
let mut my_vector = vec![1, 2, 3];
my_vector.push(4);
println!("My vector: {:?}", my_vector);
// Using a Result to handle potential errors
fn divide(a: i32, b: i32) -> Result<i32, String> {
if b == 0 {
Err("Cannot divide by zero".to_string())
} else {
Ok(a / b)
}
}
let result = divide(10, 2);
match result {
Ok(value) => println!("Result of division: {}", value),
Err(error) => println!("Error: {}", error),
}
let result2 = divide(10, 0);
match result2 {
Ok(value) => println!("Result of division: {}", value),
Err(error) => println!("Error: {}", error),
}
// Example of a closure
let square = |x: i32| -> i32 { x * x };
println!("Square of 5: {}", square(5));
// String manipulation
let my_string = "Hello, world!".to_string();
let greeting = format!("Greeting: {}", my_string);
println!("{}", greeting);
// Option example
let optional_value: Option<i32> = Some(42);
match optional_value {
Some(value) => println!("Optional value: {}", value),
None => println!("No value present"),
}
}
```
```python
# Python
# Function definition
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"
# List comprehension
numbers = [1, 2, 3, 4, 5]
doubled = [num * 2 for num in numbers]
# Dictionary
person = {
"name": "Alice",
"age": 30,
"greet": lambda self: print(f"My name is {self['name']}."),
}
# Class definition
class Dog:
def __init__(self, name, breed):
self.name = name
self.breed = breed
def bark(self):
print("Woof!")
# Comments: single-line and multi-line
# This is a single-line comment.
"""
This is a
multi-line comment.
"""
# Try-except block
try:
result = 10 / 0
except ZeroDivisionError:
print("Cannot divide by zero.")
# For loop
for i in range(5):
print(f"Value of i: {i}")
# While loop
count = 0
while count < 3:
print(f"Count: {count}")
count += 1
# String formatting
message = "Name: {}, Age: {}".format(person["name"], person["age"])
# f-strings (formatted string literals)
message2 = f"Name: {person['name']}, Age: {person['age']}"
# List slicing
my_list = [10, 20, 30, 40, 50]
slice_of_list = my_list[1:4]
# Tuple unpacking
coordinates = (10, 20)
x, y = coordinates
# Decorators
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
```
```java
// Java
// Class definition
public class Main {
// Main method
public static void main(String[] args) {
// Variables and data types
int age = 30;
String name = "Alice";
double height = 5.8;
boolean isStudent = true;
// Conditional statement
if (age >= 18) {
System.out.println("Adult");
} else {
System.out.println("Minor");
}
// Loops
for (int i = 0; i < 5; i++) {
System.out.println("Value of i: " + i);
}
// While loop
int count = 0;
while (count < 3) {
System.out.println("Count: " + count);
count++;
}
// Arrays
int[] numbers = {1, 2, 3, 4, 5};
// Methods
greet(name);
// Object creation
Person person = new Person(name, age);
person.greet();
// Try-catch block
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero.");
}
// Comments: single-line and multi-line
// This is a single-line comment.
/*
This is a
multi-line comment.
*/
// String concatenation
String message = "Hello, " + name + "!";
System.out.println(message);
}
// Method definition
public static void greet(String name) {
System.out.println("Hello, " + name + "!");
}
}
// Class definition
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void greet() {
System.out.println("My name is " + this.name + ".");
}
}
```

View File

@ -1,7 +1,3 @@
<script>
console.log('navbar.svelte');
</script>
<nav class="flex border-b-1 border-gray-700 py-6"> <nav class="flex border-b-1 border-gray-700 py-6">
<div class="flex items-end"> <div class="flex items-end">
<h3 class="ml-4 px-2 text-2xl font-[600] text-gray-200">Hayden Hargreaves</h3> <h3 class="ml-4 px-2 text-2xl font-[600] text-gray-200">Hayden Hargreaves</h3>
@ -15,6 +11,9 @@
<a href="/about" class="transition-all duration-150 hover:text-blue-300"> <a href="/about" class="transition-all duration-150 hover:text-blue-300">
<p class="px-3">About</p> <p class="px-3">About</p>
</a> </a>
<a href="/blog" class="transition-all duration-150 hover:text-blue-300">
<p class="px-3">Blog</p>
</a>
<a href="https://github.com/Azpect3120" target="_blank" class=""> <a href="https://github.com/Azpect3120" target="_blank" class="">
<svg viewBox="0 0 98 96" xmlns="http://www.w3.org/2000/svg" class="mx-4 h-auto w-6"> <svg viewBox="0 0 98 96" xmlns="http://www.w3.org/2000/svg" class="mx-4 h-auto w-6">
><path ><path

View File

@ -0,0 +1,48 @@
import type { RequestEvent } from '@sveltejs/kit';
import { readFileSync } from 'fs';
import { Marked } from 'marked';
import { markedHighlight } from "marked-highlight";
import hljs from 'highlight.js';
// Root of the project
const cwd = process.cwd();
/**
* Load the blog post from the file system when the page is requested.
* @param {RequestEvent} event
*/
export const load = async ({ url }: RequestEvent) => {
// Create the path
// ./src/[url].md
const blogPath = cwd.concat("/src", url.pathname, ".md");
// Read the file and get the data
const data = readFileSync(blogPath, 'utf-8');
// marked.use({
// gfm: true,
// breaks: true,
//
// });
const marked = new Marked(
markedHighlight({
emptyLangClass: 'hljs',
langPrefix: 'hljs language-',
highlight(code, lang, info) {
console.log("INFO: ", code);
const language = hljs.getLanguage(lang) ? lang : 'plaintext';
return hljs.highlight(code, { language }).value;
}
})
);
// Convert the markdown to HTML
const html = marked.parse(data);
console.log(html);
return {
post: {
content: html,
}
};
};

View File

@ -0,0 +1,25 @@
<script lang="ts">
import type { PageProps } from './$types';
// import hljs from 'highlight.js';
let { data }: PageProps = $props();
// Run highlight.js after the component is rendered (onMount or after each update)
// import { onMount } from 'svelte';
//
// onMount(() => {
// // console.log("onMount called");
// highlightAllCodeBlocks();
// });
//
// function highlightAllCodeBlocks() {
// // console.log("highlightAllCodeBlocks called");
// const codeBlocks = document.querySelectorAll('pre code');
// codeBlocks.forEach((block) => {
// hljs.highlightElement(block);
// });
// }
</script>
<div class="prose">
{@html data.post.content}
</div>