تخطيط
تٌصنع ملفات التخطيط من دوال TypeScript. يمكنك تعريف العديد من الخصائص كما تريد طالما أنك تعيد سلسلة نصية. ثم اجعل كل صفحة في مشروعك تمرر البيانات ذات الصلة إلى هذه الدالة.
استخدام ملفات TypeScript فقط يبقي عدد اللغات منخفضًا في هذا المشروع. لا تحتاج إلى تعلم لغة قوالب جديدة بعد. لجعل التفاعل مع HTML في TypeScript أسهل، لقد استخدمت تعليق `/* HTML */` للسماح بسلاسل متعددة الأسطر. يتم التعرف على ذلك من قِبل ملحقين أجدهم مفيدين.
- 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>
© ${new Date().getFullYear()} ${baseUrl}
</p>
<div>
${[...props.languageOptions]
.map((option) => {
return `<a href="${option.url}" >${option.name}</a>`;
})
.join(" | ")}
</div>
</div>
</footer>
</body>
</html>
`;
}