Skip to content
This repository has been archived by the owner on Jan 21, 2023. It is now read-only.

Testing @napi-rs/canvas #182

Closed
wants to merge 15 commits into from
Binary file added api/_fonts/Inter-Bold.ttf
Binary file not shown.
Binary file removed api/_fonts/Inter-Bold.woff2
Binary file not shown.
Binary file added api/_fonts/Inter-Regular.ttf
Binary file not shown.
Binary file removed api/_fonts/Inter-Regular.woff2
Binary file not shown.
Binary file added api/_fonts/Licorice-Regular.ttf
Binary file not shown.
124 changes: 0 additions & 124 deletions api/_fonts/Vera-License.txt

This file was deleted.

Binary file removed api/_fonts/Vera-Mono.woff2
Binary file not shown.
22 changes: 0 additions & 22 deletions api/_lib/chromium.ts

This file was deleted.

30 changes: 0 additions & 30 deletions api/_lib/options.ts

This file was deleted.

13 changes: 0 additions & 13 deletions api/_lib/sanitizer.ts

This file was deleted.

146 changes: 0 additions & 146 deletions api/_lib/template.ts

This file was deleted.

73 changes: 73 additions & 0 deletions api/_lib/template.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { ParsedRequest } from './types';
import React from 'react';

export function Template(parsedReq: ParsedRequest) {
//const { text, fontSize, images, widths, heights } = parsedReq;
console.log(parsedReq);
return (<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="1280" height="640">
<defs>
<linearGradient id="rainbow" x1="0" x2="0" y1="0" y2="40%" gradientUnits="userSpaceOnUse" >
<stop stopColor="#FF5B99" offset="0%"/>
<stop stopColor="#FF5447" offset="20%"/>
<stop stopColor="#FF7B21" offset="40%"/>
<stop stopColor="#EAFC37" offset="60%"/>
<stop stopColor="#4FCB6B" offset="80%"/>
<stop stopColor="#51F7FE" offset="100%"/>
</linearGradient>
</defs>

<circle cx="0" cy="0" r="1" fill="#ccc" />
<circle cx="50" cy="0" r="1" fill="#ccc" />
<circle cx="100" cy="0" r="1" fill="#ccc" />
<circle cx="150" cy="0" r="1" fill="#ccc" />
<circle cx="200" cy="0" r="1" fill="#ccc" />
<circle cx="250" cy="0" r="1" fill="#ccc" />
<circle cx="300" cy="0" r="1" fill="#ccc" />
<circle cx="350" cy="0" r="1" fill="#ccc" />

<circle cx="0" cy="50" r="1" fill="#ccc" />
<circle cx="50" cy="50" r="1" fill="#ccc" />
<circle cx="100" cy="50" r="1" fill="#ccc" />
<circle cx="150" cy="50" r="1" fill="#ccc" />
<circle cx="200" cy="50" r="1" fill="#ccc" />
<circle cx="250" cy="50" r="1" fill="#ccc" />
<circle cx="300" cy="50" r="1" fill="#ccc" />
<circle cx="350" cy="50" r="1" fill="#ccc" />

<circle cx="0" cy="100" r="1" fill="#ccc" />
<circle cx="50" cy="100" r="1" fill="#ccc" />
<circle cx="100" cy="100" r="1" fill="#ccc" />
<circle cx="150" cy="100" r="1" fill="#ccc" />
<circle cx="200" cy="100" r="1" fill="#ccc" />
<circle cx="250" cy="100" r="1" fill="#ccc" />
<circle cx="300" cy="100" r="1" fill="#ccc" />
<circle cx="350" cy="100" r="1" fill="#ccc" />

<circle cx="0" cy="150" r="1" fill="#ccc" />
<circle cx="50" cy="150" r="1" fill="#ccc" />
<circle cx="100" cy="150" r="1" fill="#ccc" />
<circle cx="150" cy="150" r="1" fill="#ccc" />
<circle cx="200" cy="150" r="1" fill="#ccc" />
<circle cx="250" cy="150" r="1" fill="#ccc" />
<circle cx="300" cy="150" r="1" fill="#ccc" />
<circle cx="350" cy="150" r="1" fill="#ccc" />

<circle cx="0" cy="200" r="1" fill="#ccc" />
<circle cx="50" cy="200" r="1" fill="#ccc" />
<circle cx="100" cy="200" r="1" fill="#ccc" />
<circle cx="150" cy="200" r="1" fill="#ccc" />
<circle cx="200" cy="200" r="1" fill="#ccc" />
<circle cx="250" cy="200" r="1" fill="#ccc" />
<circle cx="300" cy="200" r="1" fill="#ccc" />
<circle cx="350" cy="200" r="1" fill="#ccc" />

<path d="M141.68 16.25c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.46 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zm117.14-14.5c-11.04 0-19 7.2-19 18s8.96 18 20 18c6.67 0 12.55-2.64 16.19-7.09l-7.65-4.42c-2.02 2.21-5.09 3.5-8.54 3.5-4.79 0-8.86-2.5-10.37-6.5h28.02c.22-1.12.35-2.28.35-3.5 0-10.79-7.96-17.99-19-17.99zm-9.45 14.5c1.25-3.99 4.67-6.5 9.45-6.5 4.79 0 8.21 2.51 9.45 6.5h-18.9zm-39.03 3.5c0 6 3.92 10 10 10 4.12 0 7.21-1.87 8.8-4.92l7.68 4.43c-3.18 5.3-9.14 8.49-16.48 8.49-11.05 0-19-7.2-19-18s7.96-18 19-18c7.34 0 13.29 3.19 16.48 8.49l-7.68 4.43c-1.59-3.05-4.68-4.92-8.8-4.92-6.07 0-10 4-10 10zm82.48-29v46h-9v-46h9zM37.59.25l36.95 64H.64l36.95-64zm92.38 5l-27.71 48-27.71-48h10.39l17.32 30 17.32-30h10.39zm58.91 12v9.69c-1-.29-2.06-.49-3.2-.49-5.81 0-10 4-10 10v14.8h-9v-34h9v9.2c0-5.08 5.91-9.2 13.2-9.2z"></path>

<text fill="url(#rainbow)" fontFamily="Licorice">
<tspan fontSize="30" x="100" y="125">Develop.</tspan>
<tspan fontSize="30" x="100" dy="30">Preview.</tspan>
<tspan fontSize="30" x="120" dy="30">Ship.</tspan>
</text>

</svg>);
}
37 changes: 25 additions & 12 deletions api/index.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,39 @@
import { IncomingMessage, ServerResponse } from 'http';
import { join } from 'path';
import { parseRequest } from './_lib/parser';
import { getScreenshot } from './_lib/chromium';
import { getHtml } from './_lib/template';
import { Template } from './_lib/template';
import { renderToStaticMarkup } from 'react-dom/server';
import { Canvas, GlobalFonts, Image, convertSVGTextToPath } from '@napi-rs/canvas'

const isDev = !process.env.AWS_REGION;
const isHtmlDebug = process.env.OG_HTML_DEBUG === '1';
GlobalFonts.registerFromPath(join(__dirname, '_fonts', 'Inter-Regular.ttf'));
GlobalFonts.registerFromPath(join(__dirname, '_fonts', 'Inter-Bold.ttf'));
GlobalFonts.registerFromPath(join(__dirname, '_fonts', 'Licorice-Regular.ttf'));

export default async function handler(req: IncomingMessage, res: ServerResponse) {
try {
const parsedReq = parseRequest(req);
const html = getHtml(parsedReq);
if (isHtmlDebug) {
res.setHeader('Content-Type', 'text/html');
res.end(html);
return;
}
const { fileType } = parsedReq;
const file = await getScreenshot(html, fileType, isDev);

const svgStart = Date.now()
const svg = renderToStaticMarkup(Template(parsedReq));
console.log('Rendered jsx to html in', Date.now() - svgStart, 'ms')

const canvasStart = Date.now()
const img = new Image()
img.src = convertSVGTextToPath(svg);
img.width = 1280;
img.height = 640;
const canvas = new Canvas(img.width, img.height);
const ctx = canvas.getContext('2d');
ctx.font = '30px Licorice';
ctx.drawImage(img, 0, 0, img.width, img.height);
const buffer = await canvas.encode(fileType as any);
console.log(`Rendered canvas to ${fileType} in`, Date.now() - canvasStart, 'ms')

res.statusCode = 200;
res.setHeader('Content-Type', `image/${fileType}`);
res.setHeader('Cache-Control', `public, immutable, no-transform, s-maxage=31536000, max-age=31536000`);
res.end(file);
res.end(buffer);
} catch (e) {
res.statusCode = 500;
res.setHeader('Content-Type', 'text/html');
13 changes: 6 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -7,15 +7,14 @@
"build": "tsc -p api/tsconfig.json && tsc -p web/tsconfig.json"
},
"dependencies": {
"chrome-aws-lambda": "7.0.0",
"marked": "2.0.0",
"puppeteer-core": "7.0.0",
"twemoji": "13.0.1"
"@napi-rs/canvas": "0.1.19",
"react": "17.0.2",
"react-dom": "17.0.2"
},
"devDependencies": {
"@types/marked": "1.2.2",
"@types/puppeteer": "5.4.3",
"@types/puppeteer-core": "5.4.0",
"@types/node": "14",
"@types/react": "17.0.38",
"@types/react-dom": "17.0.11",
"typescript": "4.1.5"
}
}
567 changes: 125 additions & 442 deletions yarn.lock

Large diffs are not rendered by default.