Files
djledda-web/app/generative-energy/GEDeutschArticle.tsx
Daniel Ledda 20479958bd update
2024-11-01 21:29:13 +01:00

125 lines
4.7 KiB
TypeScript

import { createTextVNode, computed, defineComponent, h, inject, onServerPrefetch, ref, type VNode, watchEffect } from "vue";
import { RouterLink } from "vue-router";
import useAsyncState from "@/useAsyncState.ts";
import useHead from "@/useHead.ts";
import DJEmail from "@/DJEmail.tsx";
import getDJAPI from "@/api.ts";
export default defineComponent({
name: "ge-deutsch-article",
props: {
articleName: {
type: String,
required: true,
},
},
async setup(props) {
const currentLang = ref<"en" | "de">("de");
function clickBtn() {
currentLang.value = currentLang.value === "en" ? "de" : "en";
}
const parseDom = inject(
"dom-parse",
(innerHTML: string) => Object.assign(document.createElement("div"), { innerHTML }),
);
const { result: articleContent, stateIsReady } = useAsyncState(
"ge-deutsch-article-data",
async ({ hostUrl }) => {
const articleResponse = await fetch(`${hostUrl}/generative-energy/content/${props.articleName}.html`);
const result = await articleResponse.text();
return result;
},
);
const {
result: articleData,
stateIsReady: articleDataReady,
} = useAsyncState('article-data', ({hostUrl}) => getDJAPI(hostUrl, '/rp-articles'));
const articleMetadata = computed(() => articleData.value?.find(_ => _.slug === props.articleName));
const title = computed(() => {
return articleContent.value?.split('<h1 lang="de">')[1].split("</h1>")[0] ?? 'Artikel';
});
useHead({ title });
onServerPrefetch(() =>
new Promise<void>((res) => {
watchEffect(() => {
if (title.value !== "") {
res();
}
});
})
);
function transformArticleNode(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((_) => transformArticleNode(_));
if (el.tagName === "P") {
el.classList.add("text-slab");
children.unshift(h("button", {
class: "swap",
onClick: (e) => {
(e.target as HTMLButtonElement).parentElement?.classList.toggle("swap");
},
}, "↻"));
}
for (let i = 0; i < el.attributes.length; i++) {
const item = el.attributes.item(i);
if (item) {
attrs[item.name] = item.value;
}
}
if (el.tagName === "H1") {
return h("header", attrs, h("h1", {}, children));
} else {
return h((node as Element).tagName, attrs, children);
}
} else {
return createTextVNode(node.textContent ?? "");
}
}
function ArticleContentTransformed() {
if (articleContent.value) {
const dom = parseDom(articleContent.value);
return h("div", {}, [...dom.children].map((_) => transformArticleNode(_)));
}
return <div>Artikel lädt...</div>;
}
await Promise.all([stateIsReady, articleDataReady]);
console.log(articleMetadata.value);
return () => (
<div class="ge-article">
<div class="header">
<RouterLink to={{ name: "GEDeutsch" }}>Zur Artikelübersicht</RouterLink>
<button onClick={clickBtn}>
Sprache auf <span>{currentLang.value === "en" ? "Deutsch" : "Englisch"}</span> umschalten
</button>
</div>
<p class="text-slab">
Bei dem untenstehenden Artikel handelt es sich um eine hobbymäßige, amateurhafte Übersetzung des
Artikels { title.value } von Ray Peat. Bei Ungenauigkeiten oder Fehlübersetzungen freue ich mich über <DJEmail>eine Mail</DJEmail>!
</p>
{ articleMetadata.value?.tags?.includes('in-arbeit') && <h5 class="baustelle">🚧 Bitte beachte, dass diese Übersetzung noch in Arbeit und darum nicht fertig ist! 🚧</h5> }
<hr />
<article class={`lang-${currentLang.value}`}>
<ArticleContentTransformed />
</article>
</div>
);
},
});