move from nano-jsx to Preact, benefits: 1. Smaller bundle size, 2. Quicker rendering, 3. Full vDom with proper states, 4. Proper pure functions
All checks were successful
/ test (push) Successful in 14s

This commit is contained in:
Soph :3 2024-08-01 22:55:12 +03:00
parent b598ebd306
commit 7255080d31
Signed by: sophie
GPG key ID: EDA5D222A0C270F2
7 changed files with 91 additions and 119 deletions

BIN
bun.lockb

Binary file not shown.

View file

@ -18,6 +18,6 @@
"esbuild": "^0.23.0", "esbuild": "^0.23.0",
"marked": "^13.0.2", "marked": "^13.0.2",
"mime-types": "^2.1.35", "mime-types": "^2.1.35",
"nano-jsx": "^0.1.0" "preact": "^10.23.1"
} }
} }

View file

@ -29,8 +29,8 @@ export default class TSCompiler extends Plugin {
| "jsx", | "jsx",
}, },
jsxFragment: "Fragment", jsxFragment: "Fragment",
jsxFactory: "Nano.h", jsxFactory: "h",
jsxImportSource: "nano-jsx", jsxImportSource: "preact",
jsx: "transform", jsx: "transform",
write: false, write: false,
bundle: true, bundle: true,

View file

@ -6,7 +6,7 @@
"module": "ESNext", "module": "ESNext",
"moduleDetection": "force", "moduleDetection": "force",
"jsx": "react-jsx", "jsx": "react-jsx",
"jsxImportSource": "nano-jsx/esm", "jsxImportSource": "preact",
"allowJs": true, "allowJs": true,
// Bundler mode // Bundler mode

View file

@ -1,7 +1,7 @@
import Nano, { Component, Fragment } from "nano-jsx" import { h, Component, Fragment, render } from 'preact';
import { BlogPage } from "./blog_page"; import { useEffect, useState } from 'preact/hooks';
import { Giscus } from "./giscus"; import { Giscus } from './giscus';
import { useState } from "nano-jsx/esm/hooks/useState.js"; import { BlogPost } from './blog_post';
export interface Metadata { export interface Metadata {
title: string; title: string;
@ -12,74 +12,58 @@ export interface Metadata {
const blog_posts = __BLOG_POSTS__ as string[]; const blog_posts = __BLOG_POSTS__ as string[];
const fetchBlogPosts = async () => { const Blog = () => {
const metadatas: Metadata[] = []; const pageOpen = useState<Metadata | undefined>()
const blogPosts = useState<Metadata[] | undefined>(undefined)
const md = new URLSearchParams(location.search).get("md");
for await (const blog of blog_posts) { useEffect(() => {
const req = await fetch("/blogs/" + blog + ".json"); (async () => {
const json = await req.json() const metadatas: Metadata[] = [];
json.filename = blog;
metadatas.push(json);
}
return metadatas for await (const blog of blog_posts) {
} const req = await fetch("/blogs/" + blog + ".json");
const json = await req.json()
class Main extends Component { json.filename = blog;
async didMount() { metadatas.push(json);
const blogPosts = await fetchBlogPosts()
this.update(blogPosts)
}
list(metadatas: Metadata[]) {
const pageOpen = useState<Metadata | undefined>(undefined, "pageOpen");
return <ul>
{metadatas.map((n) => {
return <li>
<a onClick={
() => {
pageOpen[1](n);
this.update();
}
}>{n.title} (created {new Date(n.time * 1000).toLocaleString()})</a>
</li>
})}
</ul>
}
async handleSelfUpdate() {
const blogPosts = await fetchBlogPosts()
this.update(blogPosts)
}
render(blogPosts: Metadata[]) {
const pageOpen = useState<Metadata | undefined>(undefined, "pageOpen");
const md = new URLSearchParams(location.search).get("md");
let pageOpenValueRender = pageOpen[0];
if (blogPosts) {
const found = blogPosts.find(z => z.filename == md);
if (found) {
pageOpen[1](found);
pageOpenValueRender = found;
} }
}
blogPosts[1](metadatas);
})();
}, [])
if (pageOpenValueRender) { if (blogPosts[0]) {
return <div><BlogPage metadata={pageOpenValueRender} updateParent={this.handleSelfUpdate.bind(this)}></BlogPage></div> const found = blogPosts[0].find(z => z.filename == md);
if (found) {
pageOpen[1](found);
} }
return <>
<h1>blog & comments</h1>
{() => {
if (blogPosts) return this.list(blogPosts)
else return <h3>Loading...</h3>
}}
<Giscus searchTerm="main"></Giscus>
</>
} }
if (pageOpen[0]) {
return <BlogPost pageOpen={pageOpen}></BlogPost>
}
return <>
<h1>blog & comments</h1>
{(() => {
if (blogPosts[0]) {
return <ul>
{blogPosts[0].map((n) => {
return <li>
<a onClick={
() => {
pageOpen[1](n);
}
}>{n.title} (created {new Date(n.time * 1000).toLocaleString()})</a>
</li>
})}
</ul>;
}
else { return <h3>Loading...</h3> }
})()}
<Giscus searchTerm='main'></Giscus>
</>;
} }
Nano.render(<Main></Main>, document.getElementById("root"))
render(<Blog></Blog>, document.getElementById("root")!);

View file

@ -1,48 +0,0 @@
import { Component } from "nano-jsx"
import { Giscus } from "./giscus";
import { useState } from "nano-jsx/esm/hooks/useState.js";
import type { Metadata } from "./blog";
const fetchBlogPost = async (metadata: Metadata) => {
return (await fetch("/blogs/" + metadata.filename + ".html")).text();
}
export class BlogPage extends Component {
metadata: Metadata;
updateParent: () => void;
constructor(props: { metadata: Metadata, updateParent: () => void }) {
super(props);
this.metadata = props.metadata;
this.updateParent = props.updateParent;
}
async didMount() {
const blogPost = await fetchBlogPost(this.metadata)
this.update(blogPost)
}
render(blogPost: string) {
const pageOpen = useState<string | undefined>(undefined, "pageOpen");
history.replaceState({}, "", location.pathname + "?md=" + this.metadata.filename);
return <>
<h1>blog & comments</h1>
<a style="font-size:xx-large;" onClick={() => {
pageOpen[1](undefined);
history.replaceState({}, "", location.pathname + "?md=");
this.updateParent();
}}>return back?</a>
<div>Scroll to bottom for comments </div>
{
() => {
if (!blogPost) return <h1>Loading...</h1>
else return <div dangerouslySetInnerHTML={{ __html: blogPost }}></div>
}
}
<Giscus searchTerm={this.metadata.filename}></Giscus>
</>
}
}

View file

@ -0,0 +1,36 @@
import { useEffect, useState } from "preact/hooks";
import type { Metadata } from "./blog";
import { Giscus } from "./giscus";
export function BlogPost({ pageOpen }: { pageOpen: [Metadata | undefined, (z: Metadata | undefined) => void] }) {
if(!pageOpen[0]) return <h1>How did you get to here..?</h1>;
const blogPost = useState<string | undefined>();
history.replaceState({}, "", location.pathname + "?md=" + pageOpen[0].filename);
useEffect(() => {
(async () => {
const blogpost = await (await fetch("/blogs/" + pageOpen[0]!.filename + ".html")).text();;
blogPost[1](blogpost);
})();
}, [])
return <>
<h1>blog & comments</h1>
<a style="font-size:xx-large;" onClick={() => {
history.replaceState({}, "", location.pathname + "?md=");
pageOpen[1](undefined);
}}>return back?</a>
<div>Scroll to bottom for comments </div>
{
(() => {
if (!blogPost[0]) return <h1>Loading...</h1>
else return <div dangerouslySetInnerHTML={{ __html: blogPost[0] }}></div>
})()
}
<Giscus searchTerm={pageOpen[0].filename}></Giscus>
</>
}