djledda.de main
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

125 righe
5.0 KiB

  1. import { createTextVNode, computed, defineComponent, h, inject, onServerPrefetch, ref, type VNode, watchEffect } from "vue";
  2. import { RouterLink } from "vue-router";
  3. import useAsyncState from "@/useAsyncState.ts";
  4. import useHead from "@/useHead.ts";
  5. import DJEmail from "@/DJEmail.tsx";
  6. import getDJAPI from "@/api.ts";
  7. export default defineComponent({
  8. name: "ge-deutsch-article",
  9. props: {
  10. articleName: {
  11. type: String,
  12. required: true,
  13. },
  14. },
  15. async setup(props) {
  16. const currentLang = ref<"en" | "de">("de");
  17. function clickBtn() {
  18. currentLang.value = currentLang.value === "en" ? "de" : "en";
  19. }
  20. const parseDom = inject(
  21. "dom-parse",
  22. (innerHTML: string) => Object.assign(document.createElement("div"), { innerHTML }),
  23. );
  24. const { result: articleContent, stateIsReady } = useAsyncState(
  25. "ge-deutsch-article-data",
  26. async ({ hostUrl }) => {
  27. const articleResponse = await fetch(`${hostUrl}/generative-energy/content/${props.articleName}.html`);
  28. const result = await articleResponse.text();
  29. return result;
  30. },
  31. );
  32. const {
  33. result: articleData,
  34. stateIsReady: articleDataReady,
  35. } = useAsyncState('article-data', ({hostUrl}) => getDJAPI(hostUrl, '/rp-articles'));
  36. const articleMetadata = computed(() => articleData.value?.find(_ => _.slug === props.articleName));
  37. useHead({
  38. title: () => articleMetadata.value?.title ?? '',
  39. metatags: () => articleMetadata.value ? [
  40. { name: 'title', content: articleMetadata.value.title },
  41. { name: 'author', content: articleMetadata.value.author },
  42. ] : [],
  43. });
  44. function transformArticleNode(node: Node): VNode | string {
  45. if (node.nodeType === node.ELEMENT_NODE) {
  46. const el = node as Element;
  47. const attrs: Record<string, string> = {};
  48. const children = [...node.childNodes].map((_) => transformArticleNode(_));
  49. if (el.attributes.getNamedItem('lang')?.value === 'en') {
  50. el.ariaHidden = 'true';
  51. }
  52. if (el.tagName === "P") {
  53. (el as HTMLParagraphElement).dataset.tunit = '';
  54. }
  55. if ('dataset' in el && 'tunit' in (el as HTMLElement).dataset) {
  56. if (el.tagName !== 'H1') {
  57. el.classList.add("text-slab");
  58. } else {
  59. el.classList.add("title");
  60. }
  61. if (!('notranslate' in (el as HTMLElement).dataset)) {
  62. children.unshift(h("button", {
  63. class: "swap",
  64. onClick: (e) => {
  65. (e.target as HTMLButtonElement).parentElement?.classList.toggle("swap");
  66. },
  67. }, "↻"));
  68. }
  69. }
  70. for (let i = 0; i < el.attributes.length; i++) {
  71. const item = el.attributes.item(i);
  72. if (item) {
  73. attrs[item.name] = item.value;
  74. }
  75. }
  76. return h((node as Element).tagName, attrs, children);
  77. } else {
  78. return createTextVNode(node.textContent ?? "");
  79. }
  80. }
  81. function ArticleContentTransformed() {
  82. if (articleContent.value) {
  83. const dom = parseDom(articleContent.value);
  84. return h("div", {}, [...dom.children].map((_) => transformArticleNode(_)));
  85. }
  86. return <div>Artikel lädt...</div>;
  87. }
  88. await Promise.all([stateIsReady, articleDataReady]);
  89. return () => (
  90. <div class="ge-article">
  91. <div class="header">
  92. <RouterLink to={{ name: "GEDeutsch" }}>Zur Artikelübersicht</RouterLink>
  93. <button onClick={clickBtn}>
  94. Sprache auf <span>{currentLang.value === "en" ? "Deutsch" : "Englisch"}</span> umschalten
  95. </button>
  96. </div>
  97. <p class="text-slab">
  98. Bei dem untenstehenden Artikel handelt es sich um eine hobbymäßige, amateurhafte Übersetzung des
  99. Artikels „{ articleMetadata.value?.titleEn }“ von Ray Peat. Bei Ungenauigkeiten oder Fehlübersetzungen freue ich mich über <DJEmail>eine Mail</DJEmail>!
  100. </p>
  101. { articleMetadata.value?.tags?.includes('in-arbeit') && <h5 class="baustelle">🚧 Bitte beachte, dass diese Übersetzung noch in Arbeit ist! 🚧</h5> }
  102. <hr />
  103. <article class={`lang-${currentLang.value}`}>
  104. <ArticleContentTransformed />
  105. </article>
  106. </div>
  107. );
  108. },
  109. });