djledda.de main
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

GEDeutschArticle.tsx 3.6 KiB

2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
2 个月前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import { createTextVNode, 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. export default defineComponent({
  6. name: "ge-deutsch-article",
  7. props: {
  8. articleName: {
  9. type: String,
  10. required: true,
  11. },
  12. },
  13. async setup(props) {
  14. const currentLang = ref<"en" | "de">("de");
  15. function clickBtn() {
  16. currentLang.value = currentLang.value === "en" ? "de" : "en";
  17. }
  18. const parseDom = inject(
  19. "dom-parse",
  20. (innerHTML: string) => Object.assign(document.createElement("div"), { innerHTML }),
  21. );
  22. const title = ref("");
  23. const { result: articleContent, stateIsReady } = useAsyncState(
  24. "ge-deutsch-article-data",
  25. async ({ hostUrl }) => {
  26. const articleResponse = await fetch(`${hostUrl}/generative-energy/content/${props.articleName}.html`);
  27. const result = await articleResponse.text();
  28. title.value = result.split('<h1 lang="de">')[1].split("</h1>")[0];
  29. return result;
  30. },
  31. );
  32. useHead({ title });
  33. onServerPrefetch(() =>
  34. new Promise<void>((res) => {
  35. watchEffect(() => {
  36. if (title.value !== "") {
  37. console.log("resolve", title.value);
  38. res();
  39. }
  40. });
  41. })
  42. );
  43. function transformArticleNode(node: Node): VNode | string {
  44. if (node.nodeType === node.ELEMENT_NODE) {
  45. const el = node as Element;
  46. const attrs: Record<string, string> = {};
  47. const children = [...node.childNodes].map((_) => transformArticleNode(_));
  48. if (el.tagName === "P") {
  49. el.classList.add("text-slab");
  50. children.unshift(h("button", {
  51. class: "swap",
  52. onClick: (e) => {
  53. e.target.parentElement.classList.toggle("swap");
  54. },
  55. }, "↻"));
  56. }
  57. for (let i = 0; i < el.attributes.length; i++) {
  58. const item = el.attributes.item(i);
  59. if (item) {
  60. attrs[item.name] = item.value;
  61. }
  62. }
  63. return h((node as Element).tagName, attrs, children);
  64. } else {
  65. return createTextVNode(node.textContent ?? "");
  66. }
  67. }
  68. function ArticleContentTransformed() {
  69. if (articleContent.value) {
  70. const dom = parseDom(articleContent.value);
  71. return h("div", {}, [...dom.children].map((_) => transformArticleNode(_)));
  72. }
  73. return <div>Artikel lädt...</div>;
  74. }
  75. await stateIsReady;
  76. return () => (
  77. <div class="ge-article">
  78. <div class="header">
  79. <RouterLink to={{ name: "GEDeutsch" }}>Zur Artikelübersicht</RouterLink>
  80. <button onClick={clickBtn}>
  81. Sprache auf <span>{currentLang.value === "en" ? "Deutsch" : "Englisch"}</span> umschalten
  82. </button>
  83. </div>
  84. <article class={`lang-${currentLang.value}`}>
  85. <ArticleContentTransformed />
  86. </article>
  87. </div>
  88. );
  89. },
  90. });