-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5edddde
Showing
26 changed files
with
1,211 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Local Netlify folder | ||
.netlify |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"deno.enable": true, | ||
"deno.unstable": true, | ||
"deno.importMap": ".netlify/edge-functions-import-map.json", | ||
"editor.defaultFormatter": "denoland.vscode-deno" | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
# Open Graph Image Generation | ||
|
||
Generate Open Graph images with Deno and Netlify Edge Functions. This is a fork | ||
of the awesome [`@vercel/og`](https://www.npmjs.com/package/@vercel/og), ported to run on Deno. | ||
|
||
## Usage | ||
|
||
To use on Netlify, create the following Edge Function: | ||
|
||
```jsx | ||
// /netlify/edge-functions/og.tsx | ||
|
||
import React from "https://esm.sh/[email protected]"; | ||
import { ImageResponse } from 'https://deno.land/x/og_edge/mod.ts' | ||
|
||
export default async function handler(req: Request) { | ||
return new ImageResponse( | ||
( | ||
<div | ||
style={{ | ||
width: '100%', | ||
height: '100%', | ||
display: 'flex', | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
fontSize: 128, | ||
background: 'lavender', | ||
}} | ||
> | ||
Hello! | ||
</div> | ||
) | ||
) | ||
} | ||
``` | ||
|
||
Then create a `netlify.toml` file with the following: | ||
|
||
```toml | ||
[[edge_functions]] | ||
function = "og" | ||
path = "/og" | ||
``` | ||
|
||
Then run `netlify dev` and load http://localhost:8888/og, the React element will be | ||
rendered and responded as a PNG. | ||
|
||
To use with the Deno CLI or Deno Deploy, create a file with the following: | ||
|
||
```tsx | ||
// /og.tsx | ||
|
||
import { serve } from "https://deno.land/[email protected]/http/server.ts"; | ||
import React from "https://esm.sh/[email protected]"; | ||
import { ImageResponse } from 'https://deno.land/x/og_edge/mod.ts' | ||
|
||
async function handler(req: Request) { | ||
return new ImageResponse( | ||
( | ||
<div | ||
style={{ | ||
width: '100%', | ||
height: '100%', | ||
display: 'flex', | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
fontSize: 128, | ||
background: 'lavender', | ||
}} | ||
> | ||
Hello! | ||
</div> | ||
) | ||
) | ||
} | ||
|
||
serve(handler); | ||
|
||
``` | ||
Then run `deno run --allow-net=:8000 --allow-env og.tsx` | ||
|
||
|
||
Read more about the API, supported features and check out the examples in the | ||
following sections. | ||
|
||
## API Reference | ||
|
||
The package exposes an `ImageResponse` constructor, with the following options | ||
available: | ||
|
||
```jsx | ||
import React from "https://esm.sh/[email protected]"; | ||
import { ImageResponse } from 'https://deno.land/x/og_edge/mod.ts' | ||
|
||
// ... | ||
new ImageResponse( | ||
element: ReactElement, | ||
options: { | ||
width?: number = 1200 | ||
height?: number = 630 | ||
emoji?: 'twemoji' | 'blobmoji' | 'noto' | 'openmoji' | 'fluent' | 'fluentFlat' = 'twemoji', | ||
fonts?: { | ||
name: string, | ||
data: ArrayBuffer, | ||
weight: number, | ||
style: 'normal' | 'italic' | ||
}[] | ||
debug?: boolean = false | ||
|
||
// Options that will be passed to the HTTP response | ||
status?: number = 200 | ||
statusText?: string | ||
headers?: Record<string, string> | ||
}, | ||
) | ||
``` | ||
|
||
When running in production, these headers will be included by `og_edge`: | ||
|
||
```jsx | ||
'content-type': 'image/png', | ||
'cache-control': 'public, immutable, no-transform, max-age=31536000', | ||
``` | ||
|
||
During development, the `cache-control: no-cache, no-store` header is used | ||
instead. | ||
|
||
### Supported HTML and CSS Features | ||
|
||
Please refer to | ||
[Satori’s documentation](https://github.com/vercel/satori#documentation) for a | ||
list of supported HTML and CSS features. | ||
|
||
By default, `og_edge` only has the Noto Sans font included. If you need to | ||
use other fonts, you can pass them in the `fonts` option. Check the **Custom | ||
Font** example below for more details. | ||
|
||
## Examples | ||
|
||
- Embed SVG Image · [_source_](/netlify/edge-functions/image-svg.tsx) · | ||
[_demo_](https://og-examples.netlify.app/api/image-svg) | ||
- Dynamic PNG Image Based on URL Queries · | ||
[_source_](/netlify/edge-functions/dynamic-image.tsx) · | ||
[_demo_](https://og-examples.netlify.app/api/dynamic-image?username=ascorbic) | ||
- Custom Font · [_source_](/netlify/edge-functions/custom-font.tsx) · | ||
[_demo_](https://og-examples.netlify.app/api/custom-font) | ||
- Emoji · [_source_](/netlify/edge-functions/emoji.tsx) · | ||
[_demo_](https://og-examples.netlify.app/api/emoji) | ||
- Languages · [_source_](/netlify/edge-functions/language.tsx) · | ||
[_demo_](https://og-examples.netlify.app/api/language) | ||
|
||
## Development / Contributing | ||
|
||
|
||
## Acknowledgements | ||
|
||
Basically all of the credit for this goes to [shuding](https://github.com/shuding). I just ported it to Deno and added a few tweaks. | ||
|
||
## License | ||
Mozilla Public Licence. Copyright Vercel and Matt Kane |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<!-- og image --> | ||
<meta property="og:image" content="/og/dynamic-image?username=ascorbic"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Hello OG Image</title> | ||
<style> | ||
body { | ||
/* default font stack */ | ||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<h1>Dynamic OG images</h1> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
|
||
const apis = { | ||
twemoji: (code: string) => | ||
"https://twemoji.maxcdn.com/v/latest/svg/" + code.toLowerCase() + ".svg", | ||
openmoji: "https://cdn.jsdelivr.net/npm/@svgmoji/[email protected]/svg/", | ||
blobmoji: "https://cdn.jsdelivr.net/npm/@svgmoji/[email protected]/svg/", | ||
noto: | ||
"https://cdn.jsdelivr.net/gh/svgmoji/svgmoji/packages/svgmoji__noto/svg/", | ||
fluent: (code: string) => | ||
"https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/" + | ||
code.toLowerCase() + "_color.svg", | ||
fluentFlat: (code: string) => | ||
"https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/" + | ||
code.toLowerCase() + "_flat.svg", | ||
}; | ||
|
||
export type EmojiType = keyof typeof apis; | ||
|
||
const n = String.fromCharCode(8205), O = /\uFE0F/g; | ||
|
||
export function loadEmoji( | ||
code: string, | ||
type?: EmojiType, | ||
): Promise<Response> { | ||
(!type || !apis[type]) && (type = "twemoji"); | ||
const A = apis[type]; | ||
return fetch( | ||
typeof A == "function" ? A(code) : `${A}${code.toUpperCase()}.svg`, | ||
); | ||
} | ||
|
||
export function getIconCode(char: string): string { | ||
return d(char.indexOf(n) < 0 ? char.replace(O, "") : char); | ||
} | ||
|
||
function d(j:string) { | ||
const t = [] | ||
let A = 0, k = 0 | ||
for (let E = 0; E < j.length;) { | ||
A = j.charCodeAt(E++), | ||
k | ||
? (t.push((65536 + (k - 55296 << 10) + (A - 56320)).toString(16)), | ||
k = 0) | ||
: 55296 <= A && A <= 56319 | ||
? k = A | ||
: t.push(A.toString(16)); | ||
} | ||
return t.join("-"); | ||
} |
Oops, something went wrong.