From 2e7b5da0f9cca792f1df6ac25cc0101336585c27 Mon Sep 17 00:00:00 2001 From: Dave Smith-Hayes Date: Tue, 2 Jul 2024 22:35:01 -0400 Subject: [PATCH] Start the blog --- .editorconfig | 3 ++ .gitignore | 2 ++ README.md | 11 ++++++++ bun.lockb | Bin 0 -> 28248 bytes package.json | 16 +++++++++++ src/Model/Post.ts | 10 +++++++ src/index.tsx | 38 ++++++++++++++++++++++++++ src/readPostMarkdown.ts | 21 ++++++++++++++ src/templates/Page.tsx | 20 ++++++++++++++ src/templates/Pages/Home.tsx | 11 ++++++++ src/templates/components/PostList.tsx | 15 ++++++++++ tsconfig.json | 10 +++++++ 12 files changed, 157 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 README.md create mode 100755 bun.lockb create mode 100644 package.json create mode 100644 src/Model/Post.ts create mode 100644 src/index.tsx create mode 100644 src/readPostMarkdown.ts create mode 100644 src/templates/Page.tsx create mode 100644 src/templates/Pages/Home.tsx create mode 100644 src/templates/components/PostList.tsx create mode 100644 tsconfig.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..8f08686 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,3 @@ +[*.{js,ts,jsx,tsx,json}] +indent_style = space +indent_size = 2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..506e4c3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# deps +node_modules/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..6dd13e7 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +To install dependencies: +```sh +bun install +``` + +To run: +```sh +bun run dev +``` + +open http://localhost:3000 diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..01bf5133667645badb1d5518be4f929155adc7e6 GIT binary patch literal 28248 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 literal 0 HcmV?d00001 diff --git a/package.json b/package.json new file mode 100644 index 0000000..f5a1b81 --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "blog", + "scripts": { + "dev": "bun run --hot src/index.tsx" + }, + "dependencies": { + "@types/yaml-front-matter": "^4.1.3", + "hono": "^4.4.10", + "marked": "^13.0.1", + "remark": "^15.0.1", + "yaml-front-matter": "^4.1.1" + }, + "devDependencies": { + "@types/bun": "latest" + } +} diff --git a/src/Model/Post.ts b/src/Model/Post.ts new file mode 100644 index 0000000..d7d87dc --- /dev/null +++ b/src/Model/Post.ts @@ -0,0 +1,10 @@ +import { Tag } from '@blog/Model/Tag'; + +export type Post = { + title: string, + slug: string, + description: string, + content: string, + date: Date, + tags: string[] +}; diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 0000000..f1de0e3 --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,38 @@ +import { Hono } from 'hono'; +import { jsxRenderer, useRequestContext } from 'hono/jsx-renderer'; +import { Page } from '@blog/templates/Page'; +import { Home } from '@blog/templates/Pages/Home'; +import { readdir } from 'node:fs/promises'; + +const app = new Hono(); + +app.get( + '*', + jsxRenderer( + ({ children }) => { + return ({children}); + }, + { + docType: true + } + ) +); + +// read all posts +// create listing of posts + + +app.get('/', async (c) => { + const files = await readdir('../posts', { recursive: true }); + const posts = files.filter(f => f === '.' || f === '..'); + return c.render(); +}); + +app.get('/posts/:slug', (c) => { + const postSlug: string = c.req.param("slug"); + + // render post + // send to Post layout +}); + +export default app; diff --git a/src/readPostMarkdown.ts b/src/readPostMarkdown.ts new file mode 100644 index 0000000..5d02d1c --- /dev/null +++ b/src/readPostMarkdown.ts @@ -0,0 +1,21 @@ +import { marked } from 'marked'; +import type { Post } from '@blog/Model/Post'; +import * as yamlFront from 'yaml-front-matter'; + +export async function readPostMarkdown(filename: string): Promise { + const file = Bun.file(filename); + const contents = await file.text(); + + const parsedData = yamlFront.loadFront(contents); + const parsedPost = await marked.parse(parsedData.__content); + + return { + title: parsedData.title, + slug: filename.slice(0, -3), + description: parsedData.description, + date: new Date(parsedData.date), + tags: parsedData.tags, + content: parsedPost + }; +} + diff --git a/src/templates/Page.tsx b/src/templates/Page.tsx new file mode 100644 index 0000000..81f007a --- /dev/null +++ b/src/templates/Page.tsx @@ -0,0 +1,20 @@ +export function Page({ children }: { children: any }) { + return ( + + + davesmithhayes.com + + +
+ +
+
+ {children} +
+
+ +
+ + + ); +} diff --git a/src/templates/Pages/Home.tsx b/src/templates/Pages/Home.tsx new file mode 100644 index 0000000..f764666 --- /dev/null +++ b/src/templates/Pages/Home.tsx @@ -0,0 +1,11 @@ +import { PostList } from '@blog/templates/components/PostList'; + +export function Home({ posts }: { posts: string[] }) { + return ( +
+

davesmithhayes.com

+ {posts.length ? :
No posts.
} +
+ ); +} + diff --git a/src/templates/components/PostList.tsx b/src/templates/components/PostList.tsx new file mode 100644 index 0000000..e947abf --- /dev/null +++ b/src/templates/components/PostList.tsx @@ -0,0 +1,15 @@ +import type { Post } from '@blog/Model/Post'; + +export function PostList(postList: Post[]) { + return( +
    + {postList.map(p => { + return ( +
  • + {p.name} +
  • + ); + })} +
+ ); +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a7eb9c2 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "strict": true, + "jsx": "react-jsx", + "jsxImportSource": "hono/jsx", + "paths": { + "@blog/*": [ "./src/*" ] + } + } +}