This commit is contained in:
Orion Reed 2024-07-07 22:14:24 +01:00
parent 7948a458f9
commit 36bb02cf64
8 changed files with 93 additions and 14 deletions

View File

@ -14,10 +14,13 @@
"dependencies": { "dependencies": {
"@dimforge/rapier2d": "^0.11.2", "@dimforge/rapier2d": "^0.11.2",
"@tldraw/tldraw": "2.0.2", "@tldraw/tldraw": "2.0.2",
"@types/markdown-it": "^14.1.1",
"@vercel/analytics": "^1.2.2", "@vercel/analytics": "^1.2.2",
"gray-matter": "^4.0.3",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-router-dom": "^6.22.3" "react-router-dom": "^6.22.3",
"vite-plugin-md": "^0.21.5"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "1.4.1", "@biomejs/biome": "1.4.1",

View File

@ -10,6 +10,7 @@ import { useCanvas } from "@/hooks/useCanvas"
import { createShapes } from "@/utils"; import { createShapes } from "@/utils";
import { BrowserRouter, Route, Routes } from 'react-router-dom'; import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { Contact } from "@/components/Contact"; import { Contact } from "@/components/Contact";
import { Post } from '@/components/Post';
inject(); inject();
ReactDOM.createRoot(document.getElementById("root")!).render(<App />); ReactDOM.createRoot(document.getElementById("root")!).render(<App />);
@ -23,6 +24,7 @@ function App() {
<Routes> <Routes>
<Route path="/" element={<Home />} /> <Route path="/" element={<Home />} />
<Route path="/card/contact" element={<Contact />} /> <Route path="/card/contact" element={<Contact />} />
<Route path="/posts/:slug" element={<Post />} />
</Routes> </Routes>
</BrowserRouter> </BrowserRouter>
</React.StrictMode> </React.StrictMode>

View File

@ -23,9 +23,8 @@ export function Default() {
<h1>My work</h1> <h1>My work</h1>
<p> <p>
Alongside my independent work I am a researcher at <a href="https://block.science/">Block Science</a> building{' '} Alongside my independent work I am a researcher at <a href="https://block.science/">Block Science</a> building{' '}
<i>knowledge organisation infrastructure</i> and at <a href="https://economicspace.agency/">ECSA</a> working on{' '} <i>knowledge organisation infrastructure</i> and an engineer-in-residence at <a href="https://tldraw.com">tldraw</a>. I am also part of the nascent <a href="https://libcomp.org/">Liberatory Computing</a>{' '}
<i>computational media</i>. I am also part of the nascent <a href="https://libcomp.org/">Liberatory Computing</a>{' '} collective, occasional collaborator with <a href="https://economicspace.agency/">ECSA</a> and a co-organiser of the <a href="https://canvasprotocol.org/">OCWG</a>.
collective and a co-organiser of the <a href="https://canvasprotocol.org/">OCWG</a>.
</p> </p>
<h1>Get in touch</h1> <h1>Get in touch</h1>

29
src/components/Post.tsx Normal file
View File

@ -0,0 +1,29 @@
import React from 'react';
import { useParams } from 'react-router-dom';
export function Post() {
const { slug } = useParams<{ slug: string }>();
const [post, setPost] = React.useState<{ title: string, html: string } | null>(null);
React.useEffect(() => {
import(`../posts/${slug}.md`)
.then((module) => {
setPost(module.default);
})
.catch((error) => {
console.error('Failed to load post:', error);
setPost(null);
});
}, [slug]);
if (!post) {
return <div>Loading...</div>;
}
return (
<main>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</main>
);
}

10
src/posts/test.md Normal file
View File

@ -0,0 +1,10 @@
# This is a title
this is some text under the title
here is an image:
![image](image.png)
requirements:
- basic html (headings, quotes, italics, bold...)
- images and videos (easy authoring, what are the vercel limits too?)
- static gen, we don't want SPA pop-in, we want 100% prerendered html

View File

@ -0,0 +1,20 @@
import MarkdownIt from 'markdown-it';
const md = new MarkdownIt({
html: true,
breaks: true,
linkify: true,
});
// Customize Markdown-to-HTML mapping here
md.renderer.rules.paragraph_open = () => '<p class="custom-paragraph">';
md.renderer.rules.image = (tokens, idx, options, env, self) => {
const token = tokens[idx];
const src = token.attrGet('src');
const alt = token.content;
return `<img src="${src}" alt="${alt}" class="custom-image" />`;
};
export function markdownToHtml(content: string): string {
return md.render(content);
}

View File

@ -1,10 +1,10 @@
{ {
"compilerOptions": { "compilerOptions": {
"composite": true, "composite": true,
"skipLibCheck": true, "skipLibCheck": true,
"module": "ESNext", "module": "ESNext",
"moduleResolution": "bundler", "moduleResolution": "bundler",
"allowSyntheticDefaultImports": true "allowSyntheticDefaultImports": true
}, },
"include": ["vite.config.ts"] "include": ["vite.config.ts", "src/utils/*"]
} }

View File

@ -1,13 +1,29 @@
import { defineConfig } from 'vite' import { defineConfig, Plugin } from 'vite'
import react from '@vitejs/plugin-react' import react from '@vitejs/plugin-react'
import wasm from "vite-plugin-wasm"; import wasm from "vite-plugin-wasm";
import topLevelAwait from "vite-plugin-top-level-await"; import topLevelAwait from "vite-plugin-top-level-await";
import matter from 'gray-matter';
import { markdownToHtml } from './src/utils/markdownToHtml';
const markdownPlugin: Plugin = {
name: 'markdown-plugin',
enforce: 'pre',
transform(code, id) {
if (id.endsWith('.md')) {
const { data, content } = matter(code);
const html = markdownToHtml(content);
const jsonContent = JSON.stringify({ ...data, html });
return `export default ${jsonContent};`;
}
},
};
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
react(), react(),
wasm(), wasm(),
topLevelAwait() topLevelAwait(),
markdownPlugin
], ],
build: { build: {
sourcemap: true, // Enable source maps for production sourcemap: true, // Enable source maps for production