feat: add Open Graph image generation and SEO metadata
- Introduced `PageSeo` component for managing page metadata for social sharing. - Created Open Graph image templates using SVG and static fonts for better visual representation. - Implemented service alert management with functions to check active alerts and format route numbers. - Added utility functions for generating and watching alert validity. - Developed a script to generate Open Graph images dynamically based on page content. - Included tests for service alert functionalities to ensure correctness and reliability.
This commit is contained in:
114
lib/social.mjs
Normal file
114
lib/social.mjs
Normal file
@@ -0,0 +1,114 @@
|
||||
import { legalCopy } from '../modules/legal/content.ts';
|
||||
|
||||
export const siteUrl = 'https://ridebus.by';
|
||||
export const socialLocales = ['en', 'ru'];
|
||||
export const ogImageSize = { width: 1200, height: 630 };
|
||||
|
||||
// Shared by the page metadata and the build-time image generator.
|
||||
export const socialPages = {
|
||||
home: {
|
||||
path: '/',
|
||||
illustration: 'schedule',
|
||||
en: {
|
||||
title: 'RideBus',
|
||||
description:
|
||||
'RideBus — An app that helps you conveniently view public transportation schedules',
|
||||
label: 'Public transport, at hand',
|
||||
heading: ['Public transport', 'made simple'],
|
||||
caption: 'Schedules, stops and routes. All in one small app.',
|
||||
tags: ['Schedules', 'Routes', 'Favourites'],
|
||||
},
|
||||
ru: {
|
||||
title: 'RideBus',
|
||||
description:
|
||||
'RideBus — Приложение, которое поможет вам удобно смотреть расписание общественного транспорта',
|
||||
label: 'Транспорт под рукой',
|
||||
heading: ['Расписание', 'транспорта'],
|
||||
caption: 'Расписания, остановки и маршруты. В одном приложении.',
|
||||
tags: ['Расписания', 'Маршруты', 'Избранное'],
|
||||
},
|
||||
},
|
||||
contribute: {
|
||||
path: '/contribute',
|
||||
illustration: 'community',
|
||||
en: {
|
||||
title: 'RideBus - Contribute',
|
||||
description:
|
||||
'Help RideBus grow: add your city, share the app or leave a review.',
|
||||
label: 'Made with love',
|
||||
heading: ['Help RideBus', 'grow with you'],
|
||||
caption: 'Add your city, share the app or leave a review.',
|
||||
tags: ['Open source', 'Community'],
|
||||
},
|
||||
ru: {
|
||||
title: 'RideBus - Вклад',
|
||||
description:
|
||||
'Помогите развитию RideBus: добавьте свой город, расскажите о приложении или оставьте отзыв.',
|
||||
label: 'Сделано с любовью',
|
||||
heading: ['Помогите RideBus', 'стать лучше'],
|
||||
caption:
|
||||
'Добавьте свой город, расскажите о приложении или оставьте отзыв.',
|
||||
tags: ['Открытый код', 'Сообщество'],
|
||||
},
|
||||
},
|
||||
privacy: {
|
||||
path: '/privacy',
|
||||
illustration: 'privacy',
|
||||
en: {
|
||||
title: `${legalCopy.en.documents.privacy.title} — RideBus`,
|
||||
description: legalCopy.en.documents.privacy.description,
|
||||
label: legalCopy.en.label,
|
||||
heading: ['Privacy', 'policy'],
|
||||
caption: legalCopy.en.documents.privacy.description,
|
||||
tags: ['Data', 'Permissions'],
|
||||
},
|
||||
ru: {
|
||||
title: `${legalCopy.ru.documents.privacy.title} — RideBus`,
|
||||
description: legalCopy.ru.documents.privacy.description,
|
||||
label: legalCopy.ru.label,
|
||||
heading: ['Политика', 'конфиденциальности'],
|
||||
caption: legalCopy.ru.documents.privacy.description,
|
||||
tags: ['Данные', 'Разрешения'],
|
||||
},
|
||||
},
|
||||
terms: {
|
||||
path: '/terms',
|
||||
illustration: 'terms',
|
||||
en: {
|
||||
title: `${legalCopy.en.documents.terms.title} — RideBus`,
|
||||
description: legalCopy.en.documents.terms.description,
|
||||
label: legalCopy.en.label,
|
||||
heading: ['Terms', 'of use'],
|
||||
caption: legalCopy.en.documents.terms.description,
|
||||
tags: ['The service', 'Guidelines'],
|
||||
},
|
||||
ru: {
|
||||
title: `${legalCopy.ru.documents.terms.title} — RideBus`,
|
||||
description: legalCopy.ru.documents.terms.description,
|
||||
label: legalCopy.ru.label,
|
||||
heading: ['Условия', 'использования'],
|
||||
caption: legalCopy.ru.documents.terms.description,
|
||||
tags: ['О сервисе', 'Правила'],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/** @param {keyof typeof socialPages} page @param {string} locale */
|
||||
export function getSocialMetadata(page, locale) {
|
||||
const language = locale === 'ru' ? 'ru' : 'en';
|
||||
const definition = socialPages[page];
|
||||
const localizedPath =
|
||||
language === 'ru'
|
||||
? definition.path === '/'
|
||||
? '/ru'
|
||||
: `/ru${definition.path}`
|
||||
: definition.path;
|
||||
|
||||
return {
|
||||
...definition[language],
|
||||
url: `${siteUrl}${localizedPath}`,
|
||||
image: `${siteUrl}/images/og/${page}-${language}.png`,
|
||||
locale: language === 'ru' ? 'ru_RU' : 'en_US',
|
||||
alternateLocale: language === 'ru' ? 'en_US' : 'ru_RU',
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user