Layout

Layoutdateien werden aus TypeScript Funktionen erstellt. Sie können so viele Eigenschaften definieren, wie Sie möchten, solange Sie einen String zurückgeben. Lassen Sie dann jede Seite in Ihrem Projekt die entsprechenden Daten an diese Funktion übergeben.

Nur die Verwendung von TypeScript Dateien hält die Anzahl der Sprachen in diesem Projekt gering. Sie müssen nicht noch eine weitere Template Sprache lernen. Um die Interaktion mit HTML in TypeScript zu erleichtern, habe ich den `/* HTML */` Kommentar verwendet, um mehrzeilige Strings zu ermöglichen. Das wird von 2 Erweiterungen erkannt, die ich als nützlich empfinde.

  • esbenp.prettier-vscode
  • tobermory.es6-string-html
TypeScript - src/Layout.ts
import { LanguageOption } from "./GlobalSitesCore/LanguageOption";
import i18next from "./GlobalSitesCore/i18n";
import { languageSettings } from "./GlobalSitesCore/languages";
import { urlBuilder } from "./GlobalSitesCore/urlBuilder";

interface LayoutProps {
  content: string;
  lang: string;
  description: string;
  title: string;
  languageOptions: LanguageOption[];
}
export function Layout(props: LayoutProps): string {
  const baseUrl = "https://www.globalsites.ai";
  var currentLanguageOption = props.languageOptions.find(
    (option) => option.code == props.lang
  );
  var defaultLanguageOption = props.languageOptions.find(
    (option) => option.code == languageSettings.defaultLanguage
  );

  return /* HTML */ `
    <!DOCTYPE html>
    <html lang="${props.lang}">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta name="description" content="${props.description}" />
        <meta property="og:title" content="${props.title}" />
        <meta property="og:description" content="${props.description}" />
        <meta property="og:url" content="${currentLanguageOption?.url}" />
        <meta property="og:type" content="website" />
        <meta property="og:site_name" content="Global Sites" />
        <meta property="og:locale" content="${props.lang}" />
        <meta property="og:image" content="${baseUrl}/ogImage.jpg" />
        <meta name="twitter:card" content="summary_large_image" />
        <meta name="twitter:site" content="@benwmaddox" />
        <meta name="twitter:creator" content="@benwmaddox" />
        <meta name="twitter:title" content="${props.title}" />
        <meta name="twitter:description" content="${props.description}" />
        <meta name="twitter:image" content="${baseUrl}/ogImage.jpg" />

        <link
          rel="sitemap"
          type="application/xml"
          title="Sitemap"
          href="/sitemap.xml"
        />
        <link
          rel="stylesheet"
          href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/dark.min.css"
        />
        <link rel="stylesheet" href="/styles.css" />
        <link rel="icon" type="image/svg+xml" href="/icon.svg" />
        <title>
          ${props.title ? props.title + " - " : ""}${i18next.t(`Global Sites`)}
        </title>
        <style>
          body {
            height: 100vh;
          }
        </style>

        ${props.languageOptions
          .map((option) => {
            return option.code == languageSettings.defaultLanguage
              ? `<link rel="alternate" href="${baseUrl}${option.url}" hreflang="${option.code}"/>
<link rel="alternate" href="${baseUrl}${option.url}" hreflang="x-default"/>`
              : `<link rel="alternate" href="${baseUrl}${option.url}" hreflang="${option.code}"/>`;
          })
          .join("
")}
        <script>
          function switchLanguage() {
            var selectedLanguageUrl =
              document.getElementById("language-select").value;
            window.location.href = selectedLanguageUrl;
          }
        </script>
      </head>
      <body>
        <header>
          <div class="flex">
            <div class="logo">
              <a
                href="${props.lang === "en" ? "/" : `/${props.lang}/`}"
                style="display:inline-block;"
              >
                <img src="/logo.svg" alt="Logo"
              /></a>
            </div>

            <div class="language-switcher">
              <select id="language-select" onchange="switchLanguage()">
                ${[...props.languageOptions]
                  .sort((a, b) =>
                    a.code == props.lang ? 1 : a.code.localeCompare(b.code)
                  )
                  .map((option) => {
                    return `<option value="${option.url}" ${
                      option.code === props.lang ? "selected" : ""
                    }>${option.name}</option>`;
                  })
                  .join("")}
              </select>
            </div>
            <nav>
              <a href="/${urlBuilder(undefined, undefined)}"
                >${i18next.t("Home")}</a
              >
              |
              <a href="/${urlBuilder(undefined, "documentation")}"
                >${i18next.t("Documentation")}</a
              >
              |
              <a href="/${urlBuilder(undefined, "contact-us")}"
                >${i18next.t("Contact Us")}</a
              >
              |
              <a href="/${urlBuilder(undefined, "privacy-policy")}"
                >${i18next.t("Privacy Policy")}</a
              >
              |
              <a href="/${urlBuilder(undefined, "faq")}">${i18next.t("FAQ")}</a>
            </nav>
          </div>
        </header>
        <main>
          <div class="container">${props.content}</div>
        </main>
        <footer>
          <div class="footer-content">
            <p>
              <a href="/${urlBuilder(undefined, "contact-us")}"
                >${i18next.t("Contact Us")}</a
              >
              |
              <a href="/${urlBuilder(undefined, "privacy-policy")}"
                >${i18next.t("Privacy Policy")}</a
              >
              |
              <a href="/${urlBuilder(undefined, "faq")}">${i18next.t("FAQ")}</a>
              &copy; ${new Date().getFullYear()} ${baseUrl}
            </p>
            <div>
              ${[...props.languageOptions]
                .map((option) => {
                  return `<a href="${option.url}" >${option.name}</a>`;
                })
                .join(" | ")}
            </div>
          </div>
        </footer>
      </body>
    </html>
  `;
}