Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ascorbic committed Oct 15, 2022
0 parents commit 5edddde
Show file tree
Hide file tree
Showing 26 changed files with 1,211 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Local Netlify folder
.netlify
6 changes: 6 additions & 0 deletions .vscode/settings.json
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"
}
374 changes: 374 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

160 changes: 160 additions & 0 deletions README.md
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 added assets/TYPEWR__.TTF
Binary file not shown.
20 changes: 20 additions & 0 deletions demo/index.html
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>
49 changes: 49 additions & 0 deletions emoji.ts
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("-");
}
Loading

0 comments on commit 5edddde

Please sign in to comment.