This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
import type { AppLocale } from "./locale";
|
||||
|
||||
export const SITE_NAME_KEY = "siteName";
|
||||
export const SITE_SETTINGS_KEY = "site_settings";
|
||||
export const SITE_SETTINGS_ENTITY_TYPE = "site-settings";
|
||||
export const SITE_SETTINGS_ENTITY_ID = "global";
|
||||
export const SITE_SETTINGS_FAVICON_FIELD_KEY = "favicon";
|
||||
export const SITE_SETTINGS_DEFAULT_OG_IMAGE_FIELD_KEY = "defaultOgImage";
|
||||
export const PAGE_TITLE_TOKEN = "{pageTitle}";
|
||||
export const SITE_NAME_TOKEN = "{siteName}";
|
||||
|
||||
export const DEFAULT_SITE_NAME = "moh-sass";
|
||||
export const DEFAULT_SITE_DESCRIPTION = "Multilingual Next.js base project";
|
||||
|
||||
type SiteLocaleSettings = {
|
||||
siteName: string;
|
||||
titleTemplate: string;
|
||||
siteDescription: string;
|
||||
subhead: string;
|
||||
};
|
||||
|
||||
export type SiteSettings = {
|
||||
locales: Record<AppLocale, SiteLocaleSettings>;
|
||||
};
|
||||
|
||||
export type SiteSettingsMediaBinding = {
|
||||
assetId: string;
|
||||
url: string;
|
||||
};
|
||||
|
||||
export type SiteSettingsMediaBindings = {
|
||||
favicon: SiteSettingsMediaBinding | null;
|
||||
defaultOgImage: SiteSettingsMediaBinding | null;
|
||||
};
|
||||
|
||||
function normalizeSiteLocaleSettings(
|
||||
input: unknown,
|
||||
fallbackName: string,
|
||||
fallbackDescription: string,
|
||||
): SiteLocaleSettings {
|
||||
const value = input && typeof input === "object" ? (input as Record<string, unknown>) : {};
|
||||
|
||||
return {
|
||||
siteName:
|
||||
typeof value.siteName === "string" && value.siteName.trim()
|
||||
? value.siteName.trim()
|
||||
: fallbackName,
|
||||
titleTemplate:
|
||||
typeof value.titleTemplate === "string" &&
|
||||
value.titleTemplate.trim() &&
|
||||
value.titleTemplate.includes(PAGE_TITLE_TOKEN)
|
||||
? value.titleTemplate.trim()
|
||||
: `${PAGE_TITLE_TOKEN} | ${SITE_NAME_TOKEN}`,
|
||||
siteDescription:
|
||||
typeof value.siteDescription === "string"
|
||||
? value.siteDescription.trim()
|
||||
: fallbackDescription,
|
||||
subhead: typeof value.subhead === "string" ? value.subhead.trim() : "",
|
||||
};
|
||||
}
|
||||
|
||||
export function getDefaultSiteSettingsMediaBindings(): SiteSettingsMediaBindings {
|
||||
return {
|
||||
favicon: null,
|
||||
defaultOgImage: null,
|
||||
};
|
||||
}
|
||||
|
||||
export function buildDefaultSiteSettings(fallbackName = DEFAULT_SITE_NAME): SiteSettings {
|
||||
return {
|
||||
locales: {
|
||||
ar: {
|
||||
siteName: fallbackName,
|
||||
titleTemplate: `${PAGE_TITLE_TOKEN} | ${SITE_NAME_TOKEN}`,
|
||||
siteDescription: DEFAULT_SITE_DESCRIPTION,
|
||||
subhead: "",
|
||||
},
|
||||
en: {
|
||||
siteName: fallbackName,
|
||||
titleTemplate: `${PAGE_TITLE_TOKEN} | ${SITE_NAME_TOKEN}`,
|
||||
siteDescription: DEFAULT_SITE_DESCRIPTION,
|
||||
subhead: "",
|
||||
},
|
||||
de: {
|
||||
siteName: fallbackName,
|
||||
titleTemplate: `${PAGE_TITLE_TOKEN} | ${SITE_NAME_TOKEN}`,
|
||||
siteDescription: DEFAULT_SITE_DESCRIPTION,
|
||||
subhead: "",
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function parseSiteSettingsValue(
|
||||
rawValue: string | null | undefined,
|
||||
fallbackName = DEFAULT_SITE_NAME,
|
||||
): SiteSettings {
|
||||
const defaults = buildDefaultSiteSettings(fallbackName);
|
||||
|
||||
if (!rawValue) {
|
||||
return defaults;
|
||||
}
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(rawValue) as Record<string, unknown>;
|
||||
const locales = parsed.locales && typeof parsed.locales === "object"
|
||||
? (parsed.locales as Record<string, unknown>)
|
||||
: {};
|
||||
|
||||
const siteSettings: SiteSettings = {
|
||||
locales: {
|
||||
ar: normalizeSiteLocaleSettings(
|
||||
{
|
||||
titleTemplate:
|
||||
typeof parsed.titleTemplate === "string" && parsed.titleTemplate.trim()
|
||||
? parsed.titleTemplate.trim()
|
||||
: undefined,
|
||||
...(locales.ar && typeof locales.ar === "object" ? (locales.ar as Record<string, unknown>) : {}),
|
||||
},
|
||||
defaults.locales.ar.siteName,
|
||||
defaults.locales.ar.siteDescription,
|
||||
),
|
||||
en: normalizeSiteLocaleSettings(
|
||||
{
|
||||
titleTemplate:
|
||||
typeof parsed.titleTemplate === "string" && parsed.titleTemplate.trim()
|
||||
? parsed.titleTemplate.trim()
|
||||
: undefined,
|
||||
...(locales.en && typeof locales.en === "object" ? (locales.en as Record<string, unknown>) : {}),
|
||||
},
|
||||
defaults.locales.en.siteName,
|
||||
defaults.locales.en.siteDescription,
|
||||
),
|
||||
de: normalizeSiteLocaleSettings(
|
||||
{
|
||||
titleTemplate:
|
||||
typeof parsed.titleTemplate === "string" && parsed.titleTemplate.trim()
|
||||
? parsed.titleTemplate.trim()
|
||||
: undefined,
|
||||
...(locales.de && typeof locales.de === "object" ? (locales.de as Record<string, unknown>) : {}),
|
||||
},
|
||||
defaults.locales.de.siteName,
|
||||
defaults.locales.de.siteDescription,
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
return siteSettings;
|
||||
} catch {
|
||||
return defaults;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user