Skip to content

Commit

Permalink
Add auto-generated OpenGraph images (withastro#1651)
Browse files Browse the repository at this point in the history
* Add auto-generated OpenGraph images

* Upgrade `astro-og-canvas`

* Update to newer OG image library

Added improved handling for some of docs’ longer titles/descriptions
  • Loading branch information
delucis authored Oct 2, 2022
1 parent 697b873 commit 6b78cff
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 13 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"@typescript-eslint/parser": "^5.32.0",
"astro": "1.2.1",
"astro-eslint-parser": "^0.4.5",
"astro-og-canvas": "^0.1.4",
"bcp-47-normalize": "^2.1.0",
"chroma-js": "^2.4.2",
"dedent-js": "^1.0.1",
Expand Down
31 changes: 22 additions & 9 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 8 additions & 4 deletions src/components/HeadSEO.astro
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
---
import { OPEN_GRAPH } from '../config';
import { getLanguageFromURL } from '../util';
import languages from '../i18n/languages';
import { normalizeLangTag } from '../i18n/bcp-normalize';
import languages from '../i18n/languages';
import { useTranslations } from '../i18n/util';
import { getLanguageFromURL } from '../util';
import { getOgImageUrl } from '../util/getOgImageUrl';
export interface Props {
content: any;
site: any;
canonicalURL: URL;
}
const { content = {}, canonicalURL } = Astro.props;
const t = useTranslations(Astro);
const imageSrc = content?.image?.src ?? t('site.og.imageSrc');
const ogImageUrl = getOgImageUrl(canonicalURL.pathname, !!Astro.params.fallback);
const imageSrc = content?.image?.src ?? ogImageUrl ?? t('site.og.imageSrc');
const canonicalImageSrc = new URL(imageSrc, Astro.site);
const imageAlt = content?.image?.alt ?? t('site.og.imageAlt');
const imageAlt = content?.image?.alt ?? imageSrc === ogImageUrl ? '' : t('site.og.imageAlt');
const lang = getLanguageFromURL(canonicalURL?.pathname || '/');
const bcpLang = normalizeLangTag(lang);
const ogLocale = bcpLang.replace(/-/g, '_');
Expand Down
Binary file added src/docs-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 73 additions & 0 deletions src/pages/open-graph/[...path].ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { OGImageRoute } from 'astro-og-canvas';
import { getLanguageFromURL } from '../../util';
import { rtlLanguages } from '../../i18n/languages';

export const { getStaticPaths, get } = OGImageRoute({
param: 'path',

pages: await import.meta.glob('/src/pages/**/*.md'),

getImageOptions: async (_, mod) => {
const page = await mod();
return {
title: page.frontmatter.title,
description: page.frontmatter.description,
dir: rtlLanguages.has(getLanguageFromURL(page.url)) ? 'rtl' : 'ltr',
logo: {
path: './src/docs-logo.png',
size: [400],
},
border: { color: [255, 93, 1], width: 20, side: 'inline-start' },
bgGradient: [
[42, 35, 62],
[23, 20, 36],
],
font: {
title: {
size: 78,
families: [
'Work Sans',
'Noto Sans Black',
'Noto Sans Arabic',
'Noto Sans SC Black',
'Noto Sans TC Black',
'Noto Sans JP Black',
],
weight: 'ExtraBold',
},
description: {
size: 45,
lineHeight: 1.25,
families: [
'Work Sans',
'Noto Sans',
'Noto Sans Arabic',
'Noto Sans SC',
'Noto Sans TC',
'Noto Sans JP',
],
weight: 'Normal',
},
},
fonts: [
'https://api.fontsource.org/v1/fonts/work-sans/latin-400-normal.ttf',
'https://api.fontsource.org/v1/fonts/work-sans/latin-800-normal.ttf',

'https://api.fontsource.org/v1/fonts/noto-sans/cyrillic-400-normal.ttf',
'https://api.fontsource.org/v1/fonts/noto-sans/cyrillic-900-normal.ttf',

'https://api.fontsource.org/v1/fonts/noto-sans-sc/chinese-simplified-400-normal.ttf',
'https://api.fontsource.org/v1/fonts/noto-sans-sc/chinese-simplified-900-normal.ttf',

'https://api.fontsource.org/v1/fonts/noto-sans-tc/chinese-traditional-400-normal.ttf',
'https://api.fontsource.org/v1/fonts/noto-sans-tc/chinese-traditional-900-normal.ttf',

'https://api.fontsource.org/v1/fonts/noto-sans-jp/japanese-400-normal.ttf',
'https://api.fontsource.org/v1/fonts/noto-sans-jp/japanese-900-normal.ttf',

'https://api.fontsource.org/v1/fonts/noto-sans-arabic/arabic-400-normal.ttf',
'https://api.fontsource.org/v1/fonts/noto-sans-arabic/arabic-800-normal.ttf',
],
};
},
});
22 changes: 22 additions & 0 deletions src/util/getOgImageUrl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { GetStaticPathsOptions, GetStaticPathsResult } from 'astro';
import { getStaticPaths } from '../pages/open-graph/[...path]';

const routes = (await getStaticPaths({} as GetStaticPathsOptions)) as GetStaticPathsResult;

/** All the OpenGraph image paths as generated by our `getStaticPaths`. */
const paths = new Set(routes.map(({ params }) => params.path));

/**
* Get the path to the OpenGraph image for a page
* @param path Pathname of the page URL.
* @param isFallback Whether or not this page is displaying fallback content.
* @returns Path to the OpenGraph image if found. Otherwise, `undefined`.
*/
export function getOgImageUrl(path: string, isFallback: boolean): string | undefined {
let imagePath = path.replace(/^\//, '').replace(/\/$/, '') + '.png';
if (isFallback) {
// Replace the language segment with 'en' for fallback pages.
imagePath = 'en' + imagePath.slice(imagePath.indexOf('/'));
}
if (paths.has(imagePath)) return '/open-graph/' + imagePath;
}

0 comments on commit 6b78cff

Please sign in to comment.