big style update

This commit is contained in:
Daniel Ledda
2025-12-20 21:16:00 +01:00
parent 51e44db779
commit 498cb37561
17 changed files with 562 additions and 322 deletions

98
app/blog/DjBlogEntry.tsx Normal file
View File

@@ -0,0 +1,98 @@
import { computed, createTextVNode, defineComponent, h, type VNode } from "vue";
import useHead from "@/useHead.ts";
import useAsyncState from "@/useAsyncState.ts";
import getDjAPI from "@/api.ts";
import getDomParser from "@/domParse.ts";
import { addCSS, css } from "../util.ts";
const style = css`
.byline {
font-style: italic;
color: gray;
}
h1 {
color: var(--dj-palette1);
}
p {
margin-bottom: 30px;
}
`;
export default defineComponent({
name: "DjBlogEntry",
props: {
slug: {
type: String,
required: true,
},
},
async setup(props) {
addCSS('DjBlogEntry', style);
const parseDom = getDomParser();
const blogpostContent = useAsyncState(
`dj-blog-article-content-${ props.slug }`,
async ({ hostUrl }) => {
const blogpostResponse = await fetch(`${hostUrl}/blog/content/${ props.slug }.html`);
const result = await blogpostResponse.text();
return result;
},
);
const blogpostsMetadata = useAsyncState('article-metadata', ({ hostUrl }) => getDjAPI(hostUrl, '/blog-entries'));
const blogpostMetadata = computed(() => blogpostsMetadata.result.value?.find(_ => _.slug === props.slug));
useHead({
title: () => blogpostMetadata.value?.title ?? '',
metatags: () => blogpostMetadata.value ? [
{ name: 'title', content: blogpostMetadata.value.title },
{ name: 'author', content: 'Daniel Ledda' },
] : [],
});
function transformPostNode(node: Node): VNode | string {
if (node.nodeType === node.ELEMENT_NODE) {
const el = node as Element;
const attrs: Record<string, string> = {};
const children = [...node.childNodes].map((_) => transformPostNode(_));
for (let i = 0; i < el.attributes.length; i++) {
const item = el.attributes.item(i);
if (item) {
attrs[item.name] = item.value;
}
}
return h((node as Element).tagName, attrs, children);
} else {
return createTextVNode(node.textContent ?? "");
}
}
function PostContentTransformed() {
if (blogpostContent.result.value) {
const dom = parseDom(blogpostContent.result.value);
return h("div", {}, [...dom.children].map((_) => transformPostNode(_)));
}
return <div>Blog post loading...</div>;
}
await Promise.allSettled([ blogpostContent.done, blogpostsMetadata.done ]);
return () => <>
{ blogpostMetadata.value
? <>
<h1>{ blogpostMetadata.value.title }</h1>
<div class="byline">by Daniel Ledda, first published { new Date(blogpostMetadata.value.createdAt).toLocaleDateString() }</div>
<PostContentTransformed />
</>
: "Sorry, this blog post doesn't seem to exist."
}
</>;
}
});