60 lines
2.3 KiB
TypeScript
60 lines
2.3 KiB
TypeScript
import type { PageSeoData } from "@montech/shared";
|
|||
|
|
import type { MaybeRefOrGetter } from "vue";
|
||
|
|
|
||
|
|
const DEFAULT_TITLE = "منتک | هوشافزار منظر - پلتفرم راهکارهای نرمافزاری و هوش مصنوعی";
|
||
|
|
const DEFAULT_DESCRIPTION =
|
||
|
|
"با کمک هوش مصنوعی منتک، بهترین نرمافزارها و خدمات متناسب با کسبوکار شما پیشنهاد میشود.";
|
||
|
|
|
||
|
|
function absoluteUrl(siteUrl: string, pathOrUrl?: string | null) {
|
||
|
|
if (!pathOrUrl) return undefined;
|
||
|
|
if (/^https?:\/\//i.test(pathOrUrl)) return pathOrUrl;
|
||
|
|
return `${siteUrl.replace(/\/$/, "")}${pathOrUrl.startsWith("/") ? "" : "/"}${pathOrUrl}`;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Central metadata for every page: title, description, canonical, Open Graph, Twitter and robots. */
|
||
|
|
export function usePageSeo(input: MaybeRefOrGetter<Partial<PageSeoData> | null | undefined>, opts: { type?: "website" | "article" } = {}) {
|
||
|
|
const config = useRuntimeConfig();
|
||
|
|
const route = useRoute();
|
||
|
|
const siteUrl = config.public.siteUrl.replace(/\/$/, "");
|
||
|
|
|
||
|
|
const seo = computed(() => toValue(input) || {});
|
||
|
|
const title = computed(() => seo.value.title || DEFAULT_TITLE);
|
||
|
|
const description = computed(() => seo.value.description || DEFAULT_DESCRIPTION);
|
||
|
|
const canonical = computed(() => absoluteUrl(siteUrl, seo.value.canonical) || `${siteUrl}${route.path === "/" ? "/" : route.path}`);
|
||
|
|
const image = computed(() => absoluteUrl(siteUrl, seo.value.ogImage) || `${siteUrl}/brand/og-default.png`);
|
||
|
|
|
||
|
|
useSeoMeta({
|
||
|
|
title,
|
||
|
|
description,
|
||
|
|
ogTitle: title,
|
||
|
|
ogDescription: description,
|
||
|
|
ogType: opts.type ?? "website",
|
||
|
|
ogUrl: canonical,
|
||
|
|
ogImage: image,
|
||
|
|
ogLocale: "fa_IR",
|
||
|
|
ogSiteName: "منتک",
|
||
|
|
twitterCard: "summary_large_image",
|
||
|
|
twitterTitle: title,
|
||
|
|
twitterDescription: description,
|
||
|
|
twitterImage: image,
|
||
|
|
robots: computed(() => (seo.value.noIndex ? "noindex,nofollow" : "index,follow,max-image-preview:large")),
|
||
|
|
});
|
||
|
|
|
||
|
|
useHead({
|
||
|
|
link: [{ rel: "canonical", href: canonical }],
|
||
|
|
});
|
||
|
|
|
||
|
|
return { canonical, siteUrl };
|
||
|
|
}
|
||
|
|
|
||
|
|
export function useJsonLd(schema: MaybeRefOrGetter<Record<string, unknown> | Record<string, unknown>[]>) {
|
||
|
|
useHead({
|
||
|
|
script: [
|
||
|
|
{
|
||
|
|
type: "application/ld+json",
|
||
|
|
innerHTML: computed(() => JSON.stringify(toValue(schema))),
|
||
|
|
},
|
||
|
|
],
|
||
|
|
});
|
||
|
|
}
|