move blog to tsx
All checks were successful
/ test (push) Successful in 12s

This commit is contained in:
Soph :3 2024-07-23 11:51:16 +03:00
parent a7aaff537f
commit 262032b4e3
Signed by: sophie
GPG key ID: EDA5D222A0C270F2
7 changed files with 186 additions and 78 deletions

View file

@ -11,37 +11,46 @@ export default class TSCompiler extends Plugin {
minify = false;
constructor() {
super();
if(process.argv.includes("--prod")) {
if (process.argv.includes("--prod")) {
this.minify = true;
}
}
async rewriteFile(file: string, filePath: string) {
const result = await esbuild.build({
stdin: {
contents: file,
resolveDir: filePath.split("/")?.slice(0,-1).join("/"),
sourcefile: filePath.split("/").at(-1),
loader: filePath.split("/").at(-1)?.split(".").at(-1) as "ts"|"tsx"|"jsx"
},
jsxFragment: "Fragment",
jsxFactory: "Nano.h",
jsxImportSource: "nano-jsx",
jsx: "transform",
write: false,
bundle: true,
outdir: 'out',
minify: this.minify,
});
let result;
try {
result = await esbuild.build({
stdin: {
contents: file,
resolveDir: filePath.split("/")?.slice(0, -1).join("/"),
sourcefile: filePath.split("/").at(-1),
loader: filePath.split("/").at(-1)?.split(".").at(-1) as
| "ts"
| "tsx"
| "jsx",
},
jsxFragment: "Fragment",
jsxFactory: "Nano.h",
jsxImportSource: "nano-jsx",
jsx: "transform",
write: false,
bundle: true,
outdir: "out",
minify: this.minify,
});
} catch (e) {
console.error(e);
console.log("Errored!");
return;
}
if(result.errors.length != 0) {
console.log("TS compiler errored.")
result.errors.forEach(element => {
console.error(element);
});
if (result.errors.length != 0) {
console.log("TS compiler errored.");
result.errors.forEach((element) => {
console.error(element);
});
} else {
const output = result.outputFiles[0].contents;
return (new TextDecoder()).decode(output);
return new TextDecoder().decode(output);
}
}
}

View file

@ -13,7 +13,7 @@ export default class Variables extends Plugin {
constructor() {
super();
this.variables["__BLOG_POSTS__"] = JSON.stringify(
fs.readdirSync("./website/blogs")
fs.readdirSync("./website/blogs").map((z) => z.replace(".md", ""))
);
const templatePath = path.resolve(__dirname, "../../website/templates");
if (fs.existsSync(templatePath)) {

View file

@ -3,21 +3,7 @@ __TEMPLATE_HEAD__
</head>
<body>
<h1> sophie's blog </h1>
<a id="return_back" href="/blog.html" style="display:none;font-size:xx-large;">return back?</a>
<div>Scroll to bottom for comments ↓</div>
<ul id="html_list" style="display: none">
</ul>
<div id="renderer"></div>
<div style="color:red;font-size:larger;font-weight:bolder;display:none;" id="error">
Blog post <span></span> does not exist.
</div>
<div class="giscus"></div>
<script src="https://giscus.app/client.js" data-repo="fucksophie/blog_comments" data-repo-id="R_kgDOMY4cfw"
data-category="General" data-category-id="DIC_kwDOMY4cf84ChCRR" data-mapping="url" data-strict="1"
data-reactions-enabled="1" data-emit-metadata="0" data-input-position="bottom" data-theme="noborder_dark"
data-lang="en" data-loading="lazy" crossorigin="anonymous" async>
</script>
<div id="root"></div>
<script type="module" src="scripts/blog.js"></script>
</body>

View file

@ -1,38 +0,0 @@
async function blog() {
const uriParams = new URLSearchParams(location.search);
if (uriParams.has("md")) {
const error = document.getElementById("error")!;
const renderer = document.getElementById("renderer")!;
const return_back = document.getElementById("return_back")!;
const req = await fetch("/blogs/" + uriParams.get("md") + ".html");
const giscus = document.querySelector(".giscus")! as HTMLDivElement;
if (req.status != 200) {
error.style.display = "block";
giscus.style.display = "none";
} else {
let text = await req.text();
renderer.innerHTML = text;
}
return_back.style.display = "block";
} else {
//@ts-expect-error
const blog_posts = __BLOG_POSTS__.map((z) => z.replace(".md", ""));
const html_list = document.getElementById("html_list")!;
html_list.style.display = "block";
for (const blog_post of blog_posts) {
const req = await fetch("/blogs/" + blog_post + ".json");
const metadata = await req.json();
const li = document.createElement("li");
const a = document.createElement("a");
a.href = "/blog.html?md=" + encodeURIComponent(blog_post);
a.innerText = `${metadata.title} (created ${new Date(
metadata.time * 1000
//@ts-expect-error
).toGMTString()})`;
li.appendChild(a);
html_list.appendChild(li);
}
}
}
blog();

84
website/scripts/blog.tsx Normal file
View file

@ -0,0 +1,84 @@
import Nano, { Component, Fragment, Suspense } from "nano-jsx"
import { BlogPage } from "./blog_page";
import { Giscus } from "./giscus";
import { useState } from "nano-jsx/esm/hooks/useState.js";
export interface Metadata {
title: string;
// time in seconds since epoch (*1000 for MS)
time: number;
filename: string;
}
//@ts-expect-error
const blog_posts = __BLOG_POSTS__ as string[];
const fetchBlogPosts = async () => {
const metadatas: Metadata[] = [];
for await (const blog of blog_posts) {
const req = await fetch("/blogs/" + blog + ".json");
const json = await req.json()
json.filename = blog;
metadatas.push(json);
}
return metadatas
}
class Main extends Component {
async didMount() {
const blogPosts = await fetchBlogPosts()
this.update(blogPosts)
}
list(metadatas: Metadata[]) {
const pageOpen = useState<Metadata | undefined>(undefined, "pageOpen");
console.log("abcd")
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>
}
render(blogPosts: Metadata[]) {
const pageOpen = useState<Metadata | undefined>(undefined, "pageOpen");
const md = new URLSearchParams(location.search).get("md");
if (blogPosts) {
const found = blogPosts.find(z => z.filename == md);
if (found) {
console.log(found);
pageOpen[1](found);
//@ts-expect-error
pageOpen[0] = found;
}
}
if (pageOpen[0]) {
return <BlogPage metadata={pageOpen[0]}></BlogPage>
}
return <>
<h1> sophie's blog </h1>
<div>Scroll to bottom for comments </div>
{() => {
if (blogPosts) return this.list(blogPosts)
else return <h3>Loading...</h3>
}}
<Giscus searchTerm="main"></Giscus>
</>
}
}
Nano.render(<Main></Main>, document.getElementById("root"))

View file

@ -0,0 +1,43 @@
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;
constructor(props: { metadata: Metadata }) {
super(props);
this.metadata = props.metadata;
}
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> sophie's blog </h1>
<a href="/blog.html" style="font-size:xx-large;" onClick={() => {
pageOpen[1](undefined);
this.update();
}}>return back?</a>
{
() => {
if (!blogPost) return <h1>Loading...</h1>
else return <div dangerouslySetInnerHTML={{ __html: blogPost }}></div>
}
}
<Giscus searchTerm={this.metadata.filename}></Giscus>
</>
}
}

View file

@ -0,0 +1,24 @@
export function Giscus({searchTerm}: {searchTerm: string}) {
let config: Record<string, string> = {
"repo": "fucksophie/blog_comments",
"repo-id": "R_kgDOMY4cfw",
"category": "General",
"category-id": "DIC_kwDOMY4cf84ChCRR",
"mapping": "specific",
"term": searchTerm,
"strict": "1",
"reactions-enabled": "1",
"emit-metadata": "0",
"input-position": "bottom",
"theme": "noborder_dark",
"lang": "en",
"loading": "lazy",
}
for(const x of Object.entries(config)) {
delete config[x[0]];
config["data-"+x[0]] = x[1];
}
return <div>
<script src="https://giscus.app/client.js" {...config} crossorigin="anonymous" async></script>
</div>
}