md posts
This commit is contained in:
parent
7948a458f9
commit
36bb02cf64
|
|
@ -14,10 +14,13 @@
|
|||
"dependencies": {
|
||||
"@dimforge/rapier2d": "^0.11.2",
|
||||
"@tldraw/tldraw": "2.0.2",
|
||||
"@types/markdown-it": "^14.1.1",
|
||||
"@vercel/analytics": "^1.2.2",
|
||||
"gray-matter": "^4.0.3",
|
||||
"react": "^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": {
|
||||
"@biomejs/biome": "1.4.1",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { useCanvas } from "@/hooks/useCanvas"
|
|||
import { createShapes } from "@/utils";
|
||||
import { BrowserRouter, Route, Routes } from 'react-router-dom';
|
||||
import { Contact } from "@/components/Contact";
|
||||
import { Post } from '@/components/Post';
|
||||
inject();
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(<App />);
|
||||
|
|
@ -23,6 +24,7 @@ function App() {
|
|||
<Routes>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/card/contact" element={<Contact />} />
|
||||
<Route path="/posts/:slug" element={<Post />} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
|
|
|
|||
|
|
@ -23,9 +23,8 @@ export function Default() {
|
|||
<h1>My work</h1>
|
||||
<p>
|
||||
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>computational media</i>. I am also part of the nascent <a href="https://libcomp.org/">Liberatory Computing</a>{' '}
|
||||
collective and a co-organiser of the <a href="https://canvasprotocol.org/">OCWG</a>.
|
||||
<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>{' '}
|
||||
collective, occasional collaborator with <a href="https://economicspace.agency/">ECSA</a> and a co-organiser of the <a href="https://canvasprotocol.org/">OCWG</a>.
|
||||
</p>
|
||||
|
||||
<h1>Get in touch</h1>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
# This is a title
|
||||
this is some text under the title
|
||||
|
||||
here is an image:
|
||||

|
||||
|
||||
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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"skipLibCheck": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts", "src/utils/*"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,29 @@
|
|||
import { defineConfig } from 'vite'
|
||||
import { defineConfig, Plugin } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
import wasm from "vite-plugin-wasm";
|
||||
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({
|
||||
plugins: [
|
||||
react(),
|
||||
wasm(),
|
||||
topLevelAwait()
|
||||
topLevelAwait(),
|
||||
markdownPlugin
|
||||
],
|
||||
build: {
|
||||
sourcemap: true, // Enable source maps for production
|
||||
|
|
|
|||
Loading…
Reference in New Issue