Files
edgeever/tests/browser/poster-thumbnail-generator.ts
T

43 lines
2.3 KiB
TypeScript

// Build-time only. The gallery never imports this renderer.
import { buildPosterDesign, DESIGN_TEMPLATES, templatesFor } from "../../apps/web/src/lib/poster-design/templates";
import { renderPosterBlob } from "../../apps/web/src/lib/poster-canvas";
import { loadPosterFont } from "../../apps/web/src/lib/poster-design/fonts";
import { installEditorBodyFontFaces } from "../../apps/web/src/lib/editor-body-font-faces";
installEditorBodyFontFaces();
const prepared = new Map<string, Awaited<ReturnType<typeof buildPosterDesign>>>();
const recommended = new Set(templatesFor(undefined).map(template => template.id));
Object.assign(window, {
posterThumbnailGenerator: {
templates: DESIGN_TEMPLATES.map(template => ({ id: template.id, recommended: recommended.has(template.id) })),
async prepare(id: string, zh: boolean) {
const input = {
id, zh, width: 1080, height: 1440,
title: zh ? "把想法\n变成作品" : "MAKE IDEAS\nWORTH SHARING",
subtitle: zh ? "一个好想法,值得被看见。" : "Ideas deserve to be seen.",
badge: zh ? "创作笔记" : "CREATIVE NOTES",
};
const draft = await buildPosterDesign(input);
const texts = draft.elements.filter(element => element.type === "text");
// Generation must wait for the actual typefaces; never freeze a temporary
// system-font fallback into a released thumbnail.
await Promise.all([...new Set(texts.map(element => element.fontFamily))].map(family =>
loadPosterFont(family, texts.map(element => element.text).join(" "), { deadline: false }),
));
const document = await buildPosterDesign(input);
prepared.set(`${id}:${zh}`, document);
return JSON.stringify(document);
},
async render(id: string, zh: boolean) {
const document = prepared.get(`${id}:${zh}`);
if (!document) throw new Error("Prepare template before rendering");
const blob = await renderPosterBlob(document, async () => { throw new Error("Thumbnail cannot read note resources"); }, "webp", true, 1, 0.85);
return new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(String(reader.result).split(",")[1]);
reader.onerror = () => reject(reader.error);
reader.readAsDataURL(blob);
});
},
},
});