mirror of
https://github.com/BradNut/personal-website-sveltekit
synced 2025-09-08 23:20:18 +00:00
Moving og generation to lib component (Geoff Rich influenced).
This commit is contained in:
parent
0826667fb7
commit
17b5325ec4
5 changed files with 57 additions and 37 deletions
|
|
@ -10,12 +10,12 @@
|
||||||
|
|
||||||
<div class="social-card" style={`width: ${width}px; height: ${height}px;`}>
|
<div class="social-card" style={`width: ${width}px; height: ${height}px;`}>
|
||||||
<div class="social-card-header">
|
<div class="social-card-header">
|
||||||
<div class="social-card-title">
|
<div class="social-card-title">
|
||||||
<div class="social-card-image">
|
<div class="social-card-image">
|
||||||
<img src={image || '/images/b_shell_nut_favicon.png'} alt="Bradley Shellnut" />
|
<img src={image || '/images/b_shell_nut_favicon.png'} alt="Bradley Shellnut" />
|
||||||
</div>
|
|
||||||
<h1>{header}</h1>
|
|
||||||
</div>
|
</div>
|
||||||
|
<h1>{header}</h1>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="social-card-content">
|
<div class="social-card-content">
|
||||||
<h2 class="page">{page}</h2>
|
<h2 class="page">{page}</h2>
|
||||||
|
|
|
||||||
40
src/lib/renderImage.ts
Normal file
40
src/lib/renderImage.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
import satori from 'satori';
|
||||||
|
import { Resvg } from '@resvg/resvg-js';
|
||||||
|
import { html as toReactNode } from 'satori-html';
|
||||||
|
|
||||||
|
// we use a Vite plugin to turn this import into the result of fs.readFileSync during build
|
||||||
|
import firaSansSemiBold from '$lib/fonts/FiraSans-SemiBold.ttf';
|
||||||
|
import { dev } from '$app/environment';
|
||||||
|
|
||||||
|
export async function componentToPng(component, props, height, width) {
|
||||||
|
const result = component.render(props);
|
||||||
|
const markup = toReactNode(`${result.html}<style lang="css">${result.css.code}</style>`);
|
||||||
|
|
||||||
|
const svg = await satori(markup, {
|
||||||
|
fonts: [
|
||||||
|
{
|
||||||
|
name: 'Fira Sans',
|
||||||
|
data: Buffer.from(firaSansSemiBold),
|
||||||
|
style: 'normal'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
height: +height,
|
||||||
|
width: +width
|
||||||
|
});
|
||||||
|
|
||||||
|
const resvg = new Resvg(svg, {
|
||||||
|
fitTo: {
|
||||||
|
mode: 'width',
|
||||||
|
value: +width
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const png = resvg.render();
|
||||||
|
|
||||||
|
return new Response(png.asPng(), {
|
||||||
|
headers: {
|
||||||
|
'content-type': 'image/png',
|
||||||
|
'cache-control': dev ? 'no-cache, no-store' : 'public, immutable, no-transform, max-age=86400'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { BANDCAMP_USERNAME, USE_REDIS_CACHE } from '$env/static/private';
|
import { BANDCAMP_USERNAME, USE_REDIS_CACHE } from '$env/static/private';
|
||||||
import scrapeIt from 'scrape-it';
|
import scrapeIt from 'scrape-it';
|
||||||
import type { ScrapeResult } from 'scrape-it';
|
import type { ScrapeResult } from 'scrape-it';
|
||||||
import { redis } from '../server/redis';
|
import { redis } from '$lib/server/redis';
|
||||||
import type { Album } from '../types/album';
|
import type { Album } from '../types/album';
|
||||||
|
|
||||||
export async function fetchBandcampAlbums() {
|
export async function fetchBandcampAlbums() {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,12 @@ import type { PageServerLoad } from './$types';
|
||||||
import { fetchBandcampAlbums } from '$lib/util/fetchBandcampAlbums';
|
import { fetchBandcampAlbums } from '$lib/util/fetchBandcampAlbums';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ fetch, setHeaders, url }) => {
|
export const load: PageServerLoad = async ({ fetch, setHeaders, url }) => {
|
||||||
const baseUrl = new URL(url.origin).href || PUBLIC_SITE_URL || 'https://bradleyshellnut.com';
|
let baseUrl = 'https://bradleyshellnut.com';
|
||||||
|
if (url.origin.includes('prerender')) {
|
||||||
|
baseUrl = PUBLIC_SITE_URL || 'https://bradleyshellnut.com';
|
||||||
|
} else {
|
||||||
|
baseUrl = new URL(url.origin).href || PUBLIC_SITE_URL || 'https://bradleyshellnut.com';
|
||||||
|
}
|
||||||
const currentPageUrl = new URL(url.pathname, url.origin).href;
|
const currentPageUrl = new URL(url.pathname, url.origin).href;
|
||||||
|
|
||||||
const metaTags: MetaTagsProps = Object.freeze({
|
const metaTags: MetaTagsProps = Object.freeze({
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import { Resvg } from '@resvg/resvg-js';
|
||||||
import { html as toReactNode } from 'satori-html';
|
import { html as toReactNode } from 'satori-html';
|
||||||
import FiraSansSemiBold from '$lib/fonts/FiraSans-SemiBold.ttf';
|
import FiraSansSemiBold from '$lib/fonts/FiraSans-SemiBold.ttf';
|
||||||
import SocialImageCard from '$lib/components/socialImageCard.svelte';
|
import SocialImageCard from '$lib/components/socialImageCard.svelte';
|
||||||
|
import { dev } from '$app/environment';
|
||||||
|
import { componentToPng } from '$root/lib/renderImage';
|
||||||
|
|
||||||
const height = 630;
|
const height = 630;
|
||||||
const width = 1200;
|
const width = 1200;
|
||||||
|
|
@ -14,7 +16,8 @@ export const GET: RequestHandler = async ({ url }) => {
|
||||||
const header = url.searchParams.get('header') ?? undefined;
|
const header = url.searchParams.get('header') ?? undefined;
|
||||||
const page = url.searchParams.get('page') ?? undefined;
|
const page = url.searchParams.get('page') ?? undefined;
|
||||||
const content = url.searchParams.get('content') ?? '';
|
const content = url.searchParams.get('content') ?? '';
|
||||||
const result = SocialImageCard.render({
|
|
||||||
|
return componentToPng(SocialImageCard, {
|
||||||
header,
|
header,
|
||||||
page,
|
page,
|
||||||
content,
|
content,
|
||||||
|
|
@ -22,35 +25,7 @@ export const GET: RequestHandler = async ({ url }) => {
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
url: new URL(url.origin).href
|
url: new URL(url.origin).href
|
||||||
});
|
}, height, width);
|
||||||
console.log('result', result);
|
|
||||||
const element = toReactNode(`${result.html}<style>${result.css.code}</style>`);
|
|
||||||
const svg = await satori(element, {
|
|
||||||
fonts: [
|
|
||||||
{
|
|
||||||
name: 'Fira Sans',
|
|
||||||
data: Buffer.from(FiraSansSemiBold),
|
|
||||||
style: 'normal'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
height,
|
|
||||||
width
|
|
||||||
});
|
|
||||||
|
|
||||||
const resvg = new Resvg(svg, {
|
|
||||||
fitTo: {
|
|
||||||
mode: 'width',
|
|
||||||
value: width
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const image = resvg.render();
|
|
||||||
|
|
||||||
return new Response(image.asPng(), {
|
|
||||||
headers: {
|
|
||||||
'content-type': 'image/png'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue