Compare commits

..

1 Commits

16 changed files with 42 additions and 135 deletions

View File

@ -9,7 +9,6 @@ COPY tsconfig.json .
RUN bun install --frozen-lockfile
COPY ./src ./src
COPY ./posts ./posts
COPY ./config ./config
USER bun
CMD [ "bun", "src/index.tsx" ]

View File

@ -1,19 +1,3 @@
# davesmithhayes.com
This repository holds the code that deploys into the blog for Dave Smith-Hayes.
## TODO
This is an unorganized list of the features left for the blog.
* Pages Handler
* Renders Markdown pages into HTML pages
* Dynamic Navigation
* Blog Roll
* List of blogs I have read and liked
* External Links
* Links to my git, music, other things
* RSS Feed
* robots.txt
* Site map
* Images on posts and pages

BIN
bun.lockb

Binary file not shown.

View File

@ -1,12 +0,0 @@
title = "davesmithhayes.com"
[owner]
name = "Dave Smith-Hayes"
email = "me@davesmithhayes.com"
[site]
description = "Personal website of Dave Smith-Hayes - a father, developer, and musician."
url = "https://davesmithhayes.com"
repo = "https://git.davesmithhayes.com/dsh/blog"
language = "en"
copyright = "All rights reserved, Dave Smith-Hayes"

View File

@ -5,13 +5,11 @@
},
"dependencies": {
"@types/yaml-front-matter": "^4.1.3",
"feed": "^4.2.2",
"highlight.js": "^11.10.0",
"hono": "^4.6.13",
"marked": "^13.0.3",
"marked-highlight": "^2.2.1",
"hono": "^4.4.13",
"marked": "^13.0.2",
"marked-highlight": "^2.1.3",
"remark": "^15.0.1",
"smol-toml": "^1.3.1",
"yaml-front-matter": "^4.1.1"
},
"devDependencies": {

View File

@ -1,4 +1,3 @@
export const POST_PATH: string = __dirname + '/../posts';
export const CONFIG_PATH: string = __dirname + '/../config';
export const STATIC_PATH: string = __dirname + '/assets';
export const POST_ROUTE_PREFIX: string = '/posts'

16
src/handlers/about.tsx Normal file
View File

@ -0,0 +1,16 @@
import { Hono, Context } from 'hono';
const aboutPage = new Hono();
export async handleAboutPage(c: Context) {
const meta: SiteMeta = {
title: "About",
description: "About Dave Smith-Hayes - a dad, developer, musician.",
author: "Dave Smith-Hayes"
};
c.render(<AboutPage />, { meta });
}
aboutPage.get("/about", handleAboutPage);
export default aboutPage;

View File

@ -1,21 +0,0 @@
import { Hono, Context } from 'hono';
import { PostService } from '@blog/services/post-file';
import { getFeed } from '@blog/services/feed-generator';
import { Feed } from 'feed';
const feed = new Hono<{ Variables: { postService: PostService }}>();
let feedBuffer: string = "";
export async function getFeedFile(c: Context) {
if (!feedBuffer) {
const postService: PostService = c.get('postService');
const feed: Feed = await getFeed(postService);
feedBuffer = feed.rss2();
}
c.header('Content-Type', 'text/xml');
return c.body(feedBuffer);
}
feed.get('/rss.xml', getFeedFile);
export default feed;

View File

@ -4,7 +4,6 @@ import { serveStatic } from 'hono/bun';
import { Page } from '@blog/templates/Page';
import home from '@blog/handlers/home';
import posts from '@blog/handlers/posts';
import feed from '@blog/handlers/feed';
import type { SiteMeta } from '@blog/models/SiteMeta';
import { postFileMiddleware } from '@blog/middleware/post-service';
import { logger } from 'hono/logger';
@ -37,7 +36,6 @@ app.use('/static/*', serveStatic({
}));
app.route('/', home);
app.route('/feed', feed)
app.route('/posts', posts);
console.log("Starting the blog");

View File

@ -1,6 +1,3 @@
/**
* SiteMeta is often used for the `<meta />` tags in the document header
*/
export type SiteMeta = {
description?: string,
tags?: string[],

View File

@ -1,9 +0,0 @@
import { describe, expect, test } from 'bun:test'
import { getSiteConfig } from '@blog/services/config';
describe("Test the global config for the site", () => {
test("Parses the Owner", async () => {
const siteConfig = await getSiteConfig();
expect(siteConfig.owner.email).toBe("me@davesmithhayes.com");
})
})

View File

@ -1,24 +0,0 @@
import TOML from 'smol-toml';
import { CONFIG_PATH } from '@blog/config';
export type SiteConfig = {
title: string;
owner: {
name: string;
email: string;
};
site: {
description: string;
url: string;
repo: string;
language: string;
copyright: string;
}
}
export async function getSiteConfig(): Promise<SiteConfig> {
const siteConfig = CONFIG_PATH + '/site.toml';
const file = Bun.file(siteConfig);
const data = await file.text();
return TOML.parse(data) as SiteConfig;
}

View File

@ -1,41 +0,0 @@
import { Feed, FeedOptions } from 'feed';
import { getSiteConfig } from '@blog/services/config';
import { PostService } from '@blog/services/post-file';
import type { Post } from '@blog/models/post';
const updatedDate = new Date();
export async function getFeed(postService: PostService): Feed {
const config = await getSiteConfig();
const feed = new Feed({
title: config.title,
description: config.site.description,
link: config.site.link,
language: config.site.language,
copyright: config.site.copyright,
generator: "dsh feed gen",
updated: updatedDate,
author: {
name: "Dave Smith-Hayes",
email: "me@davesmithhayes.com",
link: "davesmithhayes.com"
}
});
postService.getPublishedPosts().map((post: Post) => {
feed.addItem({
title: post.meta.title,
id: post.meta.slug,
link: post.meta.slug,
description: post.meta.description,
content: post.html,
author: {
name: config.author,
email: config.email
}
});
});
return feed;
};

View File

@ -1,6 +1,7 @@
import { Style } from 'hono/css';
import { SiteMeta } from '@blog/models/SiteMeta';
import { MetaTags } from '@blog/templates/components/MetaTags';
import { Navigation } from '@blog/templates/componennts/Navigation';
function getPageTitle(title: string|undefined): string {
if (!title) {
@ -25,6 +26,9 @@ export function Page({ children, meta }: { children: any, meta: SiteMeta }) {
<a href="/">davesmithhayes.com</a>
</div>
</header>
<nav>
<Navigation />
</nav>
<main>
{children}
</main>

View File

@ -0,0 +1,7 @@
export function AboutPage() {
return (
<div class="main">
<p>Hello! I am Dave Smith-Hayes.</p>
</div>
);
}

View File

@ -0,0 +1,12 @@
const pages: Array<{ path: string, title: string }> = [
{ path: "/", title: "Home" },
{ path: "/about", title: "About" },
];
export function Navigation() {
return (
<ul>
{pages.map(p => <li><a href={p.path}>{p.title}</a></li> )}
</ul>
);
}